mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-14 04:03:47 +00:00
Bug 1430820 - Cache any required feature-modified Core Text font instances in gfxCoreTextShaper, rather than re-creating them for each shaping call. r=jrmuizel
This commit is contained in:
parent
c6574d2c99
commit
c2f3f60125
@ -18,12 +18,7 @@
|
||||
using namespace mozilla;
|
||||
|
||||
// standard font descriptors that we construct the first time they're needed
|
||||
CTFontDescriptorRef gfxCoreTextShaper::sDefaultFeaturesDescriptor = nullptr;
|
||||
CTFontDescriptorRef gfxCoreTextShaper::sSmallCapsDescriptor = nullptr;
|
||||
CTFontDescriptorRef gfxCoreTextShaper::sDisableLigaturesDescriptor = nullptr;
|
||||
CTFontDescriptorRef gfxCoreTextShaper::sSmallCapDisableLigDescriptor = nullptr;
|
||||
CTFontDescriptorRef gfxCoreTextShaper::sIndicFeaturesDescriptor = nullptr;
|
||||
CTFontDescriptorRef gfxCoreTextShaper::sIndicDisableLigaturesDescriptor = nullptr;
|
||||
CTFontDescriptorRef gfxCoreTextShaper::sFeaturesDescriptor[kMaxFontInstances];
|
||||
|
||||
// Helper to create a CFDictionary with the right attributes for shaping our
|
||||
// text, including imposing the given directionality.
|
||||
@ -45,7 +40,7 @@ gfxCoreTextShaper::CreateAttrDict(bool aRightToLeft)
|
||||
&kCFTypeArrayCallBacks);
|
||||
::CFRelease(dirNumber);
|
||||
CFTypeRef attrs[] = { kCTFontAttributeName, kCTWritingDirectionAttributeName };
|
||||
CFTypeRef values[] = { mCTFont, dirArray };
|
||||
CFTypeRef values[] = { mCTFont[0], dirArray };
|
||||
CFDictionaryRef attrDict =
|
||||
::CFDictionaryCreate(kCFAllocatorDefault,
|
||||
attrs, values, ArrayLength(attrs),
|
||||
@ -60,9 +55,13 @@ gfxCoreTextShaper::gfxCoreTextShaper(gfxMacFont *aFont)
|
||||
, mAttributesDictLTR(nullptr)
|
||||
, mAttributesDictRTL(nullptr)
|
||||
{
|
||||
// Create our CTFontRef
|
||||
mCTFont = CreateCTFontWithFeatures(aFont->GetAdjustedSize(),
|
||||
GetDefaultFeaturesDescriptor());
|
||||
for (size_t i = 0; i < kMaxFontInstances; i++) {
|
||||
mCTFont[i] = nullptr;
|
||||
}
|
||||
// Create our default CTFontRef
|
||||
mCTFont[0] =
|
||||
CreateCTFontWithFeatures(aFont->GetAdjustedSize(),
|
||||
GetFeaturesDescriptor(kDefaultFeatures));
|
||||
}
|
||||
|
||||
gfxCoreTextShaper::~gfxCoreTextShaper()
|
||||
@ -73,8 +72,10 @@ gfxCoreTextShaper::~gfxCoreTextShaper()
|
||||
if (mAttributesDictRTL) {
|
||||
::CFRelease(mAttributesDictRTL);
|
||||
}
|
||||
if (mCTFont) {
|
||||
::CFRelease(mCTFont);
|
||||
for (size_t i = 0; i < kMaxFontInstances; i++) {
|
||||
if (mCTFont[i]) {
|
||||
::CFRelease(mCTFont[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +136,7 @@ gfxCoreTextShaper::ShapeText(DrawTarget *aDrawTarget,
|
||||
(isRightToLeft ? mAttributesDictRTL : mAttributesDictLTR) = attrObj;
|
||||
}
|
||||
|
||||
CTFontRef tempCTFont = nullptr;
|
||||
FeatureFlags featureFlags = kDefaultFeatures;
|
||||
if (IsBuggyIndicScript(aScript)) {
|
||||
// To work around buggy Indic AAT fonts shipped with OS X,
|
||||
// we re-enable the Line Initial Smart Swashes feature that is needed
|
||||
@ -143,36 +144,30 @@ gfxCoreTextShaper::ShapeText(DrawTarget *aDrawTarget,
|
||||
// Affected fonts include Bangla MN, Bangla Sangam MN, Kannada MN,
|
||||
// Kannada Sangam MN. See bugs 686225, 728557, 953231, 1145515.
|
||||
// Also applies to Oriya and Khmer, see bug 1370927 and bug 1403166.
|
||||
tempCTFont =
|
||||
CreateCTFontWithFeatures(::CTFontGetSize(mCTFont),
|
||||
aShapedText->DisableLigatures()
|
||||
? GetIndicDisableLigaturesDescriptor()
|
||||
: GetIndicFeaturesDescriptor());
|
||||
} else if (aShapedText->DisableLigatures()) {
|
||||
featureFlags |= kIndicFeatures;
|
||||
}
|
||||
if (aShapedText->DisableLigatures()) {
|
||||
// For letterspacing (or maybe other situations) we need to make
|
||||
// a copy of the CTFont with the ligature feature disabled.
|
||||
tempCTFont =
|
||||
CreateCTFontWithFeatures(::CTFontGetSize(mCTFont),
|
||||
addSmallCaps
|
||||
? GetSmallCapDisableLigDescriptor()
|
||||
: GetDisableLigaturesDescriptor());
|
||||
} else if (addSmallCaps) {
|
||||
tempCTFont =
|
||||
CreateCTFontWithFeatures(::CTFontGetSize(mCTFont),
|
||||
GetSmallCapsDescriptor());
|
||||
featureFlags |= kDisableLigatures;
|
||||
}
|
||||
if (addSmallCaps) {
|
||||
featureFlags |= kAddSmallCaps;
|
||||
}
|
||||
|
||||
// For the disabled-ligature, buggy-indic-font or small-caps case, replace
|
||||
// the standard CTFont in the attribute dictionary with a tweaked version.
|
||||
// the default CTFont in the attribute dictionary with a tweaked version.
|
||||
CFMutableDictionaryRef mutableAttr = nullptr;
|
||||
if (tempCTFont) {
|
||||
mutableAttr = ::CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 2,
|
||||
attrObj);
|
||||
if (featureFlags != 0) {
|
||||
if (!mCTFont[featureFlags]) {
|
||||
mCTFont[featureFlags] =
|
||||
CreateCTFontWithFeatures(mFont->GetAdjustedSize(),
|
||||
GetFeaturesDescriptor(featureFlags));
|
||||
}
|
||||
mutableAttr =
|
||||
::CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 2, attrObj);
|
||||
::CFDictionaryReplaceValue(mutableAttr,
|
||||
kCTFontAttributeName, tempCTFont);
|
||||
// Having created the dict, we're finished with our temporary
|
||||
// Indic and/or ligature-disabled or small-caps CTFontRef.
|
||||
::CFRelease(tempCTFont);
|
||||
kCTFontAttributeName, mCTFont[featureFlags]);
|
||||
attrObj = mutableAttr;
|
||||
}
|
||||
|
||||
@ -577,7 +572,7 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText,
|
||||
|
||||
CTFontDescriptorRef
|
||||
gfxCoreTextShaper::CreateFontFeaturesDescriptor(
|
||||
const std::pair<SInt16,SInt16> aFeatures[],
|
||||
const std::pair<SInt16,SInt16>* aFeatures,
|
||||
size_t aCount)
|
||||
{
|
||||
MOZ_ASSERT(aCount <= MAX_FEATURES);
|
||||
@ -637,110 +632,34 @@ gfxCoreTextShaper::CreateFontFeaturesDescriptor(
|
||||
}
|
||||
|
||||
CTFontDescriptorRef
|
||||
gfxCoreTextShaper::GetDefaultFeaturesDescriptor()
|
||||
gfxCoreTextShaper::GetFeaturesDescriptor(FeatureFlags aFeatureFlags)
|
||||
{
|
||||
if (sDefaultFeaturesDescriptor == nullptr) {
|
||||
const std::pair<SInt16,SInt16> kDefaultFeatures[] = {
|
||||
{ kSmartSwashType, kLineInitialSwashesOffSelector },
|
||||
{ kSmartSwashType, kLineFinalSwashesOffSelector }
|
||||
};
|
||||
static_assert(ArrayLength(kDefaultFeatures) <= MAX_FEATURES,
|
||||
"need to increase MAX_FEATURES");
|
||||
sDefaultFeaturesDescriptor =
|
||||
CreateFontFeaturesDescriptor(kDefaultFeatures,
|
||||
ArrayLength(kDefaultFeatures));
|
||||
MOZ_ASSERT(aFeatureFlags < kMaxFontInstances);
|
||||
if (!sFeaturesDescriptor[aFeatureFlags]) {
|
||||
typedef std::pair<SInt16,SInt16> FeatT;
|
||||
AutoTArray<FeatT,MAX_FEATURES> features;
|
||||
features.AppendElement(FeatT(kSmartSwashType,
|
||||
kLineFinalSwashesOffSelector));
|
||||
if ((aFeatureFlags & kIndicFeatures) == 0) {
|
||||
features.AppendElement(FeatT(kSmartSwashType,
|
||||
kLineInitialSwashesOffSelector));
|
||||
}
|
||||
if (aFeatureFlags & kAddSmallCaps) {
|
||||
features.AppendElement(FeatT(kLetterCaseType,
|
||||
kSmallCapsSelector));
|
||||
features.AppendElement(FeatT(kLowerCaseType,
|
||||
kLowerCaseSmallCapsSelector));
|
||||
}
|
||||
if (aFeatureFlags & kDisableLigatures) {
|
||||
features.AppendElement(FeatT(kLigaturesType,
|
||||
kCommonLigaturesOffSelector));
|
||||
}
|
||||
MOZ_ASSERT(features.Length() <= MAX_FEATURES);
|
||||
sFeaturesDescriptor[aFeatureFlags] =
|
||||
CreateFontFeaturesDescriptor(features.Elements(),
|
||||
features.Length());
|
||||
}
|
||||
return sDefaultFeaturesDescriptor;
|
||||
}
|
||||
|
||||
CTFontDescriptorRef
|
||||
gfxCoreTextShaper::GetSmallCapsDescriptor()
|
||||
{
|
||||
if (sSmallCapsDescriptor == nullptr) {
|
||||
const std::pair<SInt16,SInt16> kSmallCaps[] = {
|
||||
{ kSmartSwashType, kLineInitialSwashesOffSelector },
|
||||
{ kSmartSwashType, kLineFinalSwashesOffSelector },
|
||||
{ kLetterCaseType, kSmallCapsSelector },
|
||||
{ kLowerCaseType, kLowerCaseSmallCapsSelector }
|
||||
};
|
||||
static_assert(ArrayLength(kSmallCaps) <= MAX_FEATURES,
|
||||
"need to increase MAX_FEATURES");
|
||||
sSmallCapsDescriptor =
|
||||
CreateFontFeaturesDescriptor(kSmallCaps,
|
||||
ArrayLength(kSmallCaps));
|
||||
}
|
||||
return sSmallCapsDescriptor;
|
||||
}
|
||||
|
||||
CTFontDescriptorRef
|
||||
gfxCoreTextShaper::GetDisableLigaturesDescriptor()
|
||||
{
|
||||
if (sDisableLigaturesDescriptor == nullptr) {
|
||||
const std::pair<SInt16,SInt16> kDisableLigatures[] = {
|
||||
{ kSmartSwashType, kLineInitialSwashesOffSelector },
|
||||
{ kSmartSwashType, kLineFinalSwashesOffSelector },
|
||||
{ kLigaturesType, kCommonLigaturesOffSelector }
|
||||
};
|
||||
static_assert(ArrayLength(kDisableLigatures) <= MAX_FEATURES,
|
||||
"need to increase MAX_FEATURES");
|
||||
sDisableLigaturesDescriptor =
|
||||
CreateFontFeaturesDescriptor(kDisableLigatures,
|
||||
ArrayLength(kDisableLigatures));
|
||||
}
|
||||
return sDisableLigaturesDescriptor;
|
||||
}
|
||||
|
||||
CTFontDescriptorRef
|
||||
gfxCoreTextShaper::GetSmallCapDisableLigDescriptor()
|
||||
{
|
||||
if (sSmallCapDisableLigDescriptor == nullptr) {
|
||||
const std::pair<SInt16,SInt16> kFeatures[] = {
|
||||
{ kSmartSwashType, kLineInitialSwashesOffSelector },
|
||||
{ kSmartSwashType, kLineFinalSwashesOffSelector },
|
||||
{ kLigaturesType, kCommonLigaturesOffSelector },
|
||||
{ kLetterCaseType, kSmallCapsSelector },
|
||||
{ kLowerCaseType, kLowerCaseSmallCapsSelector }
|
||||
};
|
||||
static_assert(ArrayLength(kFeatures) <= MAX_FEATURES,
|
||||
"need to increase MAX_FEATURES");
|
||||
sSmallCapDisableLigDescriptor =
|
||||
CreateFontFeaturesDescriptor(kFeatures,
|
||||
ArrayLength(kFeatures));
|
||||
}
|
||||
return sSmallCapDisableLigDescriptor;
|
||||
}
|
||||
|
||||
CTFontDescriptorRef
|
||||
gfxCoreTextShaper::GetIndicFeaturesDescriptor()
|
||||
{
|
||||
if (sIndicFeaturesDescriptor == nullptr) {
|
||||
const std::pair<SInt16,SInt16> kIndicFeatures[] = {
|
||||
{ kSmartSwashType, kLineFinalSwashesOffSelector }
|
||||
};
|
||||
static_assert(ArrayLength(kIndicFeatures) <= MAX_FEATURES,
|
||||
"need to increase MAX_FEATURES");
|
||||
sIndicFeaturesDescriptor =
|
||||
CreateFontFeaturesDescriptor(kIndicFeatures,
|
||||
ArrayLength(kIndicFeatures));
|
||||
}
|
||||
return sIndicFeaturesDescriptor;
|
||||
}
|
||||
|
||||
CTFontDescriptorRef
|
||||
gfxCoreTextShaper::GetIndicDisableLigaturesDescriptor()
|
||||
{
|
||||
if (sIndicDisableLigaturesDescriptor == nullptr) {
|
||||
const std::pair<SInt16,SInt16> kIndicDisableLigatures[] = {
|
||||
{ kSmartSwashType, kLineFinalSwashesOffSelector },
|
||||
{ kLigaturesType, kCommonLigaturesOffSelector }
|
||||
};
|
||||
static_assert(ArrayLength(kIndicDisableLigatures) <= MAX_FEATURES,
|
||||
"need to increase MAX_FEATURES");
|
||||
sIndicDisableLigaturesDescriptor =
|
||||
CreateFontFeaturesDescriptor(kIndicDisableLigatures,
|
||||
ArrayLength(kIndicDisableLigatures));
|
||||
}
|
||||
return sIndicDisableLigaturesDescriptor;
|
||||
return sFeaturesDescriptor[aFeatureFlags];
|
||||
}
|
||||
|
||||
CTFontRef
|
||||
@ -755,20 +674,10 @@ gfxCoreTextShaper::CreateCTFontWithFeatures(CGFloat aSize,
|
||||
void
|
||||
gfxCoreTextShaper::Shutdown() // [static]
|
||||
{
|
||||
if (sIndicDisableLigaturesDescriptor != nullptr) {
|
||||
::CFRelease(sIndicDisableLigaturesDescriptor);
|
||||
sIndicDisableLigaturesDescriptor = nullptr;
|
||||
}
|
||||
if (sIndicFeaturesDescriptor != nullptr) {
|
||||
::CFRelease(sIndicFeaturesDescriptor);
|
||||
sIndicFeaturesDescriptor = nullptr;
|
||||
}
|
||||
if (sDisableLigaturesDescriptor != nullptr) {
|
||||
::CFRelease(sDisableLigaturesDescriptor);
|
||||
sDisableLigaturesDescriptor = nullptr;
|
||||
}
|
||||
if (sDefaultFeaturesDescriptor != nullptr) {
|
||||
::CFRelease(sDefaultFeaturesDescriptor);
|
||||
sDefaultFeaturesDescriptor = nullptr;
|
||||
for (size_t i = 0; i < kMaxFontInstances; i++) {
|
||||
if (sFeaturesDescriptor[i] != nullptr) {
|
||||
::CFRelease(sFeaturesDescriptor[i]);
|
||||
sFeaturesDescriptor[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,8 +30,23 @@ public:
|
||||
// clean up static objects that may have been cached
|
||||
static void Shutdown();
|
||||
|
||||
// Flags used to track what AAT features should be enabled on the Core Text
|
||||
// font instance. (Internal; only public so that we can use the
|
||||
// MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS macro below.)
|
||||
enum FeatureFlags : uint8_t {
|
||||
kDefaultFeatures = 0x00,
|
||||
// bit flags for non-default feature settings we might need
|
||||
// to use, which will require separate font instances
|
||||
kDisableLigatures = 0x01,
|
||||
kAddSmallCaps = 0x02,
|
||||
kIndicFeatures = 0x04,
|
||||
|
||||
// number of font instances, indexed by OR-ing the flags above
|
||||
kMaxFontInstances = 8
|
||||
};
|
||||
|
||||
protected:
|
||||
CTFontRef mCTFont;
|
||||
CTFontRef mCTFont[kMaxFontInstances];
|
||||
|
||||
// attributes for shaping text with LTR or RTL directionality
|
||||
CFDictionaryRef mAttributesDictLTR;
|
||||
@ -49,27 +64,15 @@ protected:
|
||||
CFDictionaryRef CreateAttrDictWithoutDirection();
|
||||
|
||||
static CTFontDescriptorRef
|
||||
CreateFontFeaturesDescriptor(const std::pair<SInt16,SInt16> aFeatures[],
|
||||
CreateFontFeaturesDescriptor(const std::pair<SInt16,SInt16>* aFeatures,
|
||||
size_t aCount);
|
||||
|
||||
static CTFontDescriptorRef GetDefaultFeaturesDescriptor();
|
||||
static CTFontDescriptorRef GetSmallCapsDescriptor();
|
||||
static CTFontDescriptorRef GetDisableLigaturesDescriptor();
|
||||
static CTFontDescriptorRef GetSmallCapDisableLigDescriptor();
|
||||
static CTFontDescriptorRef GetIndicFeaturesDescriptor();
|
||||
static CTFontDescriptorRef GetIndicDisableLigaturesDescriptor();
|
||||
static CTFontDescriptorRef GetFeaturesDescriptor(FeatureFlags aFeatureFlags);
|
||||
|
||||
// cached font descriptor, created the first time it's needed
|
||||
static CTFontDescriptorRef sDefaultFeaturesDescriptor;
|
||||
static CTFontDescriptorRef sSmallCapsDescriptor;
|
||||
|
||||
// cached descriptor for adding disable-ligatures setting to a font
|
||||
static CTFontDescriptorRef sDisableLigaturesDescriptor;
|
||||
static CTFontDescriptorRef sSmallCapDisableLigDescriptor;
|
||||
|
||||
// feature descriptors for buggy Indic AAT font workaround
|
||||
static CTFontDescriptorRef sIndicFeaturesDescriptor;
|
||||
static CTFontDescriptorRef sIndicDisableLigaturesDescriptor;
|
||||
// cached font descriptors, created the first time they're needed
|
||||
static CTFontDescriptorRef sFeaturesDescriptor[kMaxFontInstances];
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxCoreTextShaper::FeatureFlags)
|
||||
|
||||
#endif /* GFX_CORETEXTSHAPER_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user