OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkTypes.h" // Keep this before any #ifdef ... | 9 #include "SkTypes.h" // Keep this before any #ifdef ... |
10 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) | 10 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) |
(...skipping 2353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2364 } | 2364 } |
2365 | 2365 |
2366 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov
erride { | 2366 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const ov
erride { |
2367 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea
m)); | 2367 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(strea
m)); |
2368 if (nullptr == pr) { | 2368 if (nullptr == pr) { |
2369 return nullptr; | 2369 return nullptr; |
2370 } | 2370 } |
2371 return create_from_dataProvider(pr); | 2371 return create_from_dataProvider(pr); |
2372 } | 2372 } |
2373 | 2373 |
| 2374 static CFNumberRef get_tag_for_name(CFStringRef name, CFArrayRef ctAxes) { |
| 2375 CFIndex ctAxisCount = CFArrayGetCount(ctAxes); |
| 2376 for (int i = 0; i < ctAxisCount; ++i) { |
| 2377 CFTypeRef ctAxisInfo = CFArrayGetValueAtIndex(ctAxes, i); |
| 2378 if (CFDictionaryGetTypeID() != CFGetTypeID(ctAxisInfo)) { |
| 2379 return nullptr; |
| 2380 } |
| 2381 CFDictionaryRef ctAxisInfoDict = static_cast<CFDictionaryRef>(ctAxis
Info); |
| 2382 |
| 2383 CFTypeRef ctAxisName = CFDictionaryGetValue(ctAxisInfoDict, |
| 2384 kCTFontVariationAxisName
Key); |
| 2385 if (!ctAxisName || CFGetTypeID(ctAxisName) != CFStringGetTypeID()) { |
| 2386 return nullptr; |
| 2387 } |
| 2388 |
| 2389 if (CFEqual(name, ctAxisName)) { |
| 2390 CFTypeRef tag = CFDictionaryGetValue(ctAxisInfoDict, |
| 2391 kCTFontVariationAxisIdentif
ierKey); |
| 2392 if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) { |
| 2393 return nullptr; |
| 2394 } |
| 2395 return static_cast<CFNumberRef>(tag); |
| 2396 } |
| 2397 } |
| 2398 return nullptr; |
| 2399 } |
| 2400 static CFDictionaryRef get_axes(CGFontRef cg, const FontParameters& params)
{ |
| 2401 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg)); |
| 2402 if (!cgAxes) { |
| 2403 return nullptr; |
| 2404 } |
| 2405 CFIndex axisCount = CFArrayGetCount(cgAxes); |
| 2406 |
| 2407 // The CGFont variation data is keyed by name, and lacks the tag. |
| 2408 // The CTFont variation data is keyed by tag, and also has the name. |
| 2409 // We would like to work with CTFont variaitons, but creating a CTFont f
ont with |
| 2410 // CTFont variation dictionary runs into bugs. So use the CTFont variati
on data |
| 2411 // to match names to tags to create the appropriate CGFont. |
| 2412 AutoCFRelease<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg, 0, nullptr,
nullptr)); |
| 2413 AutoCFRelease<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct)); |
| 2414 if (!ctAxes || CFArrayGetCount(ctAxes) != axisCount) { |
| 2415 return nullptr; |
| 2416 } |
| 2417 |
| 2418 int paramAxisCount; |
| 2419 const FontParameters::Axis* paramAxes = params.getAxes(¶mAxisCount); |
| 2420 |
| 2421 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefa
ult, axisCount, |
| 2422 &kCFTypeDictiona
ryKeyCallBacks, |
| 2423 &kCFTypeDictiona
ryValueCallBacks); |
| 2424 for (int i = 0; i < axisCount; ++i) { |
| 2425 CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes, i); |
| 2426 if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) { |
| 2427 return nullptr; |
| 2428 } |
| 2429 CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo
); |
| 2430 |
| 2431 CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVaria
tionAxisName); |
| 2432 if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) { |
| 2433 return nullptr; |
| 2434 } |
| 2435 |
| 2436 CFNumberRef tagNumber = get_tag_for_name(static_cast<CFStringRef>(ax
isName), ctAxes); |
| 2437 if (!tagNumber) { |
| 2438 // Could not find a tag to go with the name of this index. |
| 2439 // This would be a bug in CG/CT. |
| 2440 continue; |
| 2441 } |
| 2442 int64_t tagLong; |
| 2443 if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) { |
| 2444 return nullptr; |
| 2445 } |
| 2446 |
| 2447 // The variation axes can be set to any value, but cg will effective
ly pin them. |
| 2448 // Pin them here to normalize. |
| 2449 CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationA
xisMinValue); |
| 2450 CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationA
xisMaxValue); |
| 2451 CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCGFontVariationA
xisDefaultValue); |
| 2452 if (!min || CFGetTypeID(min) != CFNumberGetTypeID() || |
| 2453 !max || CFGetTypeID(max) != CFNumberGetTypeID() || |
| 2454 !def || CFGetTypeID(def) != CFNumberGetTypeID()) |
| 2455 { |
| 2456 return nullptr; |
| 2457 } |
| 2458 CFNumberRef minNumber = static_cast<CFNumberRef>(min); |
| 2459 CFNumberRef maxNumber = static_cast<CFNumberRef>(max); |
| 2460 CFNumberRef defNumber = static_cast<CFNumberRef>(def); |
| 2461 double minDouble; |
| 2462 double maxDouble; |
| 2463 double defDouble; |
| 2464 if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) || |
| 2465 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) || |
| 2466 !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble)) |
| 2467 { |
| 2468 return nullptr; |
| 2469 } |
| 2470 |
| 2471 double value = defDouble; |
| 2472 for (int j = 0; j < paramAxisCount; ++j) { |
| 2473 if (paramAxes[j].fTag == tagLong) { |
| 2474 value = SkTPin(SkScalarToDouble(paramAxes[j].fStyleValue),mi
nDouble,maxDouble); |
| 2475 break; |
| 2476 } |
| 2477 } |
| 2478 CFNumberRef valueNumber = CFNumberCreate(kCFAllocatorDefault, kCFNum
berDoubleType, |
| 2479 &value); |
| 2480 CFDictionaryAddValue(dict, axisName, valueNumber); |
| 2481 CFRelease(valueNumber); |
| 2482 } |
| 2483 return dict; |
| 2484 } |
| 2485 SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& param
s) const override { |
| 2486 AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream
(s)); |
| 2487 if (nullptr == provider) { |
| 2488 return nullptr; |
| 2489 } |
| 2490 AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider)); |
| 2491 if (nullptr == cg) { |
| 2492 return nullptr; |
| 2493 } |
| 2494 |
| 2495 AutoCFRelease<CFDictionaryRef> cgVariations(get_axes(cg, params)); |
| 2496 // The CGFontRef returned by CGFontCreateCopyWithVariations when the pas
sed CGFontRef was |
| 2497 // created from a data provider does not appear to have any ownership of
the underlying |
| 2498 // data. The original CGFontRef must be kept alive until the copy will n
o longer be used. |
| 2499 AutoCFRelease<CGFontRef> cgVariant; |
| 2500 if (cgVariations) { |
| 2501 cgVariant.reset(CGFontCreateCopyWithVariations(cg, cgVariations)); |
| 2502 } else { |
| 2503 cgVariant.reset(cg.detach()); |
| 2504 } |
| 2505 |
| 2506 CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, nullptr, nullp
tr); |
| 2507 if (!ct) { |
| 2508 return nullptr; |
| 2509 } |
| 2510 return NewFromFontRef(ct, cg.detach(), nullptr, true); |
| 2511 } |
| 2512 |
2374 static CFDictionaryRef get_axes(CGFontRef cg, SkFontData* fontData) { | 2513 static CFDictionaryRef get_axes(CGFontRef cg, SkFontData* fontData) { |
2375 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg)); | 2514 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg)); |
2376 if (!cgAxes) { | 2515 if (!cgAxes) { |
2377 return nullptr; | 2516 return nullptr; |
2378 } | 2517 } |
2379 | 2518 |
2380 CFIndex axisCount = CFArrayGetCount(cgAxes); | 2519 CFIndex axisCount = CFArrayGetCount(cgAxes); |
2381 if (0 == axisCount || axisCount != fontData->getAxisCount()) { | 2520 if (0 == axisCount || axisCount != fontData->getAxisCount()) { |
2382 return nullptr; | 2521 return nullptr; |
2383 } | 2522 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2488 } | 2627 } |
2489 return face; | 2628 return face; |
2490 } | 2629 } |
2491 }; | 2630 }; |
2492 | 2631 |
2493 /////////////////////////////////////////////////////////////////////////////// | 2632 /////////////////////////////////////////////////////////////////////////////// |
2494 | 2633 |
2495 SkFontMgr* SkFontMgr::Factory() { return new SkFontMgr_Mac; } | 2634 SkFontMgr* SkFontMgr::Factory() { return new SkFontMgr_Mac; } |
2496 | 2635 |
2497 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) | 2636 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) |
OLD | NEW |