CTFontRef SimpleFontData::getCTFont() const { if (getNSFont()) return toCTFontRef(getNSFont()); if (!m_CTFont) m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_platformData.cgFont(), m_platformData.size(), 0, 0)); return m_CTFont.get(); }
SkTypeface* ScaledFontMac::GetSkTypeface() { if (!mTypeface) { CTFontRef fontFace = CTFontCreateWithGraphicsFont(mFont, mSize, NULL, NULL); mTypeface = SkCreateTypefaceFromCTFont(fontFace); CFRelease(fontFace); } return mTypeface; }
SkTypeface* ScaledFontMac::GetSkTypeface() { if (!mTypeface) { if (mCTFont) { mTypeface = SkCreateTypefaceFromCTFont(mCTFont); } else { CTFontRef fontFace = CTFontCreateWithGraphicsFont(mFont, mSize, nullptr, nullptr); mTypeface = SkCreateTypefaceFromCTFont(fontFace); CFRelease(fontFace); } } return mTypeface; }
ScaledFontMac::ScaledFontMac(CGFontRef aFont, Float aSize) : ScaledFontBase(aSize) { if (!sSymbolLookupDone) { CTFontDrawGlyphsPtr = (CTFontDrawGlyphsFuncT*)dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs"); sSymbolLookupDone = true; } // XXX: should we be taking a reference mFont = CGFontRetain(aFont); if (CTFontDrawGlyphsPtr != nullptr) { // only create mCTFont if we're going to be using the CTFontDrawGlyphs API mCTFont = CTFontCreateWithGraphicsFont(aFont, aSize, nullptr, nullptr); } else { mCTFont = nullptr; } }
static cairo_int_status_t _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font, cairo_scaled_glyph_t *scaled_glyph) { cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); CGAffineTransform textMatrix; CGPathRef glyphPath; CTFontRef ctFont; cairo_path_fixed_t *path; if (glyph == INVALID_GLYPH) { _cairo_scaled_glyph_set_path (scaled_glyph, &font->base, _cairo_path_fixed_create()); return CAIRO_STATUS_SUCCESS; } /* scale(1,-1) * font->base.scale */ textMatrix = CGAffineTransformMake (font->base.scale.xx, font->base.scale.yx, -font->base.scale.xy, -font->base.scale.yy, 0, 0); // glyphPath = CGFontGetGlyphPathPtr (font_face->cgFont, &textMatrix, 0, glyph); ctFont = CTFontCreateWithGraphicsFont (font_face->cgFont, 0.0, NULL, NULL); glyphPath = CTFontCreatePathForGlyph (ctFont, glyph, &textMatrix); CFRelease (ctFont); if (!glyphPath) return CAIRO_INT_STATUS_UNSUPPORTED; path = _cairo_path_fixed_create (); if (!path) { CGPathRelease (glyphPath); return _cairo_error(CAIRO_STATUS_NO_MEMORY); } CGPathApply (glyphPath, path, _cairo_quartz_path_apply_func); CGPathRelease (glyphPath); _cairo_scaled_glyph_set_path (scaled_glyph, &font->base, path); return CAIRO_STATUS_SUCCESS; }
// This is essentially identical to the similarly-named helper function // in gfx/thebes/gfxMacFont.cpp. Maybe we should put it somewhere that // can be shared by both Moz2d and Thebes callers? static CFDictionaryRef CreateVariationDictionaryOrNull(CGFontRef aCGFont, uint32_t aVariationCount, const mozilla::gfx::ScaledFont::VariationSetting* aVariations) { // Avoid calling potentially buggy variation APIs on pre-Sierra macOS // versions (see bug 1331683) if (!nsCocoaFeatures::OnSierraOrLater()) { return nullptr; } AutoRelease<CTFontRef> ctFont(CTFontCreateWithGraphicsFont(aCGFont, 0, nullptr, nullptr)); AutoRelease<CFArrayRef> axes(CTFontCopyVariationAxes(ctFont)); if (!axes) { return nullptr; } CFIndex axisCount = CFArrayGetCount(axes); AutoRelease<CFMutableDictionaryRef> dict(CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); // Number of variation settings passed in the aVariations parameter. // This will typically be a very low value, so we just linear-search them. bool allDefaultValues = true; for (CFIndex i = 0; i < axisCount; ++i) { // We sanity-check the axis info found in the CTFont, and bail out // (returning null) if it doesn't have the expected types. CFTypeRef axisInfo = CFArrayGetValueAtIndex(axes, i); if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) { return nullptr; } CFDictionaryRef axis = static_cast<CFDictionaryRef>(axisInfo); CFTypeRef axisTag = CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey); if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) { return nullptr; } int64_t tagLong; if (!CFNumberGetValue(static_cast<CFNumberRef>(axisTag), kCFNumberSInt64Type, &tagLong)) { return nullptr; } CFTypeRef axisName = CFDictionaryGetValue(axis, kCTFontVariationAxisNameKey); if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) { return nullptr; } // Clamp axis values to the supported range. CFTypeRef min = CFDictionaryGetValue(axis, kCTFontVariationAxisMinimumValueKey); CFTypeRef max = CFDictionaryGetValue(axis, kCTFontVariationAxisMaximumValueKey); CFTypeRef def = CFDictionaryGetValue(axis, kCTFontVariationAxisDefaultValueKey); if (!min || CFGetTypeID(min) != CFNumberGetTypeID() || !max || CFGetTypeID(max) != CFNumberGetTypeID() || !def || CFGetTypeID(def) != CFNumberGetTypeID()) { return nullptr; } double minDouble; double maxDouble; double defDouble; if (!CFNumberGetValue(static_cast<CFNumberRef>(min), kCFNumberDoubleType, &minDouble) || !CFNumberGetValue(static_cast<CFNumberRef>(max), kCFNumberDoubleType, &maxDouble) || !CFNumberGetValue(static_cast<CFNumberRef>(def), kCFNumberDoubleType, &defDouble)) { return nullptr; } double value = defDouble; for (uint32_t j = 0; j < aVariationCount; ++j) { if (aVariations[j].mTag == tagLong) { value = std::min(std::max<double>(aVariations[j].mValue, minDouble), maxDouble); if (value != defDouble) { allDefaultValues = false; } break; } } AutoRelease<CFNumberRef> valueNumber(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value)); CFDictionaryAddValue(dict, axisName, valueNumber); } if (allDefaultValues) { // We didn't actually set any non-default values, so throw away the // variations dictionary and just use the default rendering. return nullptr; } return dict.forget(); }