/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef MOZ_WIDGET_COCOA // prototype for private API extern"C" {
CGPathRef CGFontGetGlyphPath(CGFontRef fontRef,
CGAffineTransform* textTransform, int unknown,
CGGlyph glyph);
}; #endif
#include"cairo-quartz.h"
namespace mozilla { namespace gfx {
// Simple helper class to automatically release a CFObject when it goes out // of scope. template <class T> class AutoRelease final { public: explicit AutoRelease(T aObject) : mObject(aObject) {}
~AutoRelease() { if (mObject) {
CFRelease(mObject);
}
}
T forget() {
T obj = mObject;
mObject = nullptr; return obj;
}
private:
T mObject;
};
// Helper to create a CTFont from a CGFont, copying any variations that were // set on the CGFont, and applying attributes from (optional) aFontDesc.
CTFontRef CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize, bool aInstalledFont,
CTFontDescriptorRef aFontDesc) { #ifdef MOZ_WIDGET_COCOA // New implementation (see bug 1856035) for macOS 13+. if (nsCocoaFeatures::OnVenturaOrLater()) { // Create CTFont, applying any descriptor that was passed (used by // gfxCoreTextShaper to set features).
AutoRelease<CTFontRef> ctFont(
CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, aFontDesc));
AutoRelease<CFDictionaryRef> vars(CGFontCopyVariations(aCGFont)); if (vars) { // Create an attribute dictionary containing the variations.
AutoRelease<CFDictionaryRef> attrs(CFDictionaryCreate(
nullptr, (constvoid**)&kCTFontVariationAttribute,
(constvoid**)&vars, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks)); // Get the original descriptor from the CTFont, then add the variations // attribute to it.
AutoRelease<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(ctFont));
desc = CTFontDescriptorCreateCopyWithAttributes(desc, attrs); // Return a copy of the font that has the variations added. return CTFontCreateCopyWithAttributes(ctFont, 0.0, nullptr, desc);
} // No variations to set, just return the default CTFont. return ctFont.forget();
} #endif
// Older implementation used up to macOS 12.
CTFontRef ctFont; if (aInstalledFont) {
AutoRelease<CFDictionaryRef> vars(CGFontCopyVariations(aCGFont)); if (vars) {
AutoRelease<CFDictionaryRef> varAttr(CFDictionaryCreate(
nullptr, (constvoid**)&kCTFontVariationAttribute,
(constvoid**)&vars, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
// Normally, Skia enables LCD FontSmoothing which creates thicker fonts // and also enables subpixel AA. CoreGraphics without font smoothing // explicitly creates thinner fonts and grayscale AA. // CoreGraphics doesn't support a configuration that produces thicker // fonts with grayscale AA as LCD Font Smoothing enables or disables // both. However, Skia supports it by enabling font smoothing (producing // subpixel AA) and converts it to grayscale AA. Since Skia doesn't // support subpixel AA on transparent backgrounds, we still want font // smoothing for the thicker fonts, even if it is grayscale AA. // // With explicit Grayscale AA (from -moz-osx-font-smoothing:grayscale), // we want to have grayscale AA with no smoothing at all. This means // disabling the LCD font smoothing behaviour. // To accomplish this we have to explicitly disable hinting, // and disable LCDRenderText. if (aFont.getEdging() == SkFont::Edging::kAntiAlias && !mUseFontSmoothing) {
aFont.setHinting(SkFontHinting::kNone);
}
}
// private API here are the public options on OS X // CTFontCreatePathForGlyph // ATSUGlyphGetCubicPaths // we've used this in cairo sucessfully for some time. // Note: cairo dlsyms it. We could do that but maybe it's // safe just to use?
// The length is not 4-byte aligned, but we still must process the remaining // bytes. if (length & 3) { // Pad with zero before adding to the checksum.
uint32_t last = 0;
memcpy(&last, end, length & 3);
sum += CFSwapInt32BigToHost(last);
}
bool UnscaledFontMac::GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) { // We'll reconstruct a TTF font from the tables we can get from the CGFont
CFArrayRef tags = CGFontCopyTableTags(mFont);
CFIndex count = CFArrayGetCount(tags);
TableRecord* records = new TableRecord[count];
uint32_t offset = 0;
offset += sizeof(uint32_t) * 3;
offset += sizeof(uint32_t) * 4 * count; bool CFF = false; for (CFIndex i = 0; i < count; i++) {
uint32_t tag = (uint32_t)(uintptr_t)CFArrayGetValueAtIndex(tags, i); if (tag == 0x43464620 || tag == 0x43464632) { // 'CFF ', 'CFF2'
CFF = true;
}
CFDataRef data = CGFontCopyTableForTag(mFont, tag); // Bug 1602391 suggests CGFontCopyTableForTag can fail, even though we just // got the tag from the font via CGFontCopyTableTags above. If we can catch // this (e.g. in fuzz-testing) it'd be good to understand when it happens, // but in any case we'll handle it safely below by treating the table as // zero-length.
MOZ_ASSERT(data, "failed to get font table data");
records[i].tag = tag;
records[i].offset = offset;
records[i].data = data; if (data) {
records[i].length = CFDataGetLength(data); bool skipChecksumAdjust = (tag == 0x68656164); // 'head'
records[i].checkSum = CalcTableChecksum( reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(data)),
records[i].length, skipChecksumAdjust);
offset += records[i].length; // 32 bit align the tables
offset = (offset + 3) & ~3;
} else {
records[i].length = 0;
records[i].checkSum = 0;
}
}
CFRelease(tags);
// write table record entries for (CFIndex i = 0; i < count; i++) {
buf.writeElement(CFSwapInt32HostToBig(records[i].tag));
buf.writeElement(CFSwapInt32HostToBig(records[i].checkSum));
buf.writeElement(CFSwapInt32HostToBig(records[i].offset));
buf.writeElement(CFSwapInt32HostToBig(records[i].length));
}
// write tables int checkSumAdjustmentOffset = 0; for (CFIndex i = 0; i < count; i++) { if (records[i].tag == 0x68656164) {
checkSumAdjustmentOffset = buf.offset + 2 * 4;
} if (records[i].data) {
buf.writeMem(CFDataGetBytePtr(records[i].data), records[i].length);
buf.align();
CFRelease(records[i].data);
}
} delete[] records;
// clear the checksumAdjust field before checksumming the whole font
memset(&buf.data[checkSumAdjustmentOffset], 0, sizeof(uint32_t));
uint32_t fontChecksum = CFSwapInt32HostToBig(
0xb1b0afba -
CalcTableChecksum(reinterpret_cast<const uint32_t*>(buf.data), offset)); // set checkSumAdjust to the computed checksum
memcpy(&buf.data[checkSumAdjustmentOffset], &fontChecksum, sizeof(fontChecksum));
// we always use an index of 0
aDataCallback(buf.data, buf.offset, 0, aBaton);
bool ScaledFontMac::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) { // Collect any variation settings that were incorporated into the CTFont.
std::vector<FontVariation> variations; if (!GetVariationsForCTFont(mCTFont, &variations)) { returnfalse;
}
// 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(aCTAxesCache, i); if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) { return nullptr;
}
CFDictionaryRef axis = static_cast<CFDictionaryRef>(axisInfo);
double value = defDouble; for (uint32_t j = 0; j < aVariationCount; ++j) { if (aVariations[j].mTag == tagLong) {
value = std::clamp<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;
}
// 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);
double value = defDouble; for (uint32_t j = 0; j < aVariationCount; ++j) { if (aVariations[j].mTag == tagLong) {
value = std::clamp<double>(aVariations[j].mValue, minDouble, maxDouble); if (value != defDouble) {
allDefaultValues = false;
} break;
}
}
AutoRelease<CFNumberRef> valueNumber(
CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
CFDictionaryAddValue(dict, axisTag, 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;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.