Bug 1567650 [wpt PR 17950] - [ElementTiming] Replace responseEnd with loadTime, a...
[gecko.git] / gfx / thebes / gfxMacFont.cpp
blobcc110373fd95f55967a1de53d3e1111806631b5c
1 /* -*- Mode: C++; tab-width: 20; 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 "gfxMacFont.h"
8 #include "mozilla/MemoryReporting.h"
9 #include "mozilla/Sprintf.h"
10 #include "mozilla/StaticPrefs_gfx.h"
12 #include "gfxCoreTextShaper.h"
13 #include <algorithm>
14 #include "gfxPlatformMac.h"
15 #include "gfxContext.h"
16 #include "gfxFontUtils.h"
17 #include "gfxMacPlatformFontList.h"
18 #include "gfxFontConstants.h"
19 #include "gfxTextRun.h"
20 #include "nsCocoaFeatures.h"
21 #include "cairo-quartz.h"
23 using namespace mozilla;
24 using namespace mozilla::gfx;
26 template <class T>
27 struct TagEquals {
28 bool Equals(const T& aIter, uint32_t aTag) const {
29 return aIter.mTag == aTag;
33 gfxMacFont::gfxMacFont(const RefPtr<UnscaledFontMac>& aUnscaledFont,
34 MacOSFontEntry* aFontEntry,
35 const gfxFontStyle* aFontStyle)
36 : gfxFont(aUnscaledFont, aFontEntry, aFontStyle),
37 mCGFont(nullptr),
38 mCTFont(nullptr),
39 mFontFace(nullptr),
40 mFontSmoothingBackgroundColor(aFontStyle->fontSmoothingBackgroundColor),
41 mVariationFont(aFontEntry->HasVariations()) {
42 mApplySyntheticBold = aFontStyle->NeedsSyntheticBold(aFontEntry);
44 if (mVariationFont) {
45 CGFontRef baseFont = aUnscaledFont->GetFont();
46 if (!baseFont) {
47 mIsValid = false;
48 return;
51 // Get the variation settings needed to instantiate the fontEntry
52 // for a particular fontStyle.
53 AutoTArray<gfxFontVariation, 4> vars;
54 aFontEntry->GetVariationsForStyle(vars, *aFontStyle);
56 // Because of a Core Text bug, we need to ensure that if the font has
57 // an 'opsz' axis, it is always explicitly set, and NOT to the font's
58 // default value. (See bug 1457417, bug 1478720.)
59 // We record the result of searching the font's axes in the font entry,
60 // so that this only has to be done by the first instance created for
61 // a given font resource.
62 const uint32_t kOpszTag = HB_TAG('o', 'p', 's', 'z');
63 const float kOpszFudgeAmount = 0.01f;
65 if (!aFontEntry->mCheckedForOpszAxis) {
66 aFontEntry->mCheckedForOpszAxis = true;
67 AutoTArray<gfxFontVariationAxis, 4> axes;
68 aFontEntry->GetVariationAxes(axes);
69 auto index = axes.IndexOf(kOpszTag, 0, TagEquals<gfxFontVariationAxis>());
70 if (index == axes.NoIndex) {
71 aFontEntry->mHasOpszAxis = false;
72 } else {
73 const auto& axis = axes[index];
74 aFontEntry->mHasOpszAxis = true;
75 aFontEntry->mOpszAxis = axis;
76 // Pick a slightly-adjusted version of the default that we'll
77 // use to work around Core Text's habit of ignoring any attempt
78 // to explicitly set the default value.
79 aFontEntry->mAdjustedDefaultOpsz =
80 axis.mDefaultValue == axis.mMinValue
81 ? axis.mDefaultValue + kOpszFudgeAmount
82 : axis.mDefaultValue - kOpszFudgeAmount;
86 // Add 'opsz' if not present, or tweak its value if it looks too close
87 // to the default (after clamping to the font's available range).
88 if (aFontEntry->mHasOpszAxis) {
89 auto index = vars.IndexOf(kOpszTag, 0, TagEquals<gfxFontVariation>());
90 if (index == vars.NoIndex) {
91 gfxFontVariation opsz{kOpszTag, aFontEntry->mAdjustedDefaultOpsz};
92 vars.AppendElement(opsz);
93 } else {
94 // Figure out a "safe" value that Core Text won't ignore.
95 auto& value = vars[index].mValue;
96 auto& axis = aFontEntry->mOpszAxis;
97 value = fmin(fmax(value, axis.mMinValue), axis.mMaxValue);
98 if (std::abs(value - axis.mDefaultValue) < kOpszFudgeAmount) {
99 value = aFontEntry->mAdjustedDefaultOpsz;
104 mCGFont = UnscaledFontMac::CreateCGFontWithVariations(
105 baseFont, vars.Length(), vars.Elements());
106 if (!mCGFont) {
107 ::CFRetain(baseFont);
108 mCGFont = baseFont;
110 } else {
111 mCGFont = aUnscaledFont->GetFont();
112 if (!mCGFont) {
113 mIsValid = false;
114 return;
116 ::CFRetain(mCGFont);
119 // InitMetrics will handle the sizeAdjust factor and set mAdjustedSize
120 InitMetrics();
121 if (!mIsValid) {
122 return;
125 mFontFace = cairo_quartz_font_face_create_for_cgfont(mCGFont);
127 cairo_status_t cairoerr = cairo_font_face_status(mFontFace);
128 if (cairoerr != CAIRO_STATUS_SUCCESS) {
129 mIsValid = false;
130 #ifdef DEBUG
131 char warnBuf[1024];
132 SprintfLiteral(warnBuf, "Failed to create Cairo font face: %s status: %d",
133 GetName().get(), cairoerr);
134 NS_WARNING(warnBuf);
135 #endif
136 return;
139 cairo_matrix_t sizeMatrix, ctm;
140 cairo_matrix_init_identity(&ctm);
141 cairo_matrix_init_scale(&sizeMatrix, mAdjustedSize, mAdjustedSize);
143 cairo_font_options_t* fontOptions = cairo_font_options_create();
145 // turn off font anti-aliasing based on user pref setting
146 if ((mAdjustedSize <=
147 (gfxFloat)gfxPlatformMac::GetPlatform()->GetAntiAliasingThreshold()) ||
148 // Turn off AA for Ahem for testing purposes when requested.
149 MOZ_UNLIKELY(StaticPrefs::gfx_font_ahem_antialias_none() &&
150 mFontEntry->FamilyName().EqualsLiteral("Ahem"))) {
151 cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_NONE);
152 mAntialiasOption = kAntialiasNone;
153 } else if (mStyle.useGrayscaleAntialiasing) {
154 cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_GRAY);
155 mAntialiasOption = kAntialiasGrayscale;
158 mScaledFont =
159 cairo_scaled_font_create(mFontFace, &sizeMatrix, &ctm, fontOptions);
160 cairo_font_options_destroy(fontOptions);
162 cairoerr = cairo_scaled_font_status(mScaledFont);
163 if (cairoerr != CAIRO_STATUS_SUCCESS) {
164 mIsValid = false;
165 #ifdef DEBUG
166 char warnBuf[1024];
167 SprintfLiteral(warnBuf, "Failed to create scaled font: %s status: %d",
168 GetName().get(), cairoerr);
169 NS_WARNING(warnBuf);
170 #endif
174 gfxMacFont::~gfxMacFont() {
175 if (mCGFont) {
176 ::CFRelease(mCGFont);
178 if (mCTFont) {
179 ::CFRelease(mCTFont);
181 if (mScaledFont) {
182 cairo_scaled_font_destroy(mScaledFont);
184 if (mFontFace) {
185 cairo_font_face_destroy(mFontFace);
189 bool gfxMacFont::ShapeText(DrawTarget* aDrawTarget, const char16_t* aText,
190 uint32_t aOffset, uint32_t aLength, Script aScript,
191 bool aVertical, RoundingFlags aRounding,
192 gfxShapedText* aShapedText) {
193 if (!mIsValid) {
194 NS_WARNING("invalid font! expect incorrect text rendering");
195 return false;
198 // Currently, we don't support vertical shaping via CoreText,
199 // so we ignore RequiresAATLayout if vertical is requested.
200 auto macFontEntry = static_cast<MacOSFontEntry*>(GetFontEntry());
201 if (macFontEntry->RequiresAATLayout() && !aVertical &&
202 StaticPrefs::gfx_font_rendering_coretext_enabled()) {
203 if (!mCoreTextShaper) {
204 mCoreTextShaper = MakeUnique<gfxCoreTextShaper>(this);
206 if (mCoreTextShaper->ShapeText(aDrawTarget, aText, aOffset, aLength,
207 aScript, aVertical, aRounding,
208 aShapedText)) {
209 PostShapingFixup(aDrawTarget, aText, aOffset, aLength, aVertical,
210 aShapedText);
211 if (GetFontEntry()->HasTrackingTable()) {
212 // Convert font size from device pixels back to CSS px
213 // to use in selecting tracking value
214 float trackSize = GetAdjustedSize() *
215 aShapedText->GetAppUnitsPerDevUnit() /
216 AppUnitsPerCSSPixel();
217 float tracking =
218 GetFontEntry()->TrackingForCSSPx(trackSize) * mFUnitsConvFactor;
219 // Applying tracking is a lot like the adjustment we do for
220 // synthetic bold: we want to apply between clusters, not to
221 // non-spacing glyphs within a cluster. So we can reuse that
222 // helper here.
223 aShapedText->AdjustAdvancesForSyntheticBold(tracking, aOffset, aLength);
225 return true;
229 return gfxFont::ShapeText(aDrawTarget, aText, aOffset, aLength, aScript,
230 aVertical, aRounding, aShapedText);
233 bool gfxMacFont::SetupCairoFont(DrawTarget* aDrawTarget) {
234 if (cairo_scaled_font_status(mScaledFont) != CAIRO_STATUS_SUCCESS) {
235 // Don't cairo_set_scaled_font as that would propagate the error to
236 // the cairo_t, precluding any further drawing.
237 return false;
239 cairo_set_scaled_font(gfxFont::RefCairo(aDrawTarget), mScaledFont);
240 return true;
243 gfxFont::RunMetrics gfxMacFont::Measure(const gfxTextRun* aTextRun,
244 uint32_t aStart, uint32_t aEnd,
245 BoundingBoxType aBoundingBoxType,
246 DrawTarget* aRefDrawTarget,
247 Spacing* aSpacing,
248 gfx::ShapedTextFlags aOrientation) {
249 gfxFont::RunMetrics metrics =
250 gfxFont::Measure(aTextRun, aStart, aEnd, aBoundingBoxType, aRefDrawTarget,
251 aSpacing, aOrientation);
253 // if aBoundingBoxType is not TIGHT_HINTED_OUTLINE_EXTENTS then we need to add
254 // a pixel column each side of the bounding box in case of antialiasing
255 // "bleed"
256 if (aBoundingBoxType != TIGHT_HINTED_OUTLINE_EXTENTS &&
257 metrics.mBoundingBox.width > 0) {
258 metrics.mBoundingBox.x -= aTextRun->GetAppUnitsPerDevUnit();
259 metrics.mBoundingBox.width += aTextRun->GetAppUnitsPerDevUnit() * 2;
262 return metrics;
265 void gfxMacFont::InitMetrics() {
266 mIsValid = false;
267 ::memset(&mMetrics, 0, sizeof(mMetrics));
269 uint32_t upem = 0;
271 // try to get unitsPerEm from sfnt head table, to avoid calling CGFont
272 // if possible (bug 574368) and because CGFontGetUnitsPerEm does not
273 // return the true value for OpenType/CFF fonts (it normalizes to 1000,
274 // which then leads to metrics errors when we read the 'hmtx' table to
275 // get glyph advances for HarfBuzz, see bug 580863)
276 CFDataRef headData =
277 ::CGFontCopyTableForTag(mCGFont, TRUETYPE_TAG('h', 'e', 'a', 'd'));
278 if (headData) {
279 if (size_t(::CFDataGetLength(headData)) >= sizeof(HeadTable)) {
280 const HeadTable* head =
281 reinterpret_cast<const HeadTable*>(::CFDataGetBytePtr(headData));
282 upem = head->unitsPerEm;
284 ::CFRelease(headData);
286 if (!upem) {
287 upem = ::CGFontGetUnitsPerEm(mCGFont);
290 if (upem < 16 || upem > 16384) {
291 // See http://www.microsoft.com/typography/otspec/head.htm
292 #ifdef DEBUG
293 char warnBuf[1024];
294 SprintfLiteral(warnBuf,
295 "Bad font metrics for: %s (invalid unitsPerEm value)",
296 mFontEntry->Name().get());
297 NS_WARNING(warnBuf);
298 #endif
299 return;
302 mAdjustedSize = std::max(mStyle.size, 1.0);
303 mFUnitsConvFactor = mAdjustedSize / upem;
305 // For CFF fonts, when scaling values read from CGFont* APIs, we need to
306 // use CG's idea of unitsPerEm, which may differ from the "true" value in
307 // the head table of the font (see bug 580863)
308 gfxFloat cgConvFactor;
309 if (static_cast<MacOSFontEntry*>(mFontEntry.get())->IsCFF()) {
310 cgConvFactor = mAdjustedSize / ::CGFontGetUnitsPerEm(mCGFont);
311 } else {
312 cgConvFactor = mFUnitsConvFactor;
315 // Try to read 'sfnt' metrics; for local, non-sfnt fonts ONLY, fall back to
316 // platform APIs. The InitMetrics...() functions will set mIsValid on success.
317 if (!InitMetricsFromSfntTables(mMetrics) &&
318 (!mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont())) {
319 InitMetricsFromPlatform();
321 if (!mIsValid) {
322 return;
325 if (mMetrics.xHeight == 0.0) {
326 mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * cgConvFactor;
329 if (mMetrics.capHeight == 0.0) {
330 mMetrics.capHeight = ::CGFontGetCapHeight(mCGFont) * cgConvFactor;
333 if (mStyle.sizeAdjust > 0.0 && mStyle.size > 0.0 && mMetrics.xHeight > 0.0) {
334 // apply font-size-adjust, and recalculate metrics
335 gfxFloat aspect = mMetrics.xHeight / mStyle.size;
336 mAdjustedSize = mStyle.GetAdjustedSize(aspect);
337 mFUnitsConvFactor = mAdjustedSize / upem;
338 if (static_cast<MacOSFontEntry*>(mFontEntry.get())->IsCFF()) {
339 cgConvFactor = mAdjustedSize / ::CGFontGetUnitsPerEm(mCGFont);
340 } else {
341 cgConvFactor = mFUnitsConvFactor;
343 mMetrics.xHeight = 0.0;
344 if (!InitMetricsFromSfntTables(mMetrics) &&
345 (!mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont())) {
346 InitMetricsFromPlatform();
348 if (!mIsValid) {
349 // this shouldn't happen, as we succeeded earlier before applying
350 // the size-adjust factor! But check anyway, for paranoia's sake.
351 return;
353 if (mMetrics.xHeight == 0.0) {
354 mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * cgConvFactor;
358 // Once we reach here, we've got basic metrics and set mIsValid = TRUE;
359 // there should be no further points of actual failure in InitMetrics().
360 // (If one is introduced, be sure to reset mIsValid to FALSE!)
362 mMetrics.emHeight = mAdjustedSize;
364 // Measure/calculate additional metrics, independent of whether we used
365 // the tables directly or ATS metrics APIs
367 CFDataRef cmap =
368 ::CGFontCopyTableForTag(mCGFont, TRUETYPE_TAG('c', 'm', 'a', 'p'));
370 uint32_t glyphID;
371 if (mMetrics.aveCharWidth <= 0) {
372 mMetrics.aveCharWidth = GetCharWidth(cmap, 'x', &glyphID, cgConvFactor);
373 if (glyphID == 0) {
374 // we didn't find 'x', so use maxAdvance rather than zero
375 mMetrics.aveCharWidth = mMetrics.maxAdvance;
378 if (IsSyntheticBold()) {
379 mMetrics.aveCharWidth += GetSyntheticBoldOffset();
380 mMetrics.maxAdvance += GetSyntheticBoldOffset();
383 mMetrics.spaceWidth = GetCharWidth(cmap, ' ', &glyphID, cgConvFactor);
384 if (glyphID == 0) {
385 // no space glyph?!
386 mMetrics.spaceWidth = mMetrics.aveCharWidth;
388 mSpaceGlyph = glyphID;
390 mMetrics.zeroWidth = GetCharWidth(cmap, '0', &glyphID, cgConvFactor);
391 if (glyphID == 0) {
392 mMetrics.zeroWidth = -1.0; // indicates not found
395 if (cmap) {
396 ::CFRelease(cmap);
399 CalculateDerivedMetrics(mMetrics);
401 SanitizeMetrics(&mMetrics, mFontEntry->mIsBadUnderlineFont);
403 #if 0
404 fprintf (stderr, "Font: %p (%s) size: %f\n", this,
405 NS_ConvertUTF16toUTF8(GetName()).get(), mStyle.size);
406 // fprintf (stderr, " fbounds.origin.x %f y %f size.width %f height %f\n", fbounds.origin.x, fbounds.origin.y, fbounds.size.width, fbounds.size.height);
407 fprintf (stderr, " emHeight: %f emAscent: %f emDescent: %f\n", mMetrics.emHeight, mMetrics.emAscent, mMetrics.emDescent);
408 fprintf (stderr, " maxAscent: %f maxDescent: %f maxAdvance: %f\n", mMetrics.maxAscent, mMetrics.maxDescent, mMetrics.maxAdvance);
409 fprintf (stderr, " internalLeading: %f externalLeading: %f\n", mMetrics.internalLeading, mMetrics.externalLeading);
410 fprintf (stderr, " spaceWidth: %f aveCharWidth: %f xHeight: %f capHeight: %f\n", mMetrics.spaceWidth, mMetrics.aveCharWidth, mMetrics.xHeight, mMetrics.capHeight);
411 fprintf (stderr, " uOff: %f uSize: %f stOff: %f stSize: %f\n", mMetrics.underlineOffset, mMetrics.underlineSize, mMetrics.strikeoutOffset, mMetrics.strikeoutSize);
412 #endif
415 gfxFloat gfxMacFont::GetCharWidth(CFDataRef aCmap, char16_t aUniChar,
416 uint32_t* aGlyphID, gfxFloat aConvFactor) {
417 CGGlyph glyph = 0;
419 if (aCmap) {
420 glyph = gfxFontUtils::MapCharToGlyph(::CFDataGetBytePtr(aCmap),
421 ::CFDataGetLength(aCmap), aUniChar);
424 if (aGlyphID) {
425 *aGlyphID = glyph;
428 if (glyph) {
429 int advance;
430 if (::CGFontGetGlyphAdvances(mCGFont, &glyph, 1, &advance)) {
431 return advance * aConvFactor;
435 return 0;
438 /* static */
439 CTFontRef gfxMacFont::CreateCTFontFromCGFontWithVariations(
440 CGFontRef aCGFont, CGFloat aSize, bool aInstalledFont,
441 CTFontDescriptorRef aFontDesc) {
442 // Avoid calling potentially buggy variation APIs on pre-Sierra macOS
443 // versions (see bug 1331683).
445 // And on HighSierra, CTFontCreateWithGraphicsFont properly carries over
446 // variation settings from the CGFont to CTFont, so we don't need to do
447 // the extra work here -- and this seems to avoid Core Text crashiness
448 // seen in bug 1454094.
450 // However, for installed fonts it seems we DO need to copy the variations
451 // explicitly even on 10.13, otherwise fonts fail to render (as in bug
452 // 1455494) when non-default values are used. Fortunately, the crash
453 // mentioned above occurs with data fonts, not (AFAICT) with system-
454 // installed fonts.
456 // So we only need to do this "the hard way" on Sierra, and on HighSierra
457 // for system-installed fonts; in other cases just let the standard CTFont
458 // function do its thing.
460 // NOTE in case this ever needs further adjustment: there is similar logic
461 // in four places in the tree (sadly):
462 // CreateCTFontFromCGFontWithVariations in gfxMacFont.cpp
463 // CreateCTFontFromCGFontWithVariations in ScaledFontMac.cpp
464 // CreateCTFontFromCGFontWithVariations in cairo-quartz-font.c
465 // ctfont_create_exact_copy in SkFontHost_mac.cpp
467 CTFontRef ctFont;
468 if (nsCocoaFeatures::OnSierraExactly() ||
469 (aInstalledFont && nsCocoaFeatures::OnHighSierraOrLater())) {
470 CFDictionaryRef variations = ::CGFontCopyVariations(aCGFont);
471 if (variations) {
472 CFDictionaryRef varAttr = ::CFDictionaryCreate(
473 nullptr, (const void**)&kCTFontVariationAttribute,
474 (const void**)&variations, 1, &kCFTypeDictionaryKeyCallBacks,
475 &kCFTypeDictionaryValueCallBacks);
476 ::CFRelease(variations);
478 CTFontDescriptorRef varDesc =
479 aFontDesc
480 ? ::CTFontDescriptorCreateCopyWithAttributes(aFontDesc, varAttr)
481 : ::CTFontDescriptorCreateWithAttributes(varAttr);
482 ::CFRelease(varAttr);
484 ctFont = ::CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, varDesc);
485 ::CFRelease(varDesc);
486 } else {
487 ctFont =
488 ::CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, aFontDesc);
490 } else {
491 ctFont = ::CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, aFontDesc);
494 return ctFont;
497 int32_t gfxMacFont::GetGlyphWidth(uint16_t aGID) {
498 if (mVariationFont) {
499 // Avoid a potential Core Text crash (bug 1450209) by using
500 // CoreGraphics glyph advance API. This is inferior for 'sbix'
501 // fonts, but those won't have variations, so it's OK.
502 int cgAdvance;
503 if (::CGFontGetGlyphAdvances(mCGFont, &aGID, 1, &cgAdvance)) {
504 return cgAdvance * mFUnitsConvFactor * 0x10000;
508 if (!mCTFont) {
509 bool isInstalledFont =
510 !mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont();
511 mCTFont = CreateCTFontFromCGFontWithVariations(mCGFont, mAdjustedSize,
512 isInstalledFont);
513 if (!mCTFont) { // shouldn't happen, but let's be safe
514 NS_WARNING("failed to create CTFontRef to measure glyph width");
515 return 0;
519 CGSize advance;
520 ::CTFontGetAdvancesForGlyphs(mCTFont, kCTFontDefaultOrientation, &aGID,
521 &advance, 1);
522 return advance.width * 0x10000;
525 // Try to initialize font metrics via platform APIs (CG/CT),
526 // and set mIsValid = TRUE on success.
527 // We ONLY call this for local (platform) fonts that are not sfnt format;
528 // for sfnts, including ALL downloadable fonts, we prefer to use
529 // InitMetricsFromSfntTables and avoid platform APIs.
530 void gfxMacFont::InitMetricsFromPlatform() {
531 CTFontRef ctFont =
532 ::CTFontCreateWithGraphicsFont(mCGFont, mAdjustedSize, nullptr, nullptr);
533 if (!ctFont) {
534 return;
537 mMetrics.underlineOffset = ::CTFontGetUnderlinePosition(ctFont);
538 mMetrics.underlineSize = ::CTFontGetUnderlineThickness(ctFont);
540 mMetrics.externalLeading = ::CTFontGetLeading(ctFont);
542 mMetrics.maxAscent = ::CTFontGetAscent(ctFont);
543 mMetrics.maxDescent = ::CTFontGetDescent(ctFont);
545 // this is not strictly correct, but neither CTFont nor CGFont seems to
546 // provide maxAdvance, unless we were to iterate over all the glyphs
547 // (which isn't worth the cost here)
548 CGRect r = ::CTFontGetBoundingBox(ctFont);
549 mMetrics.maxAdvance = r.size.width;
551 // aveCharWidth is also not provided, so leave it at zero
552 // (fallback code in gfxMacFont::InitMetrics will then try measuring 'x');
553 // this could lead to less-than-"perfect" text field sizing when width is
554 // specified as a number of characters, and the font in use is a non-sfnt
555 // legacy font, but that's a sufficiently obscure edge case that we can
556 // ignore the potential discrepancy.
557 mMetrics.aveCharWidth = 0;
559 mMetrics.xHeight = ::CTFontGetXHeight(ctFont);
560 mMetrics.capHeight = ::CTFontGetCapHeight(ctFont);
562 ::CFRelease(ctFont);
564 mIsValid = true;
567 already_AddRefed<ScaledFont> gfxMacFont::GetScaledFont(DrawTarget* aTarget) {
568 if (!mAzureScaledFont) {
569 mAzureScaledFont = Factory::CreateScaledFontForMacFont(
570 GetCGFontRef(), GetUnscaledFont(), GetAdjustedSize(),
571 Color::FromABGR(mFontSmoothingBackgroundColor),
572 !mStyle.useGrayscaleAntialiasing, IsSyntheticBold());
573 if (!mAzureScaledFont) {
574 return nullptr;
576 InitializeScaledFont();
577 mAzureScaledFont->SetCairoScaledFont(mScaledFont);
580 RefPtr<ScaledFont> scaledFont(mAzureScaledFont);
581 return scaledFont.forget();
584 void gfxMacFont::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
585 FontCacheSizes* aSizes) const {
586 gfxFont::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
587 // mCGFont is shared with the font entry, so not counted here;
588 // and we don't have APIs to measure the cairo mFontFace object
591 void gfxMacFont::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
592 FontCacheSizes* aSizes) const {
593 aSizes->mFontInstances += aMallocSizeOf(this);
594 AddSizeOfExcludingThis(aMallocSizeOf, aSizes);