gfx/thebes/gfxFT2Fonts.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     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 #if defined(MOZ_WIDGET_GTK)
     7 #include "gfxPlatformGtk.h"
     8 #define gfxToolkitPlatform gfxPlatformGtk
     9 #elif defined(MOZ_WIDGET_QT)
    10 #include <qfontinfo.h>
    11 #include "gfxQtPlatform.h"
    12 #define gfxToolkitPlatform gfxQtPlatform
    13 #elif defined(XP_WIN)
    14 #include "gfxWindowsPlatform.h"
    15 #define gfxToolkitPlatform gfxWindowsPlatform
    16 #elif defined(ANDROID)
    17 #include "gfxAndroidPlatform.h"
    18 #define gfxToolkitPlatform gfxAndroidPlatform
    19 #endif
    21 #include "gfxTypes.h"
    22 #include "gfxFT2Fonts.h"
    23 #include "gfxFT2FontBase.h"
    24 #include "gfxFT2Utils.h"
    25 #include "gfxFT2FontList.h"
    26 #include <locale.h>
    27 #include "gfxHarfBuzzShaper.h"
    28 #include "gfxGraphiteShaper.h"
    29 #include "nsGkAtoms.h"
    30 #include "nsTArray.h"
    31 #include "nsUnicodeRange.h"
    32 #include "nsCRT.h"
    33 #include "nsXULAppAPI.h"
    35 #include "prlog.h"
    36 #include "prinit.h"
    38 #include "mozilla/MemoryReporting.h"
    39 #include "mozilla/Preferences.h"
    40 #include "mozilla/gfx/2D.h"
    42 // rounding and truncation functions for a Freetype floating point number
    43 // (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
    44 // part and low 6 bits for the fractional part.
    45 #define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
    46 #define MOZ_FT_TRUNC(x) ((x) >> 6)
    47 #define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
    48         MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
    50 #ifndef ANDROID // not needed on Android, we use the generic gfxFontGroup
    51 /**
    52  * gfxFT2FontGroup
    53  */
    55 static PRLogModuleInfo *
    56 GetFontLog()
    57 {
    58     static PRLogModuleInfo *sLog;
    59     if (!sLog)
    60         sLog = PR_NewLogModule("ft2fonts");
    61     return sLog;
    62 }
    64 bool
    65 gfxFT2FontGroup::FontCallback(const nsAString& fontName,
    66                               const nsACString& genericName,
    67                               bool aUseFontSet,
    68                               void *closure)
    69 {
    70     nsTArray<nsString> *sa = static_cast<nsTArray<nsString>*>(closure);
    72     if (!fontName.IsEmpty() && !sa->Contains(fontName)) {
    73         sa->AppendElement(fontName);
    74 #ifdef DEBUG_pavlov
    75         printf(" - %s\n", NS_ConvertUTF16toUTF8(fontName).get());
    76 #endif
    77     }
    79     return true;
    80 }
    82 gfxFT2FontGroup::gfxFT2FontGroup(const nsAString& families,
    83                                  const gfxFontStyle *aStyle,
    84                                  gfxUserFontSet *aUserFontSet)
    85     : gfxFontGroup(families, aStyle, aUserFontSet)
    86 {
    87 #ifdef DEBUG_pavlov
    88     printf("Looking for %s\n", NS_ConvertUTF16toUTF8(families).get());
    89 #endif
    90     nsTArray<nsString> familyArray;
    91     ForEachFont(FontCallback, &familyArray);
    93     if (familyArray.Length() == 0) {
    94         nsAutoString prefFamilies;
    95         gfxToolkitPlatform::GetPlatform()->GetPrefFonts(aStyle->language, prefFamilies, nullptr);
    96         if (!prefFamilies.IsEmpty()) {
    97             ForEachFont(prefFamilies, aStyle->language, FontCallback, &familyArray);
    98         }
    99     }
   100     if (familyArray.Length() == 0) {
   101 #if defined(MOZ_WIDGET_QT) /* FIXME DFB */
   102         printf("failde to find a font. sadface\n");
   103         // We want to get rid of this entirely at some point, but first we need real lists of fonts.
   104         QFont defaultFont;
   105         QFontInfo fi (defaultFont);
   106         familyArray.AppendElement(nsDependentString(static_cast<const char16_t *>(fi.family().utf16())));
   107 #elif defined(MOZ_WIDGET_GTK)
   108         FcResult result;
   109         FcChar8 *family = nullptr;
   110         FcPattern* pat = FcPatternCreate();
   111         FcPattern *match = FcFontMatch(nullptr, pat, &result);
   112         if (match)
   113             FcPatternGetString(match, FC_FAMILY, 0, &family);
   114         if (family)
   115             familyArray.AppendElement(NS_ConvertUTF8toUTF16((char*)family));
   116 #elif defined(XP_WIN)
   117         HGDIOBJ hGDI = ::GetStockObject(SYSTEM_FONT);
   118         LOGFONTW logFont;
   119         if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont))
   120             familyArray.AppendElement(nsDependentString(logFont.lfFaceName));
   121 #elif defined(ANDROID)
   122         familyArray.AppendElement(NS_LITERAL_STRING("Droid Sans"));
   123         familyArray.AppendElement(NS_LITERAL_STRING("Roboto"));
   124 #else
   125 #error "Platform not supported"
   126 #endif
   127     }
   129     for (uint32_t i = 0; i < familyArray.Length(); i++) {
   130         nsRefPtr<gfxFT2Font> font = gfxFT2Font::GetOrMakeFont(familyArray[i], &mStyle);
   131         if (font) {
   132             mFonts.AppendElement(font);
   133         }
   134     }
   135     NS_ASSERTION(mFonts.Length() > 0, "We need at least one font in a fontgroup");
   136 }
   138 gfxFT2FontGroup::~gfxFT2FontGroup()
   139 {
   140 }
   142 gfxFontGroup *
   143 gfxFT2FontGroup::Copy(const gfxFontStyle *aStyle)
   144 {
   145     return new gfxFT2FontGroup(mFamilies, aStyle, nullptr);
   146 }
   148 // Helper function to return the leading UTF-8 character in a char pointer
   149 // as 32bit number. Also sets the length of the current character (i.e. the
   150 // offset to the next one) in the second argument
   151 uint32_t getUTF8CharAndNext(const uint8_t *aString, uint8_t *aLength)
   152 {
   153     *aLength = 1;
   154     if (aString[0] < 0x80) { // normal 7bit ASCII char
   155         return aString[0];
   156     }
   157     if ((aString[0] >> 5) == 6) { // two leading ones -> two bytes
   158         *aLength = 2;
   159         return ((aString[0] & 0x1F) << 6) + (aString[1] & 0x3F);
   160     }
   161     if ((aString[0] >> 4) == 14) { // three leading ones -> three bytes
   162         *aLength = 3;
   163         return ((aString[0] & 0x0F) << 12) + ((aString[1] & 0x3F) << 6) +
   164                (aString[2] & 0x3F);
   165     }
   166     if ((aString[0] >> 4) == 15) { // four leading ones -> four bytes
   167         *aLength = 4;
   168         return ((aString[0] & 0x07) << 18) + ((aString[1] & 0x3F) << 12) +
   169                ((aString[2] & 0x3F) <<  6) + (aString[3] & 0x3F);
   170     }
   171     return aString[0];
   172 }
   175 static bool
   176 AddFontNameToArray(const nsAString& aName,
   177                    const nsACString& aGenericName,
   178                    bool aUseFontSet,
   179                    void *aClosure)
   180 {
   181     if (!aName.IsEmpty()) {
   182         nsTArray<nsString> *list = static_cast<nsTArray<nsString> *>(aClosure);
   184         if (list->IndexOf(aName) == list->NoIndex)
   185             list->AppendElement(aName);
   186     }
   188     return true;
   189 }
   191 void
   192 gfxFT2FontGroup::FamilyListToArrayList(const nsString& aFamilies,
   193                                        nsIAtom *aLangGroup,
   194                                        nsTArray<nsRefPtr<gfxFontEntry> > *aFontEntryList)
   195 {
   196     nsAutoTArray<nsString, 15> fonts;
   197     ForEachFont(aFamilies, aLangGroup, AddFontNameToArray, &fonts);
   199     uint32_t len = fonts.Length();
   200     for (uint32_t i = 0; i < len; ++i) {
   201         const nsString& str = fonts[i];
   202         nsRefPtr<gfxFontEntry> fe = (gfxToolkitPlatform::GetPlatform()->FindFontEntry(str, mStyle));
   203         aFontEntryList->AppendElement(fe);
   204     }
   205 }
   207 void gfxFT2FontGroup::GetPrefFonts(nsIAtom *aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList)
   208 {
   209     NS_ASSERTION(aLangGroup, "aLangGroup is null");
   210     gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
   211     nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
   212     nsAutoCString key;
   213     aLangGroup->ToUTF8String(key);
   214     key.Append("-");
   215     key.AppendInt(GetStyle()->style);
   216     key.Append("-");
   217     key.AppendInt(GetStyle()->weight);
   218     if (!platform->GetPrefFontEntries(key, &fonts)) {
   219         nsString fontString;
   220         platform->GetPrefFonts(aLangGroup, fontString);
   221         if (fontString.IsEmpty())
   222             return;
   224         FamilyListToArrayList(fontString, aLangGroup, &fonts);
   226         platform->SetPrefFontEntries(key, fonts);
   227     }
   228     aFontEntryList.AppendElements(fonts);
   229 }
   231 static int32_t GetCJKLangGroupIndex(const char *aLangGroup) {
   232     int32_t i;
   233     for (i = 0; i < COUNT_OF_CJK_LANG_GROUP; i++) {
   234         if (!PL_strcasecmp(aLangGroup, sCJKLangGroup[i]))
   235             return i;
   236     }
   237     return -1;
   238 }
   240 // this function assigns to the array passed in.
   241 void gfxFT2FontGroup::GetCJKPrefFonts(nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList) {
   242     gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
   244     nsAutoCString key("x-internal-cjk-");
   245     key.AppendInt(mStyle.style);
   246     key.Append("-");
   247     key.AppendInt(mStyle.weight);
   249     if (!platform->GetPrefFontEntries(key, &aFontEntryList)) {
   250         NS_ENSURE_TRUE_VOID(Preferences::GetRootBranch());
   251         // Add the CJK pref fonts from accept languages, the order should be same order
   252         nsAdoptingCString list = Preferences::GetLocalizedCString("intl.accept_languages");
   253         if (!list.IsEmpty()) {
   254             const char kComma = ',';
   255             const char *p, *p_end;
   256             list.BeginReading(p);
   257             list.EndReading(p_end);
   258             while (p < p_end) {
   259                 while (nsCRT::IsAsciiSpace(*p)) {
   260                     if (++p == p_end)
   261                         break;
   262                 }
   263                 if (p == p_end)
   264                     break;
   265                 const char *start = p;
   266                 while (++p != p_end && *p != kComma)
   267                     /* nothing */ ;
   268                 nsAutoCString lang(Substring(start, p));
   269                 lang.CompressWhitespace(false, true);
   270                 int32_t index = GetCJKLangGroupIndex(lang.get());
   271                 if (index >= 0) {
   272                     nsCOMPtr<nsIAtom> atom = do_GetAtom(sCJKLangGroup[index]);
   273                     GetPrefFonts(atom, aFontEntryList);
   274                 }
   275                 p++;
   276             }
   277         }
   279         // Add the system locale
   280 #ifdef XP_WIN
   281         switch (::GetACP()) {
   282             case 932: GetPrefFonts(nsGkAtoms::Japanese, aFontEntryList); break;
   283             case 936: GetPrefFonts(nsGkAtoms::zh_cn, aFontEntryList); break;
   284             case 949: GetPrefFonts(nsGkAtoms::ko, aFontEntryList); break;
   285             // XXX Don't we need to append nsGkAtoms::zh_hk if the codepage is 950?
   286             case 950: GetPrefFonts(nsGkAtoms::zh_tw, aFontEntryList); break;
   287         }
   288 #else
   289         const char *ctype = setlocale(LC_CTYPE, nullptr);
   290         if (ctype) {
   291             if (!PL_strncasecmp(ctype, "ja", 2)) {
   292                 GetPrefFonts(nsGkAtoms::Japanese, aFontEntryList);
   293             } else if (!PL_strncasecmp(ctype, "zh_cn", 5)) {
   294                 GetPrefFonts(nsGkAtoms::zh_cn, aFontEntryList);
   295             } else if (!PL_strncasecmp(ctype, "zh_hk", 5)) {
   296                 GetPrefFonts(nsGkAtoms::zh_hk, aFontEntryList);
   297             } else if (!PL_strncasecmp(ctype, "zh_tw", 5)) {
   298                 GetPrefFonts(nsGkAtoms::zh_tw, aFontEntryList);
   299             } else if (!PL_strncasecmp(ctype, "ko", 2)) {
   300                 GetPrefFonts(nsGkAtoms::ko, aFontEntryList);
   301             }
   302         }
   303 #endif
   305         // last resort...
   306         GetPrefFonts(nsGkAtoms::Japanese, aFontEntryList);
   307         GetPrefFonts(nsGkAtoms::ko, aFontEntryList);
   308         GetPrefFonts(nsGkAtoms::zh_cn, aFontEntryList);
   309         GetPrefFonts(nsGkAtoms::zh_hk, aFontEntryList);
   310         GetPrefFonts(nsGkAtoms::zh_tw, aFontEntryList);
   312         platform->SetPrefFontEntries(key, aFontEntryList);
   313     }
   314 }
   316 already_AddRefed<gfxFT2Font>
   317 gfxFT2FontGroup::WhichFontSupportsChar(const nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList, uint32_t aCh)
   318 {
   319     for (uint32_t i = 0; i < aFontEntryList.Length(); i++) {
   320         gfxFontEntry *fe = aFontEntryList[i].get();
   321         if (fe->HasCharacter(aCh)) {
   322             nsRefPtr<gfxFT2Font> font =
   323                 gfxFT2Font::GetOrMakeFont(static_cast<FontEntry*>(fe), &mStyle);
   324             return font.forget();
   325         }
   326     }
   327     return nullptr;
   328 }
   330 already_AddRefed<gfxFont>
   331 gfxFT2FontGroup::WhichPrefFontSupportsChar(uint32_t aCh)
   332 {
   333     if (aCh > 0xFFFF)
   334         return nullptr;
   336     nsRefPtr<gfxFT2Font> selectedFont;
   338     // check out the style's language
   339     nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
   340     GetPrefFonts(mStyle.language, fonts);
   341     selectedFont = WhichFontSupportsChar(fonts, aCh);
   343     // otherwise search prefs
   344     if (!selectedFont) {
   345         uint32_t unicodeRange = FindCharUnicodeRange(aCh);
   347         /* special case CJK */
   348         if (unicodeRange == kRangeSetCJK) {
   349             if (PR_LOG_TEST(GetFontLog(), PR_LOG_DEBUG)) {
   350                 PR_LOG(GetFontLog(), PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
   351             }
   353             nsAutoTArray<nsRefPtr<gfxFontEntry>, 15> fonts;
   354             GetCJKPrefFonts(fonts);
   355             selectedFont = WhichFontSupportsChar(fonts, aCh);
   356         } else {
   357             nsIAtom *langGroup = LangGroupFromUnicodeRange(unicodeRange);
   358             if (langGroup) {
   359                 PR_LOG(GetFontLog(), PR_LOG_DEBUG, (" - Trying to find fonts for: %s", nsAtomCString(langGroup).get()));
   361                 nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
   362                 GetPrefFonts(langGroup, fonts);
   363                 selectedFont = WhichFontSupportsChar(fonts, aCh);
   364             }
   365         }
   366     }
   368     if (selectedFont) {
   369         nsRefPtr<gfxFont> f = static_cast<gfxFont*>(selectedFont.get());
   370         return f.forget();
   371     }
   373     return nullptr;
   374 }
   376 already_AddRefed<gfxFont>
   377 gfxFT2FontGroup::WhichSystemFontSupportsChar(uint32_t aCh, int32_t aRunScript)
   378 {
   379 #if defined(XP_WIN) || defined(ANDROID)
   380     FontEntry *fe = static_cast<FontEntry*>
   381         (gfxPlatformFontList::PlatformFontList()->
   382             SystemFindFontForChar(aCh, aRunScript, &mStyle));
   383     if (fe) {
   384         nsRefPtr<gfxFT2Font> f = gfxFT2Font::GetOrMakeFont(fe, &mStyle);
   385         nsRefPtr<gfxFont> font = f.get();
   386         return font.forget();
   387     }
   388 #else
   389     nsRefPtr<gfxFont> selectedFont;
   390     nsRefPtr<gfxFont> refFont = GetFontAt(0);
   391     gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
   392     selectedFont = platform->FindFontForChar(aCh, refFont);
   393     if (selectedFont)
   394         return selectedFont.forget();
   395 #endif
   396     return nullptr;
   397 }
   399 #endif // !ANDROID
   401 /**
   402  * gfxFT2Font
   403  */
   405 bool
   406 gfxFT2Font::ShapeText(gfxContext      *aContext,
   407                       const char16_t *aText,
   408                       uint32_t         aOffset,
   409                       uint32_t         aLength,
   410                       int32_t          aScript,
   411                       gfxShapedText   *aShapedText,
   412                       bool             aPreferPlatformShaping)
   413 {
   414     bool ok = false;
   416     if (FontCanSupportGraphite()) {
   417         if (gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
   418             if (!mGraphiteShaper) {
   419                 mGraphiteShaper = new gfxGraphiteShaper(this);
   420             }
   421             ok = mGraphiteShaper->ShapeText(aContext, aText,
   422                                             aOffset, aLength,
   423                                             aScript, aShapedText);
   424         }
   425     }
   427     if (!ok && gfxPlatform::GetPlatform()->UseHarfBuzzForScript(aScript)) {
   428         if (!mHarfBuzzShaper) {
   429             mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
   430         }
   431         ok = mHarfBuzzShaper->ShapeText(aContext, aText,
   432                                         aOffset, aLength,
   433                                         aScript, aShapedText);
   434     }
   436     if (!ok) {
   437         AddRange(aText, aOffset, aLength, aShapedText);
   438     }
   440     PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText);
   442     return true;
   443 }
   445 void
   446 gfxFT2Font::AddRange(const char16_t *aText, uint32_t aOffset,
   447                      uint32_t aLength, gfxShapedText *aShapedText)
   448 {
   449     const uint32_t appUnitsPerDevUnit = aShapedText->GetAppUnitsPerDevUnit();
   450     // we'll pass this in/figure it out dynamically, but at this point there can be only one face.
   451     gfxFT2LockedFace faceLock(this);
   452     FT_Face face = faceLock.get();
   454     gfxShapedText::CompressedGlyph *charGlyphs =
   455         aShapedText->GetCharacterGlyphs();
   457     const gfxFT2Font::CachedGlyphData *cgd = nullptr, *cgdNext = nullptr;
   459     FT_UInt spaceGlyph = GetSpaceGlyph();
   461     for (uint32_t i = 0; i < aLength; i++, aOffset++) {
   462         char16_t ch = aText[i];
   464         if (ch == 0) {
   465             // treat this null byte as a missing glyph, don't create a glyph for it
   466             aShapedText->SetMissingGlyph(aOffset, 0, this);
   467             continue;
   468         }
   470         NS_ASSERTION(!gfxFontGroup::IsInvalidChar(ch), "Invalid char detected");
   472         if (cgdNext) {
   473             cgd = cgdNext;
   474             cgdNext = nullptr;
   475         } else {
   476             cgd = GetGlyphDataForChar(ch);
   477         }
   479         FT_UInt gid = cgd->glyphIndex;
   480         int32_t advance = 0;
   482         if (gid == 0) {
   483             advance = -1; // trigger the missing glyphs case below
   484         } else {
   485             // find next character and its glyph -- in case they exist
   486             // and exist in the current font face -- to compute kerning
   487             char16_t chNext = 0;
   488             FT_UInt gidNext = 0;
   489             FT_Pos lsbDeltaNext = 0;
   491             if (FT_HAS_KERNING(face) && i + 1 < aLength) {
   492                 chNext = aText[i + 1];
   493                 if (chNext != 0) {
   494                     cgdNext = GetGlyphDataForChar(chNext);
   495                     gidNext = cgdNext->glyphIndex;
   496                     if (gidNext && gidNext != spaceGlyph)
   497                         lsbDeltaNext = cgdNext->lsbDelta;
   498                 }
   499             }
   501             advance = cgd->xAdvance;
   503             // now add kerning to the current glyph's advance
   504             if (chNext && gidNext) {
   505                 FT_Vector kerning; kerning.x = 0;
   506                 FT_Get_Kerning(face, gid, gidNext, FT_KERNING_DEFAULT, &kerning);
   507                 advance += kerning.x;
   508                 if (cgd->rsbDelta - lsbDeltaNext >= 32) {
   509                     advance -= 64;
   510                 } else if (cgd->rsbDelta - lsbDeltaNext < -32) {
   511                     advance += 64;
   512                 }
   513             }
   515             // convert 26.6 fixed point to app units
   516             // round rather than truncate to nearest pixel
   517             // because these advances are often scaled
   518             advance = ((advance * appUnitsPerDevUnit + 32) >> 6);
   519         }
   521         if (advance >= 0 &&
   522             gfxShapedText::CompressedGlyph::IsSimpleAdvance(advance) &&
   523             gfxShapedText::CompressedGlyph::IsSimpleGlyphID(gid)) {
   524             charGlyphs[aOffset].SetSimpleGlyph(advance, gid);
   525         } else if (gid == 0) {
   526             // gid = 0 only happens when the glyph is missing from the font
   527             aShapedText->SetMissingGlyph(aOffset, ch, this);
   528         } else {
   529             gfxTextRun::DetailedGlyph details;
   530             details.mGlyphID = gid;
   531             NS_ASSERTION(details.mGlyphID == gid,
   532                          "Seriously weird glyph ID detected!");
   533             details.mAdvance = advance;
   534             details.mXOffset = 0;
   535             details.mYOffset = 0;
   536             gfxShapedText::CompressedGlyph g;
   537             g.SetComplex(charGlyphs[aOffset].IsClusterStart(), true, 1);
   538             aShapedText->SetGlyphs(aOffset, g, &details);
   539         }
   540     }
   541 }
   543 gfxFT2Font::gfxFT2Font(cairo_scaled_font_t *aCairoFont,
   544                        FT2FontEntry *aFontEntry,
   545                        const gfxFontStyle *aFontStyle,
   546                        bool aNeedsBold)
   547     : gfxFT2FontBase(aCairoFont, aFontEntry, aFontStyle)
   548     , mCharGlyphCache(64)
   549 {
   550     NS_ASSERTION(mFontEntry, "Unable to find font entry for font.  Something is whack.");
   551     mApplySyntheticBold = aNeedsBold;
   552 }
   554 gfxFT2Font::~gfxFT2Font()
   555 {
   556 }
   558 /**
   559  * Look up the font in the gfxFont cache. If we don't find it, create one.
   560  * In either case, add a ref, append it to the aFonts array, and return it ---
   561  * except for OOM in which case we do nothing and return null.
   562  */
   563 already_AddRefed<gfxFT2Font>
   564 gfxFT2Font::GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle,
   565                           bool aNeedsBold)
   566 {
   567 #ifdef ANDROID
   568     FT2FontEntry *fe = static_cast<FT2FontEntry*>
   569         (gfxPlatformFontList::PlatformFontList()->
   570             FindFontForFamily(aName, aStyle, aNeedsBold));
   571 #else
   572     FT2FontEntry *fe = static_cast<FT2FontEntry*>
   573         (gfxToolkitPlatform::GetPlatform()->FindFontEntry(aName, *aStyle));
   574 #endif
   575     if (!fe) {
   576         NS_WARNING("Failed to find font entry for font!");
   577         return nullptr;
   578     }
   580     nsRefPtr<gfxFT2Font> font = GetOrMakeFont(fe, aStyle, aNeedsBold);
   581     return font.forget();
   582 }
   584 already_AddRefed<gfxFT2Font>
   585 gfxFT2Font::GetOrMakeFont(FT2FontEntry *aFontEntry, const gfxFontStyle *aStyle,
   586                           bool aNeedsBold)
   587 {
   588     nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aFontEntry, aStyle);
   589     if (!font) {
   590         cairo_scaled_font_t *scaledFont = aFontEntry->CreateScaledFont(aStyle);
   591         if (!scaledFont) {
   592             return nullptr;
   593         }
   594         font = new gfxFT2Font(scaledFont, aFontEntry, aStyle, aNeedsBold);
   595         cairo_scaled_font_destroy(scaledFont);
   596         if (!font) {
   597             return nullptr;
   598         }
   599         gfxFontCache::GetCache()->AddNew(font);
   600     }
   601     return font.forget().downcast<gfxFT2Font>();
   602 }
   604 void
   605 gfxFT2Font::FillGlyphDataForChar(uint32_t ch, CachedGlyphData *gd)
   606 {
   607     gfxFT2LockedFace faceLock(this);
   608     FT_Face face = faceLock.get();
   610     if (!face->charmap || face->charmap->encoding != FT_ENCODING_UNICODE) {
   611         FT_Select_Charmap(face, FT_ENCODING_UNICODE);
   612     }
   613     FT_UInt gid = FT_Get_Char_Index(face, ch);
   615     if (gid == 0) {
   616         // this font doesn't support this char!
   617         NS_ASSERTION(gid != 0, "We don't have a glyph, but font indicated that it supported this char in tables?");
   618         gd->glyphIndex = 0;
   619         return;
   620     }
   622     FT_Int32 flags = gfxPlatform::GetPlatform()->FontHintingEnabled() ?
   623                      FT_LOAD_DEFAULT :
   624                      (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
   625     FT_Error err = FT_Load_Glyph(face, gid, flags);
   627     if (err) {
   628         // hmm, this is weird, we failed to load a glyph that we had?
   629         NS_WARNING("Failed to load glyph that we got from Get_Char_index");
   631         gd->glyphIndex = 0;
   632         return;
   633     }
   635     gd->glyphIndex = gid;
   636     gd->lsbDelta = face->glyph->lsb_delta;
   637     gd->rsbDelta = face->glyph->rsb_delta;
   638     gd->xAdvance = face->glyph->advance.x;
   639 }
   641 void
   642 gfxFT2Font::AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   643                                    FontCacheSizes* aSizes) const
   644 {
   645     gfxFont::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
   646     aSizes->mFontInstances +=
   647         mCharGlyphCache.SizeOfExcludingThis(nullptr, aMallocSizeOf);
   648 }
   650 void
   651 gfxFT2Font::AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   652                                    FontCacheSizes* aSizes) const
   653 {
   654     aSizes->mFontInstances += aMallocSizeOf(this);
   655     AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
   656 }
   658 #ifdef USE_SKIA
   659 mozilla::TemporaryRef<mozilla::gfx::GlyphRenderingOptions>
   660 gfxFT2Font::GetGlyphRenderingOptions()
   661 {
   662   mozilla::gfx::FontHinting hinting;
   664   if (gfxPlatform::GetPlatform()->FontHintingEnabled()) {
   665     hinting = mozilla::gfx::FontHinting::NORMAL;
   666   } else {
   667     hinting = mozilla::gfx::FontHinting::NONE;
   668   }
   670   // We don't want to force the use of the autohinter over the font's built in hints
   671   return mozilla::gfx::Factory::CreateCairoGlyphRenderingOptions(hinting, false);
   672 }
   673 #endif

mercurial