mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset a7c9fc3f1701 (bug 739117) for unexpected Core Text crashes.
This commit is contained in:
parent
10d0d51196
commit
76655c01d7
@ -13,8 +13,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// standard font descriptors that we construct the first time they're needed
|
||||
@ -23,75 +21,28 @@ CTFontDescriptorRef gfxCoreTextShaper::sDisableLigaturesDescriptor = nullptr;
|
||||
CTFontDescriptorRef gfxCoreTextShaper::sIndicFeaturesDescriptor = nullptr;
|
||||
CTFontDescriptorRef gfxCoreTextShaper::sIndicDisableLigaturesDescriptor = nullptr;
|
||||
|
||||
static CFStringRef sCTWritingDirectionAttributeName = nullptr;
|
||||
|
||||
// See CTStringAttributes.h
|
||||
enum {
|
||||
kMyCTWritingDirectionEmbedding = (0 << 1),
|
||||
kMyCTWritingDirectionOverride = (1 << 1)
|
||||
};
|
||||
|
||||
// Helper to create a CFDictionary with the right attributes for shaping our
|
||||
// text, including imposing the given directionality.
|
||||
// This will only be called if we're on 10.8 or later.
|
||||
CFDictionaryRef
|
||||
gfxCoreTextShaper::CreateAttrDict(bool aRightToLeft)
|
||||
{
|
||||
// Because we always shape unidirectional runs, and may have applied
|
||||
// directional overrides, we want to force a direction rather than
|
||||
// allowing CoreText to do its own unicode-based bidi processing.
|
||||
SInt16 dirOverride = kMyCTWritingDirectionOverride |
|
||||
(aRightToLeft ? kCTWritingDirectionRightToLeft
|
||||
: kCTWritingDirectionLeftToRight);
|
||||
CFNumberRef dirNumber =
|
||||
::CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberSInt16Type, &dirOverride);
|
||||
CFArrayRef dirArray =
|
||||
::CFArrayCreate(kCFAllocatorDefault,
|
||||
(const void **) &dirNumber, 1,
|
||||
&kCFTypeArrayCallBacks);
|
||||
::CFRelease(dirNumber);
|
||||
CFTypeRef attrs[] = { kCTFontAttributeName, sCTWritingDirectionAttributeName };
|
||||
CFTypeRef values[] = { mCTFont, dirArray };
|
||||
CFDictionaryRef attrDict =
|
||||
::CFDictionaryCreate(kCFAllocatorDefault,
|
||||
attrs, values, ArrayLength(attrs),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
::CFRelease(dirArray);
|
||||
return attrDict;
|
||||
}
|
||||
|
||||
CFDictionaryRef
|
||||
gfxCoreTextShaper::CreateAttrDictWithoutDirection()
|
||||
{
|
||||
CFTypeRef attrs[] = { kCTFontAttributeName };
|
||||
CFTypeRef values[] = { mCTFont };
|
||||
CFDictionaryRef attrDict =
|
||||
::CFDictionaryCreate(kCFAllocatorDefault,
|
||||
attrs, values, ArrayLength(attrs),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
return attrDict;
|
||||
}
|
||||
|
||||
gfxCoreTextShaper::gfxCoreTextShaper(gfxMacFont *aFont)
|
||||
: gfxFontShaper(aFont)
|
||||
, mAttributesDictLTR(nullptr)
|
||||
, mAttributesDictRTL(nullptr)
|
||||
{
|
||||
// Create our CTFontRef
|
||||
mCTFont = CreateCTFontWithFeatures(aFont->GetAdjustedSize(),
|
||||
GetDefaultFeaturesDescriptor());
|
||||
|
||||
// Set up the default attribute dictionary that we will need each time we
|
||||
// create a CFAttributedString (unless we need to use custom features,
|
||||
// in which case a new dictionary will be created on the fly).
|
||||
mAttributesDict = ::CFDictionaryCreate(kCFAllocatorDefault,
|
||||
(const void**) &kCTFontAttributeName,
|
||||
(const void**) &mCTFont,
|
||||
1, // count of attributes
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
}
|
||||
|
||||
gfxCoreTextShaper::~gfxCoreTextShaper()
|
||||
{
|
||||
if (mAttributesDictLTR) {
|
||||
::CFRelease(mAttributesDictLTR);
|
||||
}
|
||||
if (mAttributesDictRTL) {
|
||||
::CFRelease(mAttributesDictRTL);
|
||||
if (mAttributesDict) {
|
||||
::CFRelease(mAttributesDict);
|
||||
}
|
||||
if (mCTFont) {
|
||||
::CFRelease(mCTFont);
|
||||
@ -114,83 +65,54 @@ gfxCoreTextShaper::ShapeText(gfxContext *aContext,
|
||||
gfxShapedText *aShapedText)
|
||||
{
|
||||
// Create a CFAttributedString with text and style info, so we can use CoreText to lay it out.
|
||||
|
||||
bool isRightToLeft = aShapedText->IsRightToLeft();
|
||||
const UniChar* text = reinterpret_cast<const UniChar*>(aText);
|
||||
uint32_t length = aLength;
|
||||
|
||||
// we need to bidi-wrap the text if the run is RTL,
|
||||
// or if it is an LTR run but may contain (overridden) RTL chars
|
||||
bool bidiWrap = isRightToLeft;
|
||||
if (!bidiWrap && !aShapedText->TextIs8Bit()) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < length; ++i) {
|
||||
if (gfxFontUtils::PotentialRTLChar(aText[i])) {
|
||||
bidiWrap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there's a possibility of any bidi, we wrap the text with direction overrides
|
||||
// to ensure neutrals or characters that were bidi-overridden in HTML behave properly.
|
||||
const UniChar beginLTR[] = { 0x202d, 0x20 };
|
||||
const UniChar beginRTL[] = { 0x202e, 0x20 };
|
||||
const UniChar endBidiWrap[] = { 0x20, 0x2e, 0x202c };
|
||||
|
||||
uint32_t startOffset;
|
||||
CFStringRef stringObj;
|
||||
CFDictionaryRef attrObj;
|
||||
|
||||
sCTWritingDirectionAttributeName =
|
||||
(CFStringRef)dlsym(RTLD_DEFAULT, "kCTWritingDirectionAttributeName");
|
||||
if (sCTWritingDirectionAttributeName) {
|
||||
if (bidiWrap) {
|
||||
startOffset = isRightToLeft ?
|
||||
mozilla::ArrayLength(beginRTL) : mozilla::ArrayLength(beginLTR);
|
||||
CFMutableStringRef mutableString =
|
||||
::CFStringCreateMutable(kCFAllocatorDefault,
|
||||
length + startOffset + mozilla::ArrayLength(endBidiWrap));
|
||||
::CFStringAppendCharacters(mutableString,
|
||||
isRightToLeft ? beginRTL : beginLTR,
|
||||
startOffset);
|
||||
::CFStringAppendCharacters(mutableString, reinterpret_cast<const UniChar*>(aText), length);
|
||||
::CFStringAppendCharacters(mutableString,
|
||||
endBidiWrap, mozilla::ArrayLength(endBidiWrap));
|
||||
stringObj = mutableString;
|
||||
} else {
|
||||
startOffset = 0;
|
||||
stringObj = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
|
||||
text, length,
|
||||
kCFAllocatorNull);
|
||||
|
||||
// Get an attributes dictionary suitable for shaping text in the
|
||||
// current direction, creating it if necessary.
|
||||
attrObj = isRightToLeft ? mAttributesDictRTL : mAttributesDictLTR;
|
||||
if (!attrObj) {
|
||||
attrObj = CreateAttrDict(isRightToLeft);
|
||||
(isRightToLeft ? mAttributesDictRTL : mAttributesDictLTR) = attrObj;
|
||||
}
|
||||
} else {
|
||||
// OS is too old to support kCTWritingDirectionAttributeName:
|
||||
// we need to bidi-wrap the text if the run is RTL,
|
||||
// or if it is an LTR run but may contain (overridden) RTL chars
|
||||
bool bidiWrap = isRightToLeft;
|
||||
if (!bidiWrap && !aShapedText->TextIs8Bit()) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < length; ++i) {
|
||||
if (gfxFontUtils::PotentialRTLChar(aText[i])) {
|
||||
bidiWrap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there's a possibility of any bidi, we wrap the text with
|
||||
// direction overrides to ensure neutrals or characters that were
|
||||
// bidi-overridden in HTML behave properly.
|
||||
static const UniChar beginLTR[] = { 0x202d, 0x20 };
|
||||
static const UniChar beginRTL[] = { 0x202e, 0x20 };
|
||||
static const UniChar endBidiWrap[] = { 0x20, 0x2e, 0x202c };
|
||||
|
||||
if (bidiWrap) {
|
||||
startOffset = isRightToLeft ? ArrayLength(beginRTL)
|
||||
: ArrayLength(beginLTR);
|
||||
CFMutableStringRef mutableString =
|
||||
::CFStringCreateMutable(kCFAllocatorDefault,
|
||||
length + startOffset +
|
||||
ArrayLength(endBidiWrap));
|
||||
::CFStringAppendCharacters(mutableString,
|
||||
isRightToLeft ? beginRTL : beginLTR,
|
||||
startOffset);
|
||||
::CFStringAppendCharacters(mutableString, text, length);
|
||||
::CFStringAppendCharacters(mutableString, endBidiWrap,
|
||||
ArrayLength(endBidiWrap));
|
||||
stringObj = mutableString;
|
||||
} else {
|
||||
startOffset = 0;
|
||||
stringObj =
|
||||
::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
|
||||
text, length,
|
||||
kCFAllocatorNull);
|
||||
}
|
||||
|
||||
// Get an attributes dictionary suitable for shaping text,
|
||||
// creating it if necessary. (This dict is not LTR-specific,
|
||||
// but we use that field to store it anyway.)
|
||||
if (!mAttributesDictLTR) {
|
||||
mAttributesDictLTR = CreateAttrDictWithoutDirection();
|
||||
}
|
||||
attrObj = mAttributesDictLTR;
|
||||
reinterpret_cast<const UniChar*>(aText),
|
||||
length, kCFAllocatorNull);
|
||||
}
|
||||
|
||||
CFDictionaryRef attrObj;
|
||||
CTFontRef tempCTFont = nullptr;
|
||||
|
||||
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
|
||||
@ -210,18 +132,21 @@ gfxCoreTextShaper::ShapeText(gfxContext *aContext,
|
||||
GetDisableLigaturesDescriptor());
|
||||
}
|
||||
|
||||
// For the disabled-ligature or buggy-indic-font case, we need to replace
|
||||
// the standard CTFont in the attribute dictionary with a tweaked version.
|
||||
CFMutableDictionaryRef mutableAttr = nullptr;
|
||||
if (tempCTFont) {
|
||||
mutableAttr = ::CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 2,
|
||||
attrObj);
|
||||
::CFDictionaryReplaceValue(mutableAttr,
|
||||
kCTFontAttributeName, tempCTFont);
|
||||
attrObj =
|
||||
::CFDictionaryCreate(kCFAllocatorDefault,
|
||||
(const void**) &kCTFontAttributeName,
|
||||
(const void**) &tempCTFont,
|
||||
1, // count of attributes
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
// Having created the dict, we're finished with our temporary
|
||||
// Indic and/or ligature-disabled CTFontRef.
|
||||
::CFRelease(tempCTFont);
|
||||
attrObj = mutableAttr;
|
||||
} else {
|
||||
// The default case is to use our preallocated attr dict
|
||||
attrObj = mAttributesDict;
|
||||
::CFRetain(attrObj);
|
||||
}
|
||||
|
||||
// Now we can create an attributed string
|
||||
@ -255,10 +180,8 @@ gfxCoreTextShaper::ShapeText(gfxContext *aContext,
|
||||
// If Core Text manufactured a new dictionary, this may indicate
|
||||
// unexpected font substitution. In that case, we fail (and fall
|
||||
// back to harfbuzz shaping)...
|
||||
const void* font1 =
|
||||
::CFDictionaryGetValue(attrObj, kCTFontAttributeName);
|
||||
const void* font2 =
|
||||
::CFDictionaryGetValue(runAttr, kCTFontAttributeName);
|
||||
const void* font1 = ::CFDictionaryGetValue(attrObj, kCTFontAttributeName);
|
||||
const void* font2 = ::CFDictionaryGetValue(runAttr, kCTFontAttributeName);
|
||||
if (font1 != font2) {
|
||||
// ...except that if the fallback was only for a variation
|
||||
// selector or join control that is otherwise unsupported,
|
||||
@ -275,16 +198,13 @@ gfxCoreTextShaper::ShapeText(gfxContext *aContext,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (SetGlyphsFromRun(aShapedText, aOffset, aLength, aCTRun,
|
||||
startOffset) != NS_OK) {
|
||||
if (SetGlyphsFromRun(aShapedText, aOffset, aLength, aCTRun, startOffset) != NS_OK) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mutableAttr) {
|
||||
::CFRelease(mutableAttr);
|
||||
}
|
||||
::CFRelease(attrObj);
|
||||
::CFRelease(line);
|
||||
|
||||
return success;
|
||||
|
@ -31,10 +31,7 @@ public:
|
||||
|
||||
protected:
|
||||
CTFontRef mCTFont;
|
||||
|
||||
// attributes for shaping text with LTR or RTL directionality
|
||||
CFDictionaryRef mAttributesDictLTR;
|
||||
CFDictionaryRef mAttributesDictRTL;
|
||||
CFDictionaryRef mAttributesDict;
|
||||
|
||||
nsresult SetGlyphsFromRun(gfxShapedText *aShapedText,
|
||||
uint32_t aOffset,
|
||||
@ -45,9 +42,6 @@ protected:
|
||||
CTFontRef CreateCTFontWithFeatures(CGFloat aSize,
|
||||
CTFontDescriptorRef aDescriptor);
|
||||
|
||||
CFDictionaryRef CreateAttrDict(bool aRightToLeft);
|
||||
CFDictionaryRef CreateAttrDictWithoutDirection();
|
||||
|
||||
static CTFontDescriptorRef
|
||||
CreateFontFeaturesDescriptor(const std::pair<SInt16,SInt16> aFeatures[],
|
||||
size_t aCount);
|
||||
|
@ -165,7 +165,7 @@ fails-if(cocoaWidget||Android||B2G) HTTP(..) == arabic-fallback-2.html arabic-fa
|
||||
fails-if(cocoaWidget||Android||B2G) HTTP(..) == arabic-fallback-3.html arabic-fallback-3-ref.html
|
||||
fails-if(!cocoaWidget&&!Android&&!B2G) HTTP(..) != arabic-fallback-4.html arabic-fallback-4-notref.html
|
||||
== arabic-marks-1.html arabic-marks-1-ref.html
|
||||
fails-if(OSX<1008) == arabic-final-ligature-spacing.html arabic-final-ligature-spacing-ref.html
|
||||
fails-if(cocoaWidget) == arabic-final-ligature-spacing.html arabic-final-ligature-spacing-ref.html # bug 739117
|
||||
# harfbuzz fallback mark stacking in the absence of GPOS:
|
||||
HTTP(..) != fallback-mark-stacking-1.html fallback-mark-stacking-1-notref.html
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user