diff options
Diffstat (limited to 'src/gui/text/coretext/qfontengine_coretext.mm')
-rw-r--r-- | src/gui/text/coretext/qfontengine_coretext.mm | 88 |
1 files changed, 56 insertions, 32 deletions
diff --git a/src/gui/text/coretext/qfontengine_coretext.mm b/src/gui/text/coretext/qfontengine_coretext.mm index f15b413c11..1050c03d75 100644 --- a/src/gui/text/coretext/qfontengine_coretext.mm +++ b/src/gui/text/coretext/qfontengine_coretext.mm @@ -12,6 +12,9 @@ #include <QtGui/qpainterpath.h> #include <private/qcoregraphics_p.h> #include <private/qimage_p.h> +#include <private/qguiapplication_p.h> +#include <private/qstringiterator_p.h> +#include <qpa/qplatformtheme.h> #include <cmath> @@ -125,9 +128,13 @@ public: QByteArray m_fontData; }; -QCoreTextFontEngine *QCoreTextFontEngine::create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +QCoreTextFontEngine *QCoreTextFontEngine::create(const QByteArray &fontData, + qreal pixelSize, + QFont::HintingPreference hintingPreference, + const QMap<QFont::Tag, float> &variableAxisValues) { Q_UNUSED(hintingPreference); + Q_UNUSED(variableAxisValues); QCFType<CFDataRef> fontDataReference = fontData.toRawCFData(); QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithCFData(fontDataReference); @@ -186,6 +193,7 @@ void QCoreTextFontEngine::init() face_id.index = 0; QCFString name = CTFontCopyName(ctfont, kCTFontUniqueNameKey); face_id.filename = QString::fromCFString(name).toUtf8(); + face_id.variableAxes = fontDef.variableAxisValues; QCFString family = CTFontCopyFamilyName(ctfont); fontDef.families = QStringList(family); @@ -230,7 +238,7 @@ void QCoreTextFontEngine::init() synthesisFlags |= SynthesizedItalic; avgCharWidth = 0; - QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2')); + QByteArray os2Table = getSfntTable(QFont::Tag("OS/2").value()); unsigned emSize = CTFontGetUnitsPerEm(ctfont); if (os2Table.size() >= 10) { fsType = qFromBigEndian<quint16>(os2Table.constData() + 8); @@ -267,29 +275,30 @@ glyph_t QCoreTextFontEngine::glyphIndex(uint ucs4) const return glyphIndices[0]; } -bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, - int *nglyphs, QFontEngine::ShaperFlags flags) const +int QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, + int *nglyphs, QFontEngine::ShaperFlags flags) const { Q_ASSERT(glyphs->numGlyphs >= *nglyphs); if (*nglyphs < len) { *nglyphs = len; - return false; + return -1; } QVarLengthArray<CGGlyph> cgGlyphs(len); CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len); int glyph_pos = 0; - for (int i = 0; i < len; ++i) { - glyphs->glyphs[glyph_pos] = cgGlyphs[i]; - if (glyph_pos < i) - cgGlyphs[glyph_pos] = cgGlyphs[i]; - glyph_pos++; - - // If it's a non-BMP char, skip the lower part of surrogate pair and go - // directly to the next char without increasing glyph_pos - if (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate()) - ++i; + int mappedGlyphs = 0; + QStringIterator it(str, str + len); + while (it.hasNext()) { + qsizetype idx = it.index(); + char32_t ucs4 = it.next(); + glyphs->glyphs[glyph_pos] = cgGlyphs[idx]; + if (glyph_pos < idx) + cgGlyphs[glyph_pos] = cgGlyphs[idx]; + if (glyphs->glyphs[glyph_pos] != 0 || isIgnorableChar(ucs4)) + mappedGlyphs++; + glyph_pos++; } *nglyphs = glyph_pos; @@ -298,15 +307,7 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout * if (!(flags & GlyphIndicesOnly)) loadAdvancesForGlyphs(cgGlyphs, glyphs); - return true; -} - -glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs) -{ - QFixed w; - for (int i = 0; i < glyphs.numGlyphs; ++i) - w += glyphs.effectiveAdvance(i); - return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs), ascent()+descent(), w, 0); + return mappedGlyphs; } glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) @@ -370,6 +371,7 @@ bool QCoreTextFontEngine::hasColorGlyphs() const return glyphFormat == QFontEngine::Format_ARGB; } +Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) { QVarLengthArray<QFixedPoint> positions; @@ -386,7 +388,8 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight); - CGAffineTransformConcat(cgMatrix, oldTextMatrix); + // FIXME: Should we include the old matrix here? If so we need to assign it. + Q_UNUSED(CGAffineTransformConcat(cgMatrix, oldTextMatrix)); if (synthesisFlags & QFontEngine::SynthesizedItalic) cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); @@ -413,7 +416,15 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt CTFontDrawGlyphs(ctfont, cgGlyphs.data(), cgPositions.data(), glyphs.size(), ctx); if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(), + QTransform matrix(cgMatrix.a, cgMatrix.b, cgMatrix.c, cgMatrix.d, cgMatrix.tx, cgMatrix.ty); + + qreal boldOffset = 0.5 * lineThickness().toReal(); + qreal scale; + qt_scaleForTransform(matrix, &scale); + boldOffset *= scale; + + CGContextSetTextPosition(ctx, + positions[0].x.toReal() + boldOffset, positions[0].y.toReal()); CTFontDrawGlyphs(ctfont, cgGlyphs.data(), cgPositions.data(), glyphs.size(), ctx); } @@ -503,7 +514,11 @@ glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, const QF return QFontEngine::alphaMapBoundingBox(glyph, subPixelPosition, matrix, format); glyph_metrics_t br = boundingBox(glyph); - qcoretextfontengine_scaleMetrics(br, matrix); + + QTransform xform = matrix; + if (fontDef.stretch != 100 && fontDef.stretch != QFont::AnyStretch) + xform.scale(fontDef.stretch / 100.0, 1.0); + qcoretextfontengine_scaleMetrics(br, xform); // Normalize width and height if (br.width < 0) @@ -710,10 +725,12 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, const QFixedPoint &subP // draw with white or black fill, and then invert the glyph image in the latter case, // producing an alpha map. This covers the most common use-cases, but longer term we // should propagate the fill color all the way from the paint engine, and include it - //in the key for the glyph cache. + // in the key for the glyph cache. - if (!qt_mac_applicationIsInDarkMode()) - return kCGColorBlack; + if (auto *platformTheme = QGuiApplicationPrivate::platformTheme()) { + if (platformTheme->colorScheme() != Qt::ColorScheme::Dark) + return kCGColorBlack; + } } return kCGColorWhite; }(); @@ -756,7 +773,13 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, const QFixedPoint &subP CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx); if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y); + qreal boldOffset = 0.5 * lineThickness().toReal(); + + qreal scale; + qt_scaleForTransform(matrix, &scale); + boldOffset *= scale; + + CGContextSetTextPosition(ctx, pos_x + boldOffset, pos_y); CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx); } } else { @@ -848,8 +871,9 @@ void QCoreTextFontEngine::loadAdvancesForGlyphs(QVarLengthArray<CGGlyph> &cgGlyp QVarLengthArray<CGSize> advances(numGlyphs); CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), numGlyphs); + qreal stretch = fontDef.stretch != QFont::AnyStretch ? fontDef.stretch / 100.0 : 1.0; for (int i = 0; i < numGlyphs; ++i) - glyphs->advances[i] = QFixed::fromReal(advances[i].width); + glyphs->advances[i] = QFixed::fromReal(advances[i].width * stretch); } QFontEngine::FaceId QCoreTextFontEngine::faceId() const |