gfx/src/nsFont.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsFont.h"
     7 #include "gfxFont.h"                    // for gfxFontStyle
     8 #include "gfxFontConstants.h"           // for NS_FONT_KERNING_AUTO, etc
     9 #include "gfxFontFeatures.h"            // for gfxFontFeature, etc
    10 #include "gfxFontUtils.h"               // for TRUETYPE_TAG
    11 #include "nsCRT.h"                      // for nsCRT
    12 #include "nsDebug.h"                    // for NS_ASSERTION
    13 #include "nsISupports.h"
    14 #include "nsUnicharUtils.h"
    15 #include "nscore.h"                     // for char16_t
    16 #include "mozilla/ArrayUtils.h"
    17 #include "mozilla/gfx/2D.h"
    19 nsFont::nsFont(const char* aName, uint8_t aStyle, uint8_t aVariant,
    20                uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
    21                nscoord aSize)
    22 {
    23   NS_ASSERTION(aName && IsASCII(nsDependentCString(aName)),
    24                "Must only pass ASCII names here");
    25   name.AssignASCII(aName);
    26   style = aStyle;
    27   systemFont = false;
    28   variant = aVariant;
    29   weight = aWeight;
    30   stretch = aStretch;
    31   decorations = aDecoration;
    32   smoothing = NS_FONT_SMOOTHING_AUTO;
    33   size = aSize;
    34   sizeAdjust = 0.0;
    35   kerning = NS_FONT_KERNING_AUTO;
    36   synthesis = NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE;
    38   variantAlternates = 0;
    39   variantCaps = NS_FONT_VARIANT_CAPS_NORMAL;
    40   variantEastAsian = 0;
    41   variantLigatures = 0;
    42   variantNumeric = 0;
    43   variantPosition = NS_FONT_VARIANT_POSITION_NORMAL;
    44 }
    46 nsFont::nsFont(const nsSubstring& aName, uint8_t aStyle, uint8_t aVariant,
    47                uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
    48                nscoord aSize)
    49   : name(aName)
    50 {
    51   style = aStyle;
    52   systemFont = false;
    53   variant = aVariant;
    54   weight = aWeight;
    55   stretch = aStretch;
    56   decorations = aDecoration;
    57   smoothing = NS_FONT_SMOOTHING_AUTO;
    58   size = aSize;
    59   sizeAdjust = 0.0;
    60   kerning = NS_FONT_KERNING_AUTO;
    61   synthesis = NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE;
    63   variantAlternates = 0;
    64   variantCaps = NS_FONT_VARIANT_CAPS_NORMAL;
    65   variantEastAsian = 0;
    66   variantLigatures = 0;
    67   variantNumeric = 0;
    68   variantPosition = NS_FONT_VARIANT_POSITION_NORMAL;
    69 }
    71 nsFont::nsFont(const nsFont& aOther)
    72   : name(aOther.name)
    73 {
    74   style = aOther.style;
    75   systemFont = aOther.systemFont;
    76   variant = aOther.variant;
    77   weight = aOther.weight;
    78   stretch = aOther.stretch;
    79   decorations = aOther.decorations;
    80   smoothing = aOther.smoothing;
    81   size = aOther.size;
    82   sizeAdjust = aOther.sizeAdjust;
    83   kerning = aOther.kerning;
    84   synthesis = aOther.synthesis;
    85   fontFeatureSettings = aOther.fontFeatureSettings;
    86   languageOverride = aOther.languageOverride;
    87   variantAlternates = aOther.variantAlternates;
    88   variantCaps = aOther.variantCaps;
    89   variantEastAsian = aOther.variantEastAsian;
    90   variantLigatures = aOther.variantLigatures;
    91   variantNumeric = aOther.variantNumeric;
    92   variantPosition = aOther.variantPosition;
    93   alternateValues = aOther.alternateValues;
    94   featureValueLookup = aOther.featureValueLookup;
    95 }
    97 nsFont::nsFont()
    98 {
    99 }
   101 nsFont::~nsFont()
   102 {
   103 }
   105 bool nsFont::BaseEquals(const nsFont& aOther) const
   106 {
   107   if ((style == aOther.style) &&
   108       (systemFont == aOther.systemFont) &&
   109       (weight == aOther.weight) &&
   110       (stretch == aOther.stretch) &&
   111       (size == aOther.size) &&
   112       (sizeAdjust == aOther.sizeAdjust) &&
   113       name.Equals(aOther.name, nsCaseInsensitiveStringComparator()) &&
   114       (kerning == aOther.kerning) &&
   115       (synthesis == aOther.synthesis) &&
   116       (fontFeatureSettings == aOther.fontFeatureSettings) &&
   117       (languageOverride == aOther.languageOverride) &&
   118       (variantAlternates == aOther.variantAlternates) &&
   119       (variantCaps == aOther.variantCaps) &&
   120       (variantEastAsian == aOther.variantEastAsian) &&
   121       (variantLigatures == aOther.variantLigatures) &&
   122       (variantNumeric == aOther.variantNumeric) &&
   123       (variantPosition == aOther.variantPosition) &&
   124       (alternateValues == aOther.alternateValues) &&
   125       (featureValueLookup == aOther.featureValueLookup) &&
   126       (smoothing == aOther.smoothing)) {
   127     return true;
   128   }
   129   return false;
   130 }
   132 bool nsFont::Equals(const nsFont& aOther) const
   133 {
   134   if (BaseEquals(aOther) &&
   135       (variant == aOther.variant) &&
   136       (decorations == aOther.decorations)) {
   137     return true;
   138   }
   139   return false;
   140 }
   142 nsFont& nsFont::operator=(const nsFont& aOther)
   143 {
   144   name = aOther.name;
   145   style = aOther.style;
   146   systemFont = aOther.systemFont;
   147   variant = aOther.variant;
   148   weight = aOther.weight;
   149   stretch = aOther.stretch;
   150   decorations = aOther.decorations;
   151   smoothing = aOther.smoothing;
   152   size = aOther.size;
   153   sizeAdjust = aOther.sizeAdjust;
   154   kerning = aOther.kerning;
   155   synthesis = aOther.synthesis;
   156   fontFeatureSettings = aOther.fontFeatureSettings;
   157   languageOverride = aOther.languageOverride;
   158   variantAlternates = aOther.variantAlternates;
   159   variantCaps = aOther.variantCaps;
   160   variantEastAsian = aOther.variantEastAsian;
   161   variantLigatures = aOther.variantLigatures;
   162   variantNumeric = aOther.variantNumeric;
   163   variantPosition = aOther.variantPosition;
   164   alternateValues = aOther.alternateValues;
   165   featureValueLookup = aOther.featureValueLookup;
   166   return *this;
   167 }
   169 void
   170 nsFont::CopyAlternates(const nsFont& aOther)
   171 {
   172   variantAlternates = aOther.variantAlternates;
   173   alternateValues = aOther.alternateValues;
   174   featureValueLookup = aOther.featureValueLookup;
   175 }
   177 static bool IsGenericFontFamily(const nsString& aFamily)
   178 {
   179   uint8_t generic;
   180   nsFont::GetGenericID(aFamily, &generic);
   181   return generic != kGenericFont_NONE;
   182 }
   184 const char16_t kSingleQuote  = char16_t('\'');
   185 const char16_t kDoubleQuote  = char16_t('\"');
   186 const char16_t kComma        = char16_t(',');
   188 bool nsFont::EnumerateFamilies(nsFontFamilyEnumFunc aFunc, void* aData) const
   189 {
   190   const char16_t *p, *p_end;
   191   name.BeginReading(p);
   192   name.EndReading(p_end);
   193   nsAutoString family;
   195   while (p < p_end) {
   196     while (nsCRT::IsAsciiSpace(*p))
   197       if (++p == p_end)
   198         return true;
   200     bool generic;
   201     if (*p == kSingleQuote || *p == kDoubleQuote) {
   202       // quoted font family
   203       char16_t quoteMark = *p;
   204       if (++p == p_end)
   205         return true;
   206       const char16_t *nameStart = p;
   208       // XXX What about CSS character escapes?
   209       while (*p != quoteMark)
   210         if (++p == p_end)
   211           return true;
   213       family = Substring(nameStart, p);
   214       generic = false;
   216       while (++p != p_end && *p != kComma)
   217         /* nothing */ ;
   219     } else {
   220       // unquoted font family
   221       const char16_t *nameStart = p;
   222       while (++p != p_end && *p != kComma)
   223         /* nothing */ ;
   225       family = Substring(nameStart, p);
   226       family.CompressWhitespace(false, true);
   227       generic = IsGenericFontFamily(family);
   228     }
   230     if (!family.IsEmpty() && !(*aFunc)(family, generic, aData))
   231       return false;
   233     ++p; // may advance past p_end
   234   }
   236   return true;
   237 }
   239 // mapping from bitflag to font feature tag/value pair
   240 //
   241 // these need to be kept in sync with the constants listed
   242 // in gfxFontConstants.h (e.g. NS_FONT_VARIANT_EAST_ASIAN_JIS78)
   244 // NS_FONT_VARIANT_EAST_ASIAN_xxx values
   245 const gfxFontFeature eastAsianDefaults[] = {
   246   { TRUETYPE_TAG('j','p','7','8'), 1 },
   247   { TRUETYPE_TAG('j','p','8','3'), 1 },
   248   { TRUETYPE_TAG('j','p','9','0'), 1 },
   249   { TRUETYPE_TAG('j','p','0','4'), 1 },
   250   { TRUETYPE_TAG('s','m','p','l'), 1 },
   251   { TRUETYPE_TAG('t','r','a','d'), 1 },
   252   { TRUETYPE_TAG('f','w','i','d'), 1 },
   253   { TRUETYPE_TAG('p','w','i','d'), 1 },
   254   { TRUETYPE_TAG('r','u','b','y'), 1 }
   255 };
   257 static_assert(MOZ_ARRAY_LENGTH(eastAsianDefaults) ==
   258               eFeatureEastAsian_numFeatures,
   259               "eFeatureEastAsian_numFeatures should be correct");
   261 // NS_FONT_VARIANT_LIGATURES_xxx values
   262 const gfxFontFeature ligDefaults[] = {
   263   { TRUETYPE_TAG('l','i','g','a'), 0 },  // none value means all off
   264   { TRUETYPE_TAG('l','i','g','a'), 1 },
   265   { TRUETYPE_TAG('l','i','g','a'), 0 },
   266   { TRUETYPE_TAG('d','l','i','g'), 1 },
   267   { TRUETYPE_TAG('d','l','i','g'), 0 },
   268   { TRUETYPE_TAG('h','l','i','g'), 1 },
   269   { TRUETYPE_TAG('h','l','i','g'), 0 },
   270   { TRUETYPE_TAG('c','a','l','t'), 1 },
   271   { TRUETYPE_TAG('c','a','l','t'), 0 }
   272 };
   274 static_assert(MOZ_ARRAY_LENGTH(ligDefaults) ==
   275               eFeatureLigatures_numFeatures,
   276               "eFeatureLigatures_numFeatures should be correct");
   278 // NS_FONT_VARIANT_NUMERIC_xxx values
   279 const gfxFontFeature numericDefaults[] = {
   280   { TRUETYPE_TAG('l','n','u','m'), 1 },
   281   { TRUETYPE_TAG('o','n','u','m'), 1 },
   282   { TRUETYPE_TAG('p','n','u','m'), 1 },
   283   { TRUETYPE_TAG('t','n','u','m'), 1 },
   284   { TRUETYPE_TAG('f','r','a','c'), 1 },
   285   { TRUETYPE_TAG('a','f','r','c'), 1 },
   286   { TRUETYPE_TAG('z','e','r','o'), 1 },
   287   { TRUETYPE_TAG('o','r','d','n'), 1 }
   288 };
   290 static_assert(MOZ_ARRAY_LENGTH(numericDefaults) ==
   291               eFeatureNumeric_numFeatures,
   292               "eFeatureNumeric_numFeatures should be correct");
   294 static void
   295 AddFontFeaturesBitmask(uint32_t aValue, uint32_t aMin, uint32_t aMax,
   296                       const gfxFontFeature aFeatureDefaults[],
   297                       nsTArray<gfxFontFeature>& aFeaturesOut)
   299 {
   300   uint32_t i, m;
   302   for (i = 0, m = aMin; m <= aMax; i++, m <<= 1) {
   303     if (m & aValue) {
   304       const gfxFontFeature& feature = aFeatureDefaults[i];
   305       aFeaturesOut.AppendElement(feature);
   306     }
   307   }
   308 }
   310 void nsFont::AddFontFeaturesToStyle(gfxFontStyle *aStyle) const
   311 {
   312   // add in font-variant features
   313   gfxFontFeature setting;
   315   // -- kerning
   316   setting.mTag = TRUETYPE_TAG('k','e','r','n');
   317   switch (kerning) {
   318     case NS_FONT_KERNING_NONE:
   319       setting.mValue = 0;
   320       aStyle->featureSettings.AppendElement(setting);
   321       break;
   322     case NS_FONT_KERNING_NORMAL:
   323       setting.mValue = 1;
   324       aStyle->featureSettings.AppendElement(setting);
   325       break;
   326     default:
   327       // auto case implies use user agent default
   328       break;
   329   }
   331   // -- alternates
   332   if (variantAlternates & NS_FONT_VARIANT_ALTERNATES_HISTORICAL) {
   333     setting.mValue = 1;
   334     setting.mTag = TRUETYPE_TAG('h','i','s','t');
   335     aStyle->featureSettings.AppendElement(setting);
   336   }
   339   // -- copy font-specific alternate info into style
   340   //    (this will be resolved after font-matching occurs)
   341   aStyle->alternateValues.AppendElements(alternateValues);
   342   aStyle->featureValueLookup = featureValueLookup;
   344   // -- caps
   345   setting.mValue = 1;
   346   switch (variantCaps) {
   347     case NS_FONT_VARIANT_CAPS_ALLSMALL:
   348       setting.mTag = TRUETYPE_TAG('c','2','s','c');
   349       aStyle->featureSettings.AppendElement(setting);
   350       // fall through to the small-caps case
   351     case NS_FONT_VARIANT_CAPS_SMALLCAPS:
   352       setting.mTag = TRUETYPE_TAG('s','m','c','p');
   353       aStyle->featureSettings.AppendElement(setting);
   354       break;
   356     case NS_FONT_VARIANT_CAPS_ALLPETITE:
   357       setting.mTag = TRUETYPE_TAG('c','2','p','c');
   358       aStyle->featureSettings.AppendElement(setting);
   359       // fall through to the petite-caps case
   360     case NS_FONT_VARIANT_CAPS_PETITECAPS:
   361       setting.mTag = TRUETYPE_TAG('p','c','a','p');
   362       aStyle->featureSettings.AppendElement(setting);
   363       break;
   365     case NS_FONT_VARIANT_CAPS_TITLING:
   366       setting.mTag = TRUETYPE_TAG('t','i','t','l');
   367       aStyle->featureSettings.AppendElement(setting);
   368       break;
   370     case NS_FONT_VARIANT_CAPS_UNICASE:
   371       setting.mTag = TRUETYPE_TAG('u','n','i','c');
   372       aStyle->featureSettings.AppendElement(setting);
   373       break;
   375     default:
   376       break;
   377   }
   379   // -- east-asian
   380   if (variantEastAsian) {
   381     AddFontFeaturesBitmask(variantEastAsian,
   382                            NS_FONT_VARIANT_EAST_ASIAN_JIS78,
   383                            NS_FONT_VARIANT_EAST_ASIAN_RUBY,
   384                            eastAsianDefaults, aStyle->featureSettings);
   385   }
   387   // -- ligatures
   388   if (variantLigatures) {
   389     AddFontFeaturesBitmask(variantLigatures,
   390                            NS_FONT_VARIANT_LIGATURES_NONE,
   391                            NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL,
   392                            ligDefaults, aStyle->featureSettings);
   394     if (variantLigatures & NS_FONT_VARIANT_LIGATURES_COMMON) {
   395       // liga already enabled, need to enable clig also
   396       setting.mTag = TRUETYPE_TAG('c','l','i','g');
   397       setting.mValue = 1;
   398       aStyle->featureSettings.AppendElement(setting);
   399     } else if (variantLigatures & NS_FONT_VARIANT_LIGATURES_NO_COMMON) {
   400       // liga already disabled, need to disable clig also
   401       setting.mTag = TRUETYPE_TAG('c','l','i','g');
   402       setting.mValue = 0;
   403       aStyle->featureSettings.AppendElement(setting);
   404     } else if (variantLigatures & NS_FONT_VARIANT_LIGATURES_NONE) {
   405       // liga already disabled, need to disable dlig, hlig, calt, clig
   406       setting.mValue = 0;
   407       setting.mTag = TRUETYPE_TAG('d','l','i','g');
   408       aStyle->featureSettings.AppendElement(setting);
   409       setting.mTag = TRUETYPE_TAG('h','l','i','g');
   410       aStyle->featureSettings.AppendElement(setting);
   411       setting.mTag = TRUETYPE_TAG('c','a','l','t');
   412       aStyle->featureSettings.AppendElement(setting);
   413       setting.mTag = TRUETYPE_TAG('c','l','i','g');
   414       aStyle->featureSettings.AppendElement(setting);
   415     }
   416   }
   418   // -- numeric
   419   if (variantNumeric) {
   420     AddFontFeaturesBitmask(variantNumeric,
   421                            NS_FONT_VARIANT_NUMERIC_LINING,
   422                            NS_FONT_VARIANT_NUMERIC_ORDINAL,
   423                            numericDefaults, aStyle->featureSettings);
   424   }
   426   // -- position
   427   setting.mTag = 0;
   428   setting.mValue = 1;
   429   switch (variantPosition) {
   430     case NS_FONT_VARIANT_POSITION_SUPER:
   431       setting.mTag = TRUETYPE_TAG('s','u','p','s');
   432       aStyle->featureSettings.AppendElement(setting);
   433       break;
   435     case NS_FONT_VARIANT_POSITION_SUB:
   436       setting.mTag = TRUETYPE_TAG('s','u','b','s');
   437       aStyle->featureSettings.AppendElement(setting);
   438       break;
   440     default:
   441       break;
   442   }
   444   // add in features from font-feature-settings
   445   aStyle->featureSettings.AppendElements(fontFeatureSettings);
   447   // enable grayscale antialiasing for text
   448   if (smoothing == NS_FONT_SMOOTHING_GRAYSCALE) {
   449     aStyle->useGrayscaleAntialiasing = true;
   450   }
   451 }
   453 static bool FontEnumCallback(const nsString& aFamily, bool aGeneric, void *aData)
   454 {
   455   *((nsString*)aData) = aFamily;
   456   return false;
   457 }
   459 void nsFont::GetFirstFamily(nsString& aFamily) const
   460 {
   461   EnumerateFamilies(FontEnumCallback, &aFamily);
   462 }
   464 /*static*/
   465 void nsFont::GetGenericID(const nsString& aGeneric, uint8_t* aID)
   466 {
   467   *aID = kGenericFont_NONE;
   468   if (aGeneric.LowerCaseEqualsLiteral("-moz-fixed"))      *aID = kGenericFont_moz_fixed;
   469   else if (aGeneric.LowerCaseEqualsLiteral("serif"))      *aID = kGenericFont_serif;
   470   else if (aGeneric.LowerCaseEqualsLiteral("sans-serif")) *aID = kGenericFont_sans_serif;
   471   else if (aGeneric.LowerCaseEqualsLiteral("cursive"))    *aID = kGenericFont_cursive;
   472   else if (aGeneric.LowerCaseEqualsLiteral("fantasy"))    *aID = kGenericFont_fantasy;
   473   else if (aGeneric.LowerCaseEqualsLiteral("monospace"))  *aID = kGenericFont_monospace;
   474 }

mercurial