gfx/thebes/gfxGDIFont.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: 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 #include "gfxGDIFont.h"
     8 #include "mozilla/MemoryReporting.h"
     9 #include "mozilla/WindowsVersion.h"
    11 #include "gfxGDIShaper.h"
    12 #include "gfxUniscribeShaper.h"
    13 #include "gfxHarfBuzzShaper.h"
    14 #include <algorithm>
    15 #include "gfxGraphiteShaper.h"
    16 #include "gfxWindowsPlatform.h"
    17 #include "gfxContext.h"
    18 #include "mozilla/Preferences.h"
    19 #include "nsUnicodeProperties.h"
    20 #include "gfxFontConstants.h"
    22 #include "cairo-win32.h"
    24 #define ROUND(x) floor((x) + 0.5)
    26 using namespace mozilla;
    27 using namespace mozilla::unicode;
    29 static inline cairo_antialias_t
    30 GetCairoAntialiasOption(gfxFont::AntialiasOption anAntialiasOption)
    31 {
    32     switch (anAntialiasOption) {
    33     default:
    34     case gfxFont::kAntialiasDefault:
    35         return CAIRO_ANTIALIAS_DEFAULT;
    36     case gfxFont::kAntialiasNone:
    37         return CAIRO_ANTIALIAS_NONE;
    38     case gfxFont::kAntialiasGrayscale:
    39         return CAIRO_ANTIALIAS_GRAY;
    40     case gfxFont::kAntialiasSubpixel:
    41         return CAIRO_ANTIALIAS_SUBPIXEL;
    42     }
    43 }
    45 gfxGDIFont::gfxGDIFont(GDIFontEntry *aFontEntry,
    46                        const gfxFontStyle *aFontStyle,
    47                        bool aNeedsBold,
    48                        AntialiasOption anAAOption)
    49     : gfxFont(aFontEntry, aFontStyle, anAAOption),
    50       mFont(nullptr),
    51       mFontFace(nullptr),
    52       mMetrics(nullptr),
    53       mSpaceGlyph(0),
    54       mNeedsBold(aNeedsBold)
    55 {
    56     if (FontCanSupportGraphite()) {
    57         mGraphiteShaper = new gfxGraphiteShaper(this);
    58     }
    59     if (FontCanSupportHarfBuzz()) {
    60         mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
    61     }
    62 }
    64 gfxGDIFont::~gfxGDIFont()
    65 {
    66     if (mScaledFont) {
    67         cairo_scaled_font_destroy(mScaledFont);
    68     }
    69     if (mFontFace) {
    70         cairo_font_face_destroy(mFontFace);
    71     }
    72     if (mFont) {
    73         ::DeleteObject(mFont);
    74     }
    75     delete mMetrics;
    76 }
    78 void
    79 gfxGDIFont::CreatePlatformShaper()
    80 {
    81     mPlatformShaper = new gfxGDIShaper(this);
    82 }
    84 gfxFont*
    85 gfxGDIFont::CopyWithAntialiasOption(AntialiasOption anAAOption)
    86 {
    87     return new gfxGDIFont(static_cast<GDIFontEntry*>(mFontEntry.get()),
    88                           &mStyle, mNeedsBold, anAAOption);
    89 }
    91 static bool
    92 UseUniscribe(gfxShapedText *aShapedText,
    93              char16ptr_t aText,
    94              uint32_t aLength)
    95 {
    96     uint32_t flags = aShapedText->Flags();
    97     bool useGDI;
    99     bool isXP = !IsVistaOrLater();
   101     // bug 561304 - Uniscribe bug produces bad positioning at certain
   102     // font sizes on XP, so default to GDI on XP using logic of 3.6
   104     useGDI = isXP &&
   105              (flags &
   106                (gfxTextRunFactory::TEXT_OPTIMIZE_SPEED | 
   107                 gfxTextRunFactory::TEXT_IS_RTL)
   108              ) == gfxTextRunFactory::TEXT_OPTIMIZE_SPEED;
   110     return !useGDI ||
   111         ScriptIsComplex(aText, aLength, SIC_COMPLEX) == S_OK;
   112 }
   114 bool
   115 gfxGDIFont::ShapeText(gfxContext      *aContext,
   116                       const char16_t *aText,
   117                       uint32_t         aOffset,
   118                       uint32_t         aLength,
   119                       int32_t          aScript,
   120                       gfxShapedText   *aShapedText,
   121                       bool             aPreferPlatformShaping)
   122 {
   123     if (!mMetrics) {
   124         Initialize();
   125     }
   126     if (!mIsValid) {
   127         NS_WARNING("invalid font! expect incorrect text rendering");
   128         return false;
   129     }
   131     bool ok = false;
   133     // Ensure the cairo font is set up, so there's no risk it'll fall back to
   134     // creating a "toy" font internally (see bug 544617).
   135     // We must check that this succeeded, otherwise we risk cairo creating the
   136     // wrong kind of font internally as a fallback (bug 744480).
   137     if (!SetupCairoFont(aContext)) {
   138         return false;
   139     }
   141     if (mGraphiteShaper && gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
   142         ok = mGraphiteShaper->ShapeText(aContext, aText,
   143                                         aOffset, aLength,
   144                                         aScript, aShapedText);
   145     }
   147     if (!ok && mHarfBuzzShaper) {
   148         if (gfxPlatform::GetPlatform()->UseHarfBuzzForScript(aScript) ||
   149             (!IsVistaOrLater() &&
   150              ScriptShapingType(aScript) == SHAPING_INDIC &&
   151              !Preferences::GetBool("gfx.font_rendering.winxp-indic-uniscribe",
   152                                    false))) {
   153             ok = mHarfBuzzShaper->ShapeText(aContext, aText, aOffset, aLength,
   154                                             aScript, aShapedText);
   155         }
   156     }
   158     if (!ok) {
   159         GDIFontEntry *fe = static_cast<GDIFontEntry*>(GetFontEntry());
   160         bool preferUniscribe =
   161             (!fe->IsTrueType() || fe->IsSymbolFont()) && !fe->mForceGDI;
   163         if (preferUniscribe || UseUniscribe(aShapedText, aText, aLength)) {
   164             // first try Uniscribe
   165             if (!mUniscribeShaper) {
   166                 mUniscribeShaper = new gfxUniscribeShaper(this);
   167             }
   169             ok = mUniscribeShaper->ShapeText(aContext, aText, aOffset, aLength,
   170                                              aScript, aShapedText);
   171             if (!ok) {
   172                 // fallback to GDI shaping
   173                 if (!mPlatformShaper) {
   174                     CreatePlatformShaper();
   175                 }
   177                 ok = mPlatformShaper->ShapeText(aContext, aText, aOffset,
   178                                                 aLength, aScript, aShapedText);
   179             }
   180         } else {
   181             // first use GDI
   182             if (!mPlatformShaper) {
   183                 CreatePlatformShaper();
   184             }
   186             ok = mPlatformShaper->ShapeText(aContext, aText, aOffset, aLength,
   187                                             aScript, aShapedText);
   188             if (!ok) {
   189                 // try Uniscribe if GDI failed
   190                 if (!mUniscribeShaper) {
   191                     mUniscribeShaper = new gfxUniscribeShaper(this);
   192                 }
   194                 // use Uniscribe shaping
   195                 ok = mUniscribeShaper->ShapeText(aContext, aText,
   196                                                  aOffset, aLength,
   197                                                  aScript, aShapedText);
   198             }
   199         }
   201 #if DEBUG
   202         if (!ok) {
   203             NS_ConvertUTF16toUTF8 name(GetName());
   204             char msg[256];
   206             sprintf(msg, 
   207                     "text shaping with both uniscribe and GDI failed for"
   208                     " font: %s",
   209                     name.get());
   210             NS_WARNING(msg);
   211         }
   212 #endif
   213     }
   215     PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText);
   217     return ok;
   218 }
   220 const gfxFont::Metrics&
   221 gfxGDIFont::GetMetrics()
   222 {
   223     if (!mMetrics) {
   224         Initialize();
   225     }
   226     return *mMetrics;
   227 }
   229 uint32_t
   230 gfxGDIFont::GetSpaceGlyph()
   231 {
   232     if (!mMetrics) {
   233         Initialize();
   234     }
   235     return mSpaceGlyph;
   236 }
   238 bool
   239 gfxGDIFont::SetupCairoFont(gfxContext *aContext)
   240 {
   241     if (!mMetrics) {
   242         Initialize();
   243     }
   244     if (!mScaledFont ||
   245         cairo_scaled_font_status(mScaledFont) != CAIRO_STATUS_SUCCESS) {
   246         // Don't cairo_set_scaled_font as that would propagate the error to
   247         // the cairo_t, precluding any further drawing.
   248         return false;
   249     }
   250     cairo_set_scaled_font(aContext->GetCairo(), mScaledFont);
   251     return true;
   252 }
   254 gfxFont::RunMetrics
   255 gfxGDIFont::Measure(gfxTextRun *aTextRun,
   256                     uint32_t aStart, uint32_t aEnd,
   257                     BoundingBoxType aBoundingBoxType,
   258                     gfxContext *aRefContext,
   259                     Spacing *aSpacing)
   260 {
   261     gfxFont::RunMetrics metrics =
   262         gfxFont::Measure(aTextRun, aStart, aEnd,
   263                          aBoundingBoxType, aRefContext, aSpacing);
   265     // if aBoundingBoxType is LOOSE_INK_EXTENTS
   266     // and the underlying cairo font may be antialiased,
   267     // we can't trust Windows to have considered all the pixels
   268     // so we need to add "padding" to the bounds.
   269     // (see bugs 475968, 439831, compare also bug 445087)
   270     if (aBoundingBoxType == LOOSE_INK_EXTENTS &&
   271         mAntialiasOption != kAntialiasNone &&
   272         metrics.mBoundingBox.width > 0) {
   273         metrics.mBoundingBox.x -= aTextRun->GetAppUnitsPerDevUnit();
   274         metrics.mBoundingBox.width += aTextRun->GetAppUnitsPerDevUnit() * 3;
   275     }
   277     return metrics;
   278 }
   280 #define OBLIQUE_SKEW_FACTOR 0.3
   282 void
   283 gfxGDIFont::Initialize()
   284 {
   285     NS_ASSERTION(!mMetrics, "re-creating metrics? this will leak");
   287     LOGFONTW logFont;
   289     // Figure out if we want to do synthetic oblique styling.
   290     GDIFontEntry* fe = static_cast<GDIFontEntry*>(GetFontEntry());
   291     bool wantFakeItalic =
   292         (mStyle.style & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE)) &&
   293         !fe->IsItalic();
   295     // If the font's family has an actual italic face (but font matching
   296     // didn't choose it), we have to use a cairo transform instead of asking
   297     // GDI to italicize, because that would use a different face and result
   298     // in a possible glyph ID mismatch between shaping and rendering.
   299     //
   300     // We use the mFamilyHasItalicFace flag in the entry in case of user fonts,
   301     // where the *CSS* family may not know about italic faces that are present
   302     // in the *GDI* family, and which GDI would use if we asked it to perform
   303     // the "italicization".
   304     bool useCairoFakeItalic = wantFakeItalic && fe->mFamilyHasItalicFace;
   306     if (mAdjustedSize == 0.0) {
   307         mAdjustedSize = mStyle.size;
   308         if (mStyle.sizeAdjust != 0.0 && mAdjustedSize > 0.0) {
   309             // to implement font-size-adjust, we first create the "unadjusted" font
   310             FillLogFont(logFont, mAdjustedSize,
   311                         wantFakeItalic && !useCairoFakeItalic);
   312             mFont = ::CreateFontIndirectW(&logFont);
   314             // initialize its metrics so we can calculate size adjustment
   315             Initialize();
   317             // calculate the properly adjusted size, and then proceed
   318             // to recreate mFont and recalculate metrics
   319             gfxFloat aspect = mMetrics->xHeight / mMetrics->emHeight;
   320             mAdjustedSize = mStyle.GetAdjustedSize(aspect);
   322             // delete the temporary font and metrics
   323             ::DeleteObject(mFont);
   324             mFont = nullptr;
   325             delete mMetrics;
   326             mMetrics = nullptr;
   327         }
   328     }
   330     // (bug 724231) for local user fonts, we don't use GDI's synthetic bold,
   331     // as it could lead to a different, incompatible face being used
   332     // but instead do our own multi-striking
   333     if (mNeedsBold && GetFontEntry()->IsLocalUserFont()) {
   334         mApplySyntheticBold = true;
   335     }
   337     // this may end up being zero
   338     mAdjustedSize = ROUND(mAdjustedSize);
   339     FillLogFont(logFont, mAdjustedSize, wantFakeItalic && !useCairoFakeItalic);
   340     mFont = ::CreateFontIndirectW(&logFont);
   342     mMetrics = new gfxFont::Metrics;
   343     ::memset(mMetrics, 0, sizeof(*mMetrics));
   345     AutoDC dc;
   346     SetGraphicsMode(dc.GetDC(), GM_ADVANCED);
   347     AutoSelectFont selectFont(dc.GetDC(), mFont);
   349     // Get font metrics if size > 0
   350     if (mAdjustedSize > 0.0) {
   352         OUTLINETEXTMETRIC oMetrics;
   353         TEXTMETRIC& metrics = oMetrics.otmTextMetrics;
   355         if (0 < GetOutlineTextMetrics(dc.GetDC(), sizeof(oMetrics), &oMetrics)) {
   356             mMetrics->superscriptOffset = (double)oMetrics.otmptSuperscriptOffset.y;
   357             // Some fonts have wrong sign on their subscript offset, bug 410917.
   358             mMetrics->subscriptOffset = fabs((double)oMetrics.otmptSubscriptOffset.y);
   359             mMetrics->strikeoutSize = (double)oMetrics.otmsStrikeoutSize;
   360             mMetrics->strikeoutOffset = (double)oMetrics.otmsStrikeoutPosition;
   361             mMetrics->underlineSize = (double)oMetrics.otmsUnderscoreSize;
   362             mMetrics->underlineOffset = (double)oMetrics.otmsUnderscorePosition;
   364             const MAT2 kIdentityMatrix = { {0, 1}, {0, 0}, {0, 0}, {0, 1} };
   365             GLYPHMETRICS gm;
   366             DWORD len = GetGlyphOutlineW(dc.GetDC(), char16_t('x'), GGO_METRICS, &gm, 0, nullptr, &kIdentityMatrix);
   367             if (len == GDI_ERROR || gm.gmptGlyphOrigin.y <= 0) {
   368                 // 56% of ascent, best guess for true type
   369                 mMetrics->xHeight =
   370                     ROUND((double)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
   371             } else {
   372                 mMetrics->xHeight = gm.gmptGlyphOrigin.y;
   373             }
   374             mMetrics->emHeight = metrics.tmHeight - metrics.tmInternalLeading;
   375             gfxFloat typEmHeight = (double)oMetrics.otmAscent - (double)oMetrics.otmDescent;
   376             mMetrics->emAscent = ROUND(mMetrics->emHeight * (double)oMetrics.otmAscent / typEmHeight);
   377             mMetrics->emDescent = mMetrics->emHeight - mMetrics->emAscent;
   378             if (oMetrics.otmEMSquare > 0) {
   379                 mFUnitsConvFactor = float(mAdjustedSize / oMetrics.otmEMSquare);
   380             }
   381         } else {
   382             // Make a best-effort guess at extended metrics
   383             // this is based on general typographic guidelines
   385             // GetTextMetrics can fail if the font file has been removed
   386             // or corrupted recently.
   387             BOOL result = GetTextMetrics(dc.GetDC(), &metrics);
   388             if (!result) {
   389                 NS_WARNING("Missing or corrupt font data, fasten your seatbelt");
   390                 mIsValid = false;
   391                 memset(mMetrics, 0, sizeof(*mMetrics));
   392                 return;
   393             }
   395             mMetrics->xHeight =
   396                 ROUND((float)metrics.tmAscent * DEFAULT_XHEIGHT_FACTOR);
   397             mMetrics->superscriptOffset = mMetrics->xHeight;
   398             mMetrics->subscriptOffset = mMetrics->xHeight;
   399             mMetrics->strikeoutSize = 1;
   400             mMetrics->strikeoutOffset = ROUND(mMetrics->xHeight * 0.5f); // 50% of xHeight
   401             mMetrics->underlineSize = 1;
   402             mMetrics->underlineOffset = -ROUND((float)metrics.tmDescent * 0.30f); // 30% of descent
   403             mMetrics->emHeight = metrics.tmHeight - metrics.tmInternalLeading;
   404             mMetrics->emAscent = metrics.tmAscent - metrics.tmInternalLeading;
   405             mMetrics->emDescent = metrics.tmDescent;
   406         }
   408         mMetrics->internalLeading = metrics.tmInternalLeading;
   409         mMetrics->externalLeading = metrics.tmExternalLeading;
   410         mMetrics->maxHeight = metrics.tmHeight;
   411         mMetrics->maxAscent = metrics.tmAscent;
   412         mMetrics->maxDescent = metrics.tmDescent;
   413         mMetrics->maxAdvance = metrics.tmMaxCharWidth;
   414         mMetrics->aveCharWidth = std::max<gfxFloat>(1, metrics.tmAveCharWidth);
   415         // The font is monospace when TMPF_FIXED_PITCH is *not* set!
   416         // See http://msdn2.microsoft.com/en-us/library/ms534202(VS.85).aspx
   417         if (!(metrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
   418             mMetrics->maxAdvance = mMetrics->aveCharWidth;
   419         }
   421         // Cache the width of a single space.
   422         SIZE size;
   423         GetTextExtentPoint32W(dc.GetDC(), L" ", 1, &size);
   424         mMetrics->spaceWidth = ROUND(size.cx);
   426         // Cache the width of digit zero.
   427         // XXX MSDN (http://msdn.microsoft.com/en-us/library/ms534223.aspx)
   428         // does not say what the failure modes for GetTextExtentPoint32 are -
   429         // is it safe to assume it will fail iff the font has no '0'?
   430         if (GetTextExtentPoint32W(dc.GetDC(), L"0", 1, &size)) {
   431             mMetrics->zeroOrAveCharWidth = ROUND(size.cx);
   432         } else {
   433             mMetrics->zeroOrAveCharWidth = mMetrics->aveCharWidth;
   434         }
   436         WORD glyph;
   437         DWORD ret = GetGlyphIndicesW(dc.GetDC(), L" ", 1, &glyph,
   438                                      GGI_MARK_NONEXISTING_GLYPHS);
   439         if (ret != GDI_ERROR && glyph != 0xFFFF) {
   440             mSpaceGlyph = glyph;
   441         }
   443         SanitizeMetrics(mMetrics, GetFontEntry()->mIsBadUnderlineFont);
   444     }
   446     if (IsSyntheticBold()) {
   447         mMetrics->aveCharWidth += GetSyntheticBoldOffset();
   448         mMetrics->maxAdvance += GetSyntheticBoldOffset();
   449     }
   451     mFontFace = cairo_win32_font_face_create_for_logfontw_hfont(&logFont,
   452                                                                 mFont);
   454     cairo_matrix_t sizeMatrix, ctm;
   455     cairo_matrix_init_identity(&ctm);
   456     cairo_matrix_init_scale(&sizeMatrix, mAdjustedSize, mAdjustedSize);
   458     if (useCairoFakeItalic) {
   459         // Skew the matrix to do fake italic if it wasn't already applied
   460         // via the LOGFONT
   461         double skewfactor = OBLIQUE_SKEW_FACTOR;
   462         cairo_matrix_t style;
   463         cairo_matrix_init(&style,
   464                           1,                //xx
   465                           0,                //yx
   466                           -1 * skewfactor,  //xy
   467                           1,                //yy
   468                           0,                //x0
   469                           0);               //y0
   470         cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
   471     }
   473     cairo_font_options_t *fontOptions = cairo_font_options_create();
   474     if (mAntialiasOption != kAntialiasDefault) {
   475         cairo_font_options_set_antialias(fontOptions,
   476             GetCairoAntialiasOption(mAntialiasOption));
   477     }
   478     mScaledFont = cairo_scaled_font_create(mFontFace, &sizeMatrix,
   479                                            &ctm, fontOptions);
   480     cairo_font_options_destroy(fontOptions);
   482     if (!mScaledFont ||
   483         cairo_scaled_font_status(mScaledFont) != CAIRO_STATUS_SUCCESS) {
   484 #ifdef DEBUG
   485         char warnBuf[1024];
   486         sprintf(warnBuf, "Failed to create scaled font: %s status: %d",
   487                 NS_ConvertUTF16toUTF8(mFontEntry->Name()).get(),
   488                 mScaledFont ? cairo_scaled_font_status(mScaledFont) : 0);
   489         NS_WARNING(warnBuf);
   490 #endif
   491         mIsValid = false;
   492     } else {
   493         mIsValid = true;
   494     }
   496 #if 0
   497     printf("Font: %p (%s) size: %f adjusted size: %f valid: %s\n", this,
   498            NS_ConvertUTF16toUTF8(GetName()).get(), mStyle.size, mAdjustedSize, (mIsValid ? "yes" : "no"));
   499     printf("    emHeight: %f emAscent: %f emDescent: %f\n", mMetrics->emHeight, mMetrics->emAscent, mMetrics->emDescent);
   500     printf("    maxAscent: %f maxDescent: %f maxAdvance: %f\n", mMetrics->maxAscent, mMetrics->maxDescent, mMetrics->maxAdvance);
   501     printf("    internalLeading: %f externalLeading: %f\n", mMetrics->internalLeading, mMetrics->externalLeading);
   502     printf("    spaceWidth: %f aveCharWidth: %f xHeight: %f\n", mMetrics->spaceWidth, mMetrics->aveCharWidth, mMetrics->xHeight);
   503     printf("    uOff: %f uSize: %f stOff: %f stSize: %f supOff: %f subOff: %f\n",
   504            mMetrics->underlineOffset, mMetrics->underlineSize, mMetrics->strikeoutOffset, mMetrics->strikeoutSize,
   505            mMetrics->superscriptOffset, mMetrics->subscriptOffset);
   506 #endif
   507 }
   509 void
   510 gfxGDIFont::FillLogFont(LOGFONTW& aLogFont, gfxFloat aSize,
   511                         bool aUseGDIFakeItalic)
   512 {
   513     GDIFontEntry *fe = static_cast<GDIFontEntry*>(GetFontEntry());
   515     uint16_t weight;
   516     if (fe->IsUserFont()) {
   517         if (fe->IsLocalUserFont()) {
   518             // for local user fonts, don't change the original weight
   519             // in the entry's logfont, because that could alter the
   520             // choice of actual face used (bug 724231)
   521             weight = 0;
   522         } else {
   523             // avoid GDI synthetic bold which occurs when weight
   524             // specified is >= font data weight + 200
   525             weight = mNeedsBold ? 700 : 200;
   526         }
   527     } else {
   528         weight = mNeedsBold ? 700 : fe->Weight();
   529     }
   531     fe->FillLogFont(&aLogFont, weight, aSize, 
   532                     (mAntialiasOption == kAntialiasSubpixel) ? true : false);
   534     // If GDI synthetic italic is wanted, force the lfItalic field to true
   535     if (aUseGDIFakeItalic) {
   536         aLogFont.lfItalic = 1;
   537     }
   538 }
   540 int32_t
   541 gfxGDIFont::GetGlyphWidth(gfxContext *aCtx, uint16_t aGID)
   542 {
   543     if (!mGlyphWidths) {
   544         mGlyphWidths = new nsDataHashtable<nsUint32HashKey,int32_t>(200);
   545     }
   547     int32_t width;
   548     if (mGlyphWidths->Get(aGID, &width)) {
   549         return width;
   550     }
   552     DCFromContext dc(aCtx);
   553     AutoSelectFont fs(dc, GetHFONT());
   555     int devWidth;
   556     if (GetCharWidthI(dc, aGID, 1, nullptr, &devWidth)) {
   557         // ensure width is positive, 16.16 fixed-point value
   558         width = (devWidth & 0x7fff) << 16;
   559         mGlyphWidths->Put(aGID, width);
   560         return width;
   561     }
   563     return -1;
   564 }
   566 void
   567 gfxGDIFont::AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   568                                    FontCacheSizes* aSizes) const
   569 {
   570     gfxFont::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
   571     aSizes->mFontInstances += aMallocSizeOf(mMetrics);
   572     if (mGlyphWidths) {
   573         aSizes->mFontInstances +=
   574             mGlyphWidths->SizeOfExcludingThis(nullptr, aMallocSizeOf);
   575     }
   576 }
   578 void
   579 gfxGDIFont::AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   580                                    FontCacheSizes* aSizes) const
   581 {
   582     aSizes->mFontInstances += aMallocSizeOf(this);
   583     AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
   584 }

mercurial