Reland "Replace CGFontCreate with CTFontManagerCreate."
This is a reland of f1d4f00fda5ca6ce8cd609d5a335ee27f1b75d72
Original change's description:
> Replace CGFontCreate with CTFontManagerCreate.
>
> Replaces calls to CGFontCreateWithDataProvider with calls to
> CTFontManagerCreateFontDescriptorFromData. Note that this means Skia will
> not create CTFonts based on CGFonts, however SkCreateTypefaceFromCTFont
> allows the user to create CTFonts from CGFonts and introduce them to Skia.
>
> Bug: skia:4043,skia:9627
>
> Change-Id: I8eb72c0e4eb257149f1f6a78ca34da4fbfafccab
> TBR: reed@google.com
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/254181
> Commit-Queue: Ben Wagner <bungeman@google.com>
> Reviewed-by: Dominik Röttsches <drott@google.com>
Bug: skia:4043, skia:9627
Change-Id: Ic265f2ce52b816831e6402c5ffd21dac065049dd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/257052
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 66f7849..bcbe6eb 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -924,7 +924,6 @@
"src/ports/SkOSFile_stdio.cpp",
"src/sfnt/SkOTTable_name.cpp",
"src/sfnt/SkOTUtils.cpp",
- "src/utils/mac/SkStream_mac.cpp",
]
defines = []
diff --git a/include/utils/mac/SkCGUtils.h b/include/utils/mac/SkCGUtils.h
index a8bde99..43cd59f 100644
--- a/include/utils/mac/SkCGUtils.h
+++ b/include/utils/mac/SkCGUtils.h
@@ -74,13 +74,5 @@
*/
void SkCGDrawBitmap(CGContextRef, const SkBitmap&, float x, float y);
-/**
- * Return a provider that wraps the specified stream.
- * When the provider is finally deleted, it will delete the stream.
- */
-CGDataProviderRef SkCreateDataProviderFromStream(std::unique_ptr<SkStreamRewindable>);
-
-CGDataProviderRef SkCreateDataProviderFromData(sk_sp<SkData>);
-
#endif // defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
#endif // SkCGUtils_DEFINED
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index bddbf65..3a997ec 100644
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -386,13 +386,12 @@
CGBitmapContextCreate(&smoothBitmap, 16, 16, 8, 16*4,
colorspace.get(), BITMAP_INFO_RGB));
- SkUniqueCFRef<CGDataProviderRef> data(
- CGDataProviderCreateWithData(nullptr, kSpiderSymbol_ttf,
- SK_ARRAY_COUNT(kSpiderSymbol_ttf), nullptr));
- SkUniqueCFRef<CGFontRef> cgFont(CGFontCreateWithDataProvider(data.get()));
- SkASSERT(cgFont);
- SkUniqueCFRef<CTFontRef> ctFont(
- CTFontCreateWithGraphicsFont(cgFont.get(), 16, nullptr, nullptr));
+ SkUniqueCFRef<CFDataRef> data(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, kSpiderSymbol_ttf, SK_ARRAY_COUNT(kSpiderSymbol_ttf),
+ kCFAllocatorNull));
+ SkUniqueCFRef<CTFontDescriptorRef> desc(
+ CTFontManagerCreateFontDescriptorFromData(data.get()));
+ SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc.get(), 16, nullptr));
SkASSERT(ctFont);
CGContextSetShouldSmoothFonts(noSmoothContext.get(), false);
@@ -1617,24 +1616,6 @@
///////////////////////////////////////////////////////////////////////////////
-// Returns nullptr on failure
-static sk_sp<SkTypeface> create_from_dataProvider(SkUniqueCFRef<CGDataProviderRef> provider,
- std::unique_ptr<SkStreamAsset> providedData,
- int ttcIndex) {
- if (ttcIndex != 0) {
- return nullptr;
- }
- SkUniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
- if (!cg) {
- return nullptr;
- }
- SkUniqueCFRef<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg.get(), 0, nullptr, nullptr));
- if (!ct) {
- return nullptr;
- }
- return create_from_CTFontRef(std::move(ct), nullptr, OpszVariation(), std::move(providedData));
-}
-
// Web fonts added to the CTFont registry do not return their character set.
// Iterate through the font in this case. The existing caller caches the result,
// so the performance impact isn't too bad.
@@ -2115,7 +2096,7 @@
static SkUniqueCFRef<CFDictionaryRef> ct_variation_from_cg_variation(CFDictionaryRef cgVariations,
CFArrayRef ctAxes) {
- SkUniqueCFRef<CFMutableDictionaryRef> ctVariations(
+ SkUniqueCFRef<CFMutableDictionaryRef> ctVariation(
CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
@@ -2145,9 +2126,9 @@
return nullptr;
}
- CFDictionaryAddValue(ctVariations.get(), axisTag, axisValue);
+ CFDictionaryAddValue(ctVariation.get(), axisTag, axisValue);
}
- return ctVariations;
+ return ctVariation;
}
int SkTypeface_Mac::onGetVariationDesignPosition(
@@ -2169,8 +2150,8 @@
// This call always returns nullptr on 10.11 and under for CGFontCreateWithDataProvider fonts.
// When this happens, try converting the CG variation to a CT variation.
// On 10.12 and later, this only returns non-default variations.
- SkUniqueCFRef<CFDictionaryRef> ctVariations(CTFontCopyVariation(fFontRef.get()));
- if (!ctVariations) {
+ SkUniqueCFRef<CFDictionaryRef> ctVariation(CTFontCopyVariation(fFontRef.get()));
+ if (!ctVariation) {
// When 10.11 and earlier are no longer supported, the following code can be replaced with
// return -1 and ct_variation_from_cg_variation can be removed.
SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
@@ -2181,8 +2162,8 @@
if (!cgVariations) {
return -1;
}
- ctVariations = ct_variation_from_cg_variation(cgVariations.get(), ctAxes.get());
- if (!ctVariations) {
+ ctVariation = ct_variation_from_cg_variation(cgVariations.get(), ctAxes.get());
+ if (!ctVariation) {
return -1;
}
}
@@ -2206,7 +2187,7 @@
coordinates[i].axis = tagLong;
CGFloat variationCGFloat;
- CFTypeRef variationValue = CFDictionaryGetValue(ctVariations.get(), tagNumber);
+ CFTypeRef variationValue = CFDictionaryGetValue(ctVariation.get(), tagNumber);
if (variationValue) {
if (CFGetTypeID(variationValue) != CFNumberGetTypeID()) {
return -1;
@@ -2696,45 +2677,52 @@
}
sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
- SkUniqueCFRef<CGDataProviderRef> pr(SkCreateDataProviderFromData(data));
- if (!pr) {
+ if (ttcIndex != 0) {
return nullptr;
}
- return create_from_dataProvider(std::move(pr), SkMemoryStream::Make(std::move(data)),
- ttcIndex);
+
+ SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(data, ttcIndex);
+ if (!ct) {
+ return nullptr;
+ }
+
+ return create_from_CTFontRef(std::move(ct), nullptr, OpszVariation(),
+ SkMemoryStream::Make(std::move(data)));
}
sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
int ttcIndex) const override {
- SkUniqueCFRef<CGDataProviderRef> pr(SkCreateDataProviderFromStream(stream->duplicate()));
- if (!pr) {
+ if (ttcIndex != 0) {
return nullptr;
}
- return create_from_dataProvider(std::move(pr), std::move(stream), ttcIndex);
+
+ sk_sp<SkData> data = skdata_from_skstreamasset(stream->duplicate());
+ if (!data) {
+ return nullptr;
+ }
+ SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), ttcIndex);
+ if (!ct) {
+ return nullptr;
+ }
+
+ return create_from_CTFontRef(std::move(ct), nullptr, OpszVariation(), std::move(stream));
}
- /** Creates a dictionary suitable for setting the axes on a CGFont. */
- struct CGFontVariations {
+ struct CTFontVariation {
SkUniqueCFRef<CFDictionaryRef> dict;
OpszVariation opsz;
};
- static CGFontVariations copy_axes(CGFontRef cg, const SkFontArguments& args) {
- // In macOS 10.15 CTFontCreate* overrides any 'opsz' variation with the 'size'.
- // Track the 'opsz' and return it, since it is an out of band axis.
+
+ /** Creates a dictionary suitable for setting the axes on a CTFont. */
+ static CTFontVariation ctvariation_from_skfontarguments(CTFontRef ct,
+ const SkFontArguments& args)
+ {
OpszVariation opsz;
constexpr const SkFourByteTag opszTag = SkSetFourByteTag('o','p','s','z');
- // The CGFont variation data is keyed by name, but lacks the tag.
- // The CTFont variation data is keyed by tag, and also has the name.
- // We would like to work with CTFont variations, but creating a CTFont font with
- // CTFont variation dictionary runs into bugs. So use the CTFont variation data
- // to match names to tags to create the appropriate CGFont.
- SkUniqueCFRef<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg, 0, nullptr, nullptr));
- // CTFontCopyVariationAxes returns nullptr for CGFontCreateWithDataProvider fonts with
- // macOS 10.10 and iOS 9 or earlier. When this happens, there is no API to provide the tag.
- SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct.get()));
+ SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct));
if (!ctAxes) {
- return CGFontVariations();
+ return CTFontVariation();
}
CFIndex axisCount = CFArrayGetCount(ctAxes.get());
@@ -2748,26 +2736,18 @@
for (int i = 0; i < axisCount; ++i) {
CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
- return CGFontVariations();
+ return CTFontVariation();
}
CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
- // The assumption is that values produced by kCTFontVariationAxisNameKey and
- // kCGFontVariationAxisName will always be equal.
- // If they are ever not, seach the project history for "get_tag_for_name".
- CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisNameKey);
- if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
- return CGFontVariations();
- }
-
CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
- return CGFontVariations();
+ return CTFontVariation();
}
CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
int64_t tagLong;
if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
- return CGFontVariations();
+ return CTFontVariation();
}
// The variation axes can be set to any value, but cg will effectively pin them.
@@ -2779,7 +2759,7 @@
!max || CFGetTypeID(max) != CFNumberGetTypeID() ||
!def || CFGetTypeID(def) != CFNumberGetTypeID())
{
- return CGFontVariations();
+ return CTFontVariation();
}
CFNumberRef minNumber = static_cast<CFNumberRef>(min);
CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
@@ -2791,7 +2771,7 @@
!CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
!CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
{
- return CGFontVariations();
+ return CTFontVariation();
}
double value = defDouble;
@@ -2812,73 +2792,118 @@
}
SkUniqueCFRef<CFNumberRef> valueNumber(
CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
- CFDictionaryAddValue(dict.get(), axisName, valueNumber.get());
+ CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
}
return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
}
- sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> s,
- const SkFontArguments& args) const override {
- if (args.getCollectionIndex() != 0) {
- return nullptr;
+
+ static sk_sp<SkData> skdata_from_skstreamasset(std::unique_ptr<SkStreamAsset> stream) {
+ size_t size = stream->getLength();
+ if (const void* base = stream->getMemoryBase()) {
+ return SkData::MakeWithProc(base, size,
+ [](const void*, void* ctx) -> void {
+ delete (SkStreamAsset*)ctx;
+ }, stream.release());
}
- SkUniqueCFRef<CGDataProviderRef> provider(SkCreateDataProviderFromStream(s->duplicate()));
- if (!provider) {
- return nullptr;
- }
- SkUniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
- if (!cg) {
+ return SkData::MakeFromStream(stream.get(), size);
+ }
+
+ static SkUniqueCFRef<CFDataRef> cfdata_from_skdata(sk_sp<SkData> data) {
+ void const * const addr = data->data();
+ size_t const size = data->size();
+
+ CFAllocatorContext ctx = {
+ 0, // CFIndex version
+ data.release(), // void* info
+ nullptr, // const void *(*retain)(const void *info);
+ nullptr, // void (*release)(const void *info);
+ nullptr, // CFStringRef (*copyDescription)(const void *info);
+ nullptr, // void * (*allocate)(CFIndex size, CFOptionFlags hint, void *info);
+ nullptr, // void*(*reallocate)(void* ptr,CFIndex newsize,CFOptionFlags hint,void* info);
+ [](void*,void* info) -> void { // void (*deallocate)(void *ptr, void *info);
+ SkASSERT(info);
+ ((SkData*)info)->unref();
+ },
+ nullptr, // CFIndex (*preferredSize)(CFIndex size, CFOptionFlags hint, void *info);
+ };
+ SkUniqueCFRef<CFAllocatorRef> alloc(CFAllocatorCreate(kCFAllocatorDefault, &ctx));
+ return SkUniqueCFRef<CFDataRef>(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, (const UInt8 *)addr, size, alloc.get()));
+ }
+
+ static SkUniqueCFRef<CTFontRef> ctfont_from_skdata(sk_sp<SkData> data, int ttcIndex) {
+ // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
+ if (ttcIndex != 0) {
return nullptr;
}
- CGFontVariations cgVariations = copy_axes(cg.get(), args);
- // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was
- // created from a data provider does not appear to have any ownership of the underlying
- // data. The original CGFontRef must be kept alive until the copy will no longer be used.
- SkUniqueCFRef<CGFontRef> cgVariant;
- if (cgVariations.dict) {
- cgVariant.reset(CGFontCreateCopyWithVariations(cg.get(), cgVariations.dict.get()));
- } else {
- cgVariant.reset(cg.release());
+ SkUniqueCFRef<CFDataRef> cfData(cfdata_from_skdata(std::move(data)));
+
+ SkUniqueCFRef<CTFontDescriptorRef> desc(
+ CTFontManagerCreateFontDescriptorFromData(cfData.get()));
+ if (!desc) {
+ return nullptr;
+ }
+ return SkUniqueCFRef<CTFontRef>(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
+ }
+
+ sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
+ const SkFontArguments& args) const override
+ {
+ // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
+ int ttcIndex = args.getCollectionIndex();
+ if (ttcIndex != 0) {
+ return nullptr;
}
- SkUniqueCFRef<CTFontDescriptorRef> desc;
- if (cgVariations.opsz.isSet) {
- desc = create_opsz_descriptor(cgVariations.opsz.value);
+ sk_sp<SkData> data = skdata_from_skstreamasset(stream->duplicate());
+ if (!data) {
+ return nullptr;
}
-
- SkUniqueCFRef<CTFontRef> ct(
- CTFontCreateWithGraphicsFont(cgVariant.get(), 0, nullptr, desc.get()));
+ SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), ttcIndex);
if (!ct) {
return nullptr;
}
- return create_from_CTFontRef(std::move(ct), std::move(cg), cgVariations.opsz, std::move(s));
+
+ CTFontVariation ctVariation = ctvariation_from_skfontarguments(ct.get(), args);
+
+ SkUniqueCFRef<CTFontRef> ctVariant;
+ if (ctVariation.dict) {
+ SkUniqueCFRef<CFMutableDictionaryRef> attributes(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ CFDictionaryAddValue(attributes.get(),
+ kCTFontVariationAttribute, ctVariation.dict.get());
+ SkUniqueCFRef<CTFontDescriptorRef> varDesc(
+ CTFontDescriptorCreateWithAttributes(attributes.get()));
+ ctVariant.reset(CTFontCreateCopyWithAttributes(ct.get(), 0, nullptr, varDesc.get()));
+ } else {
+ ctVariant.reset(ct.release());
+ }
+ if (!ctVariant) {
+ return nullptr;
+ }
+
+ return create_from_CTFontRef(std::move(ctVariant), nullptr, ctVariation.opsz,
+ std::move(stream));
}
- /** Creates a dictionary suitable for setting the axes on a CGFont. */
- static CGFontVariations copy_axes(CGFontRef cg, SkFontData* fontData) {
+ /** Creates a dictionary suitable for setting the axes on a CTFont. */
+ static CTFontVariation ctvariation_from_skfontdata(CTFontRef ct, SkFontData* fontData) {
// In macOS 10.15 CTFontCreate* overrides any 'opsz' variation with the 'size'.
// Track the 'opsz' and return it, since it is an out of band axis.
OpszVariation opsz;
constexpr const SkFourByteTag opszTag = SkSetFourByteTag('o','p','s','z');
- // The CGFont variation data is keyed by name, but lacks the tag.
- // The CTFont variation data is keyed by tag, and also has the name.
- // We would like to work with CTFont variations, but creating a CTFont font with
- // CTFont variation dictionary runs into bugs. So use the CTFont variation data
- // to match names to tags to create the appropriate CGFont.
- SkUniqueCFRef<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg, 0, nullptr, nullptr));
- // CTFontCopyVariationAxes returns nullptr for CGFontCreateWithDataProvider fonts with
- // macOS 10.10 and iOS 9 or earlier. When this happens, there is no API to provide the tag.
- SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct.get()));
-
- SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg));
- if (!cgAxes) {
- return CGFontVariations();
+ SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct));
+ if (!ctAxes) {
+ return CTFontVariation();
}
- CFIndex axisCount = CFArrayGetCount(cgAxes.get());
+ CFIndex axisCount = CFArrayGetCount(ctAxes.get());
if (0 == axisCount || axisCount != fontData->getAxisCount()) {
- return CGFontVariations();
+ return CTFontVariation();
}
SkUniqueCFRef<CFMutableDictionaryRef> dict(
@@ -2887,25 +2912,31 @@
&kCFTypeDictionaryValueCallBacks));
for (int i = 0; i < fontData->getAxisCount(); ++i) {
- CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes.get(), i);
+ CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
- return CGFontVariations();
+ return CTFontVariation();
}
CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
- CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisName);
- if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
- return CGFontVariations();
+ CFTypeRef tag = CFDictionaryGetValue(axisInfoDict,
+ kCTFontVariationAxisIdentifierKey);
+ if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
+ return CTFontVariation();
+ }
+ CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
+ int64_t tagLong;
+ if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
+ return CTFontVariation();
}
// The variation axes can be set to any value, but cg will effectively pin them.
// Pin them here to normalize.
- CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMinValue);
- CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMaxValue);
+ CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
+ CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
!max || CFGetTypeID(max) != CFNumberGetTypeID())
{
- return CGFontVariations();
+ return CTFontVariation();
}
CFNumberRef minNumber = static_cast<CFNumberRef>(min);
CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
@@ -2914,87 +2945,71 @@
if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
!CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
{
- return CGFontVariations();
+ return CTFontVariation();
}
double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble);
- // If this is the opsz axis, set the opsz return value.
- // Note that ctAxes will be nullptr on macOS 10.10 and iOS 9 and earlier.
- if (ctAxes) {
- CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
- if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
- return CGFontVariations();
- }
- CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
-
- CFTypeRef tag = CFDictionaryGetValue(axisInfoDict,
- kCTFontVariationAxisIdentifierKey);
- if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
- return CGFontVariations();
- }
- CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
- int64_t tagLong;
- if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
- return CGFontVariations();
- }
-
- if (tagLong == opszTag) {
- opsz.isSet = true;
- opsz.value = value;
- }
+ if (tagLong == opszTag) {
+ opsz.isSet = true;
+ opsz.value = value;
}
SkUniqueCFRef<CFNumberRef> valueNumber(
CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
- CFDictionaryAddValue(dict.get(), axisName, valueNumber.get());
+ CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
}
return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
}
sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData> fontData) const override {
+ // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
if (fontData->getIndex() != 0) {
return nullptr;
}
- SkUniqueCFRef<CGDataProviderRef> provider(
- SkCreateDataProviderFromStream(fontData->getStream()->duplicate()));
- if (!provider) {
+
+ sk_sp<SkData> data = skdata_from_skstreamasset(fontData->getStream()->duplicate());
+ if (!data) {
return nullptr;
}
- SkUniqueCFRef<CGFontRef> cg(CGFontCreateWithDataProvider(provider.get()));
- if (!cg) {
- return nullptr;
- }
-
- CGFontVariations cgVariations = copy_axes(cg.get(), fontData.get());
- // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was
- // created from a data provider does not appear to have any ownership of the underlying
- // data. The original CGFontRef must be kept alive until the copy will no longer be used.
- SkUniqueCFRef<CGFontRef> cgVariant;
- if (cgVariations.dict) {
- cgVariant.reset(CGFontCreateCopyWithVariations(cg.get(), cgVariations.dict.get()));
- } else {
- cgVariant.reset(cg.release());
- }
-
- SkUniqueCFRef<CTFontDescriptorRef> desc;
- if (cgVariations.opsz.isSet) {
- desc = create_opsz_descriptor(cgVariations.opsz.value);
- }
-
- SkUniqueCFRef<CTFontRef> ct(
- CTFontCreateWithGraphicsFont(cgVariant.get(), 0, nullptr, desc.get()));
+ SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), fontData->getIndex());
if (!ct) {
return nullptr;
}
- return create_from_CTFontRef(std::move(ct), std::move(cg),
- cgVariations.opsz, fontData->detachStream());
+
+ CTFontVariation ctVariation = ctvariation_from_skfontdata(ct.get(), fontData.get());
+
+ SkUniqueCFRef<CTFontRef> ctVariant;
+ if (ctVariation.dict) {
+ SkUniqueCFRef<CFMutableDictionaryRef> attributes(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ CFDictionaryAddValue(attributes.get(),
+ kCTFontVariationAttribute, ctVariation.dict.get());
+ SkUniqueCFRef<CTFontDescriptorRef> varDesc(
+ CTFontDescriptorCreateWithAttributes(attributes.get()));
+ ctVariant.reset(CTFontCreateCopyWithAttributes(ct.get(), 0, nullptr, varDesc.get()));
+ } else {
+ ctVariant.reset(ct.release());
+ }
+ if (!ctVariant) {
+ return nullptr;
+ }
+
+ return create_from_CTFontRef(std::move(ctVariant), nullptr,
+ ctVariation.opsz, fontData->detachStream());
}
sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
- SkUniqueCFRef<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path));
- if (!pr) {
+ if (ttcIndex != 0) {
return nullptr;
}
- return create_from_dataProvider(std::move(pr), SkFILEStream::Make(path), ttcIndex);
+
+ sk_sp<SkData> data = SkData::MakeFromFileName(path);
+ if (!data) {
+ return nullptr;
+ }
+
+ return this->onMakeFromData(std::move(data), ttcIndex);
}
sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
diff --git a/src/utils/mac/SkStream_mac.cpp b/src/utils/mac/SkStream_mac.cpp
index 30f8e1e..b299fce 100644
--- a/src/utils/mac/SkStream_mac.cpp
+++ b/src/utils/mac/SkStream_mac.cpp
@@ -5,79 +5,4 @@
* found in the LICENSE file.
*/
-#include "include/core/SkTypes.h"
-
-#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
-
-#include "include/core/SkStream.h"
-#include "include/private/SkMalloc.h"
-#include "include/utils/mac/SkCGUtils.h"
-
-// These are used by CGDataProviderCreateWithData
-
-static void unref_proc(void* info, const void* addr, size_t size) {
- SkASSERT(info);
- ((SkRefCnt*)info)->unref();
-}
-
-static void delete_stream_proc(void* info, const void* addr, size_t size) {
- SkASSERT(info);
- SkStream* stream = (SkStream*)info;
- SkASSERT(stream->getMemoryBase() == addr);
- SkASSERT(stream->getLength() == size);
- delete stream;
-}
-
-// These are used by CGDataProviderSequentialCallbacks
-
-static size_t get_bytes_proc(void* info, void* buffer, size_t bytes) {
- SkASSERT(info);
- return ((SkStream*)info)->read(buffer, bytes);
-}
-
-static off_t skip_forward_proc(void* info, off_t bytes) {
- return ((SkStream*)info)->skip((size_t) bytes);
-}
-
-static void rewind_proc(void* info) {
- SkASSERT(info);
- ((SkStream*)info)->rewind();
-}
-
-// Used when info is an SkStream.
-static void release_info_proc(void* info) {
- SkASSERT(info);
- delete (SkStream*)info;
-}
-
-CGDataProviderRef SkCreateDataProviderFromStream(std::unique_ptr<SkStreamRewindable> stream) {
- // TODO: Replace with SkStream::getData() when that is added. Then we only
- // have one version of CGDataProviderCreateWithData (i.e. same release proc)
- const void* addr = stream->getMemoryBase();
- if (addr) {
- // special-case when the stream is just a block of ram
- size_t size = stream->getLength();
- return CGDataProviderCreateWithData(stream.release(), addr, size, delete_stream_proc);
- }
-
- CGDataProviderSequentialCallbacks rec;
- sk_bzero(&rec, sizeof(rec));
- rec.version = 0;
- rec.getBytes = get_bytes_proc;
- rec.skipForward = skip_forward_proc;
- rec.rewind = rewind_proc;
- rec.releaseInfo = release_info_proc;
- return CGDataProviderCreateSequential(stream.release(), &rec);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include "include/core/SkData.h"
-
-CGDataProviderRef SkCreateDataProviderFromData(sk_sp<SkData> data) {
- const void* addr = data->data();
- size_t size = data->size();
- return CGDataProviderCreateWithData(data.release(), addr, size, unref_proc);
-}
-
-#endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+// Remove file after it is removed from downstream builds.