Remove QCoreTextFontEngineMulti
It's not used anymore since we have switch to HarfBuzz on Mac. Change-Id: I68252fbe3021f54dacac5a901184c3f3e541a6b7 Reviewed-by: Jiang Jiang <jiang.jiang@nokia.com> Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
This commit is contained in:
parent
6887a7e395
commit
d05b6b6e95
@ -77,329 +77,6 @@ static void loadAdvancesForGlyphs(CTFontRef ctfont,
|
||||
}
|
||||
}
|
||||
|
||||
QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning)
|
||||
: QFontEngineMulti(0)
|
||||
{
|
||||
this->fontDef = fontDef;
|
||||
CTFontSymbolicTraits symbolicTraits = 0;
|
||||
if (fontDef.weight >= QFont::Bold)
|
||||
symbolicTraits |= kCTFontBoldTrait;
|
||||
switch (fontDef.style) {
|
||||
case QFont::StyleNormal:
|
||||
break;
|
||||
case QFont::StyleItalic:
|
||||
case QFont::StyleOblique:
|
||||
symbolicTraits |= kCTFontItalicTrait;
|
||||
break;
|
||||
}
|
||||
|
||||
transform = CGAffineTransformIdentity;
|
||||
if (fontDef.stretch != 100) {
|
||||
transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
|
||||
}
|
||||
|
||||
QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pixelSize);
|
||||
QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pixelSize, &transform);
|
||||
ctfont = NULL;
|
||||
// There is a side effect in Core Text: if we apply 0 as symbolic traits to a font in normal weight,
|
||||
// we will get the light version of that font (while the way supposed to work doesn't:
|
||||
// setting kCTFontWeightTrait to some value between -1.0 to 0.0 has no effect on font selection)
|
||||
if (fontDef.weight != QFont::Normal || symbolicTraits)
|
||||
ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, &transform, symbolicTraits, symbolicTraits);
|
||||
|
||||
// CTFontCreateCopyWithSymbolicTraits returns NULL if we ask for a trait that does
|
||||
// not exist for the given font. (for example italic)
|
||||
if (ctfont == 0) {
|
||||
ctfont = baseFont;
|
||||
CFRetain(ctfont);
|
||||
}
|
||||
init(kerning);
|
||||
}
|
||||
|
||||
QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(CTFontRef ctFontRef, const QFontDef &fontDef, bool kerning)
|
||||
: QFontEngineMulti(0)
|
||||
{
|
||||
this->fontDef = fontDef;
|
||||
ctfont = (CTFontRef) CFRetain(ctFontRef);
|
||||
init(kerning);
|
||||
}
|
||||
|
||||
QCoreTextFontEngineMulti::~QCoreTextFontEngineMulti()
|
||||
{
|
||||
CFRelease(ctfont);
|
||||
}
|
||||
|
||||
void QCoreTextFontEngineMulti::init(bool kerning)
|
||||
{
|
||||
Q_ASSERT(ctfont != NULL);
|
||||
attributeDict = CFDictionaryCreateMutable(0, 2,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFDictionaryAddValue(attributeDict, kCTFontAttributeName, ctfont);
|
||||
if (!kerning) {
|
||||
float zero = 0.0;
|
||||
QCFType<CFNumberRef> noKern = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero);
|
||||
CFDictionaryAddValue(attributeDict, kCTKernAttributeName, noKern);
|
||||
}
|
||||
|
||||
QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef);
|
||||
fontDef.family = fe->fontDef.family;
|
||||
fontDef.styleName = fe->fontDef.styleName;
|
||||
transform = fe->transform;
|
||||
fe->ref.ref();
|
||||
engines.append(fe);
|
||||
}
|
||||
|
||||
uint QCoreTextFontEngineMulti::fontIndexForFont(CTFontRef font) const
|
||||
{
|
||||
for (int i = 0; i < engines.count(); ++i) {
|
||||
if (CFEqual(engineAt(i)->ctfont, font))
|
||||
return i;
|
||||
}
|
||||
|
||||
QCoreTextFontEngineMulti *that = const_cast<QCoreTextFontEngineMulti *>(this);
|
||||
QCoreTextFontEngine *fe = new QCoreTextFontEngine(font, fontDef);
|
||||
fe->ref.ref();
|
||||
that->engines.append(fe);
|
||||
return engines.count() - 1;
|
||||
}
|
||||
|
||||
bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
|
||||
int *nglyphs, QTextEngine::ShaperFlags flags,
|
||||
unsigned short *logClusters, const HB_CharAttributes *,
|
||||
QScriptItem *si) const
|
||||
{
|
||||
QCFType<CFStringRef> cfstring = CFStringCreateWithCharactersNoCopy(0,
|
||||
reinterpret_cast<const UniChar *>(str),
|
||||
len, kCFAllocatorNull);
|
||||
QCFType<CFAttributedStringRef> attributedString = CFAttributedStringCreate(0, cfstring, attributeDict);
|
||||
QCFType<CTTypesetterRef> typeSetter;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
if (flags & QTextEngine::RightToLeft) {
|
||||
const void *optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
|
||||
const short rtlForcedEmbeddingLevelValue = 1;
|
||||
const void *rtlOptionValues[] = { CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &rtlForcedEmbeddingLevelValue) };
|
||||
QCFType<CFDictionaryRef> options = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, 1,
|
||||
&kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
typeSetter = CTTypesetterCreateWithAttributedStringAndOptions(attributedString, options);
|
||||
} else
|
||||
#else
|
||||
Q_UNUSED(flags);
|
||||
#endif
|
||||
typeSetter = CTTypesetterCreateWithAttributedString(attributedString);
|
||||
|
||||
CFRange range = {0, 0};
|
||||
QCFType<CTLineRef> line = CTTypesetterCreateLine(typeSetter, range);
|
||||
CFArrayRef array = CTLineGetGlyphRuns(line);
|
||||
uint arraySize = CFArrayGetCount(array);
|
||||
glyph_t *outGlyphs = glyphs->glyphs;
|
||||
HB_GlyphAttributes *outAttributes = glyphs->attributes;
|
||||
QFixed *outAdvances_x = glyphs->advances_x;
|
||||
QFixed *outAdvances_y = glyphs->advances_y;
|
||||
glyph_t *initialGlyph = outGlyphs;
|
||||
|
||||
if (arraySize == 0) {
|
||||
// CoreText failed to shape the text we gave it, so we assume one glyph
|
||||
// per character and build a list of invalid glyphs with zero advance
|
||||
*nglyphs = len;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
outGlyphs[i] = 0;
|
||||
if (logClusters)
|
||||
logClusters[i] = i;
|
||||
outAdvances_x[i] = QFixed();
|
||||
outAdvances_y[i] = QFixed();
|
||||
outAttributes[i].clusterStart = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool rtl = (CTRunGetStatus(static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, 0))) & kCTRunStatusRightToLeft);
|
||||
|
||||
bool outOBounds = false;
|
||||
for (uint i = 0; i < arraySize; ++i) {
|
||||
CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, rtl ? (arraySize - 1 - i) : i));
|
||||
CFIndex glyphCount = CTRunGetGlyphCount(run);
|
||||
if (glyphCount == 0)
|
||||
continue;
|
||||
|
||||
Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl);
|
||||
CFRange stringRange = CTRunGetStringRange(run);
|
||||
int prepend = 0;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5
|
||||
UniChar beginGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location);
|
||||
QChar dir = QChar::direction(beginGlyph);
|
||||
bool beginWithOverride = dir == QChar::DirLRO || dir == QChar::DirRLO || dir == QChar::DirLRE || dir == QChar::DirRLE;
|
||||
if (beginWithOverride) {
|
||||
logClusters[stringRange.location] = 0;
|
||||
outGlyphs[0] = 0xFFFF;
|
||||
outAdvances_x[0] = 0;
|
||||
outAdvances_y[0] = 0;
|
||||
outAttributes[0].clusterStart = true;
|
||||
outAttributes[0].dontPrint = true;
|
||||
outGlyphs++;
|
||||
outAdvances_x++;
|
||||
outAdvances_y++;
|
||||
outAttributes++;
|
||||
prepend = 1;
|
||||
}
|
||||
#endif
|
||||
UniChar endGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location + stringRange.length - 1);
|
||||
bool endWithPDF = QChar::direction(endGlyph) == QChar::DirPDF;
|
||||
if (endWithPDF)
|
||||
glyphCount++;
|
||||
|
||||
if (!outOBounds && outGlyphs + glyphCount - initialGlyph > *nglyphs) {
|
||||
outOBounds = true;
|
||||
}
|
||||
if (!outOBounds) {
|
||||
CFDictionaryRef runAttribs = CTRunGetAttributes(run);
|
||||
//NSLog(@"Dictionary %@", runAttribs);
|
||||
if (!runAttribs)
|
||||
runAttribs = attributeDict;
|
||||
CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(runAttribs, kCTFontAttributeName));
|
||||
uint fontIndex = fontIndexForFont(runFont);
|
||||
const QFontEngine *engine = engineAt(fontIndex);
|
||||
fontIndex <<= 24;
|
||||
si->ascent = qMax(engine->ascent(), si->ascent);
|
||||
si->descent = qMax(engine->descent(), si->descent);
|
||||
si->leading = qMax(engine->leading(), si->leading);
|
||||
//NSLog(@"Run Font Name = %@", CTFontCopyFamilyName(runFont));
|
||||
if (endWithPDF)
|
||||
glyphCount--;
|
||||
|
||||
QVarLengthArray<CGGlyph, 512> cgglyphs(0);
|
||||
const CGGlyph *tmpGlyphs = CTRunGetGlyphsPtr(run);
|
||||
if (!tmpGlyphs) {
|
||||
cgglyphs.resize(glyphCount);
|
||||
CTRunGetGlyphs(run, range, cgglyphs.data());
|
||||
tmpGlyphs = cgglyphs.constData();
|
||||
}
|
||||
QVarLengthArray<CGPoint, 512> cgpoints(0);
|
||||
const CGPoint *tmpPoints = CTRunGetPositionsPtr(run);
|
||||
if (!tmpPoints) {
|
||||
cgpoints.resize(glyphCount);
|
||||
CTRunGetPositions(run, range, cgpoints.data());
|
||||
tmpPoints = cgpoints.constData();
|
||||
}
|
||||
|
||||
const int rtlOffset = rtl ? (glyphCount - 1) : 0;
|
||||
const int rtlSign = rtl ? -1 : 1;
|
||||
|
||||
if (logClusters) {
|
||||
CFRange stringRange = CTRunGetStringRange(run);
|
||||
QVarLengthArray<CFIndex, 512> stringIndices(0);
|
||||
const CFIndex *tmpIndices = CTRunGetStringIndicesPtr(run);
|
||||
if (!tmpIndices) {
|
||||
stringIndices.resize(glyphCount);
|
||||
CTRunGetStringIndices(run, range, stringIndices.data());
|
||||
tmpIndices = stringIndices.constData();
|
||||
}
|
||||
|
||||
const int firstGlyphIndex = outGlyphs - initialGlyph;
|
||||
outAttributes[0].clusterStart = true;
|
||||
|
||||
CFIndex k = 0;
|
||||
CFIndex i = 0;
|
||||
for (i = stringRange.location + prepend;
|
||||
(i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) {
|
||||
if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location + prepend) {
|
||||
logClusters[i] = k + firstGlyphIndex;
|
||||
outAttributes[k].clusterStart = true;
|
||||
++k;
|
||||
} else {
|
||||
logClusters[i] = k + firstGlyphIndex - 1;
|
||||
}
|
||||
}
|
||||
// in case of a ligature at the end, fill the remaining logcluster entries
|
||||
for (;i < stringRange.location + stringRange.length; i++) {
|
||||
logClusters[i] = k + firstGlyphIndex - 1;
|
||||
}
|
||||
}
|
||||
for (CFIndex i = 0; i < glyphCount - 1; ++i) {
|
||||
int idx = rtlOffset + rtlSign * i;
|
||||
outGlyphs[idx] = tmpGlyphs[i] | fontIndex;
|
||||
outAdvances_x[idx] = QFixed::fromReal(tmpPoints[i + 1].x - tmpPoints[i].x);
|
||||
// Use negative y advance for flipped coordinate system
|
||||
outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i].y - tmpPoints[i + 1].y);
|
||||
|
||||
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
|
||||
outAdvances_x[idx] = outAdvances_x[idx].round();
|
||||
outAdvances_y[idx] = outAdvances_y[idx].round();
|
||||
}
|
||||
}
|
||||
CGSize lastGlyphAdvance;
|
||||
CTFontGetAdvancesForGlyphs(runFont, kCTFontHorizontalOrientation, tmpGlyphs + glyphCount - 1, &lastGlyphAdvance, 1);
|
||||
|
||||
outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex;
|
||||
outAdvances_x[rtl ? 0 : (glyphCount - 1)] =
|
||||
(fontDef.styleStrategy & QFont::ForceIntegerMetrics)
|
||||
? QFixed::fromReal(lastGlyphAdvance.width).round()
|
||||
: QFixed::fromReal(lastGlyphAdvance.width);
|
||||
|
||||
if (endWithPDF) {
|
||||
logClusters[stringRange.location + stringRange.length - 1] = glyphCount + prepend;
|
||||
outGlyphs[glyphCount] = 0xFFFF;
|
||||
outAdvances_x[glyphCount] = 0;
|
||||
outAdvances_y[glyphCount] = 0;
|
||||
outAttributes[glyphCount].clusterStart = true;
|
||||
outAttributes[glyphCount].dontPrint = true;
|
||||
glyphCount++;
|
||||
}
|
||||
}
|
||||
outGlyphs += glyphCount;
|
||||
outAttributes += glyphCount;
|
||||
outAdvances_x += glyphCount;
|
||||
outAdvances_y += glyphCount;
|
||||
}
|
||||
*nglyphs = (outGlyphs - initialGlyph);
|
||||
return !outOBounds;
|
||||
}
|
||||
|
||||
bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
|
||||
int *nglyphs, QTextEngine::ShaperFlags flags) const
|
||||
{
|
||||
*nglyphs = len;
|
||||
QCFType<CFStringRef> cfstring;
|
||||
|
||||
QVarLengthArray<CGGlyph> cgGlyphs(len);
|
||||
CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len);
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (cgGlyphs[i]) {
|
||||
glyphs->glyphs[i] = cgGlyphs[i];
|
||||
} else {
|
||||
if (!cfstring)
|
||||
cfstring = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(str), len, kCFAllocatorNull);
|
||||
QCFType<CTFontRef> substituteFont = CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 1));
|
||||
CGGlyph substituteGlyph = 0;
|
||||
CTFontGetGlyphsForCharacters(substituteFont, (const UniChar*)str + i, &substituteGlyph, 1);
|
||||
if (substituteGlyph) {
|
||||
const uint fontIndex = (fontIndexForFont(substituteFont) << 24);
|
||||
glyphs->glyphs[i] = substituteGlyph | fontIndex;
|
||||
if (!(flags & QTextEngine::GlyphIndicesOnly)) {
|
||||
CGSize advance;
|
||||
CTFontGetAdvancesForGlyphs(substituteFont, kCTFontHorizontalOrientation, &substituteGlyph, &advance, 1);
|
||||
glyphs->advances_x[i] = QFixed::fromReal(advance.width);
|
||||
glyphs->advances_y[i] = QFixed::fromReal(advance.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & QTextEngine::GlyphIndicesOnly)
|
||||
return true;
|
||||
|
||||
loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, len, flags, fontDef);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QCoreTextFontEngineMulti::loadEngine(int)
|
||||
{
|
||||
// Do nothing
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
||||
extern int qt_antialiasing_threshold, qt_enable_font_smoothing;
|
||||
|
||||
CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef)
|
||||
|
@ -53,7 +53,6 @@ QT_BEGIN_HEADER
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QRawFontPrivate;
|
||||
class QCoreTextFontEngineMulti;
|
||||
class QCoreTextFontEngine : public QFontEngine
|
||||
{
|
||||
public:
|
||||
@ -109,39 +108,6 @@ private:
|
||||
int synthesisFlags;
|
||||
CGAffineTransform transform;
|
||||
QFixed avgCharWidth;
|
||||
friend class QCoreTextFontEngineMulti;
|
||||
};
|
||||
|
||||
class QCoreTextFontEngineMulti : public QFontEngineMulti
|
||||
{
|
||||
public:
|
||||
QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning);
|
||||
QCoreTextFontEngineMulti(CTFontRef ctFontRef, const QFontDef &fontDef, bool kerning);
|
||||
~QCoreTextFontEngineMulti();
|
||||
|
||||
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
|
||||
QTextEngine::ShaperFlags flags) const;
|
||||
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
|
||||
QTextEngine::ShaperFlags flags,
|
||||
unsigned short *logClusters, const HB_CharAttributes *charAttributes,
|
||||
QScriptItem *si) const;
|
||||
|
||||
virtual const char *name() const { return "CoreText"; }
|
||||
inline CTFontRef macFontID() const { return ctfont; }
|
||||
|
||||
protected:
|
||||
virtual void loadEngine(int at);
|
||||
|
||||
private:
|
||||
void init(bool kerning);
|
||||
inline const QCoreTextFontEngine *engineAt(int i) const
|
||||
{ return static_cast<const QCoreTextFontEngine *>(engines.at(i)); }
|
||||
|
||||
uint fontIndexForFont(CTFontRef font) const;
|
||||
CTFontRef ctfont;
|
||||
mutable QCFType<CFMutableDictionaryRef> attributeDict;
|
||||
CGAffineTransform transform;
|
||||
friend class QFontDialogPrivate;
|
||||
};
|
||||
|
||||
CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef);
|
||||
|
Loading…
Reference in New Issue
Block a user