6#include <qpa/qplatformfontdatabase.h>
7#include <QtCore/qendian.h>
9#include <QtCore/qsettings.h>
11#include <QtCore/qoperatingsystemversion.h>
12#include <QtGui/qpainterpath.h>
13#include <private/qcoregraphics_p.h>
14#include <private/qimage_p.h>
15#include <private/qguiapplication_p.h>
16#include <private/qstringiterator_p.h>
17#include <qpa/qplatformtheme.h>
21#if defined(Q_OS_MACOS)
25#if defined(QT_PLATFORM_UIKIT)
26#import <UIKit/UIKit.h>
32#if defined(Q_OS_MACOS)
33#define kCTFontWeightUltraLight NSFontWeightUltraLight
34#define kCTFontWeightThin NSFontWeightThin
35#define kCTFontWeightLight NSFontWeightLight
36#define kCTFontWeightRegular NSFontWeightRegular
37#define kCTFontWeightMedium NSFontWeightMedium
38#define kCTFontWeightSemibold NSFontWeightSemibold
39#define kCTFontWeightBold NSFontWeightBold
40#define kCTFontWeightHeavy NSFontWeightHeavy
41#define kCTFontWeightBlack NSFontWeightBlack
42#elif defined(QT_PLATFORM_UIKIT)
43#define kCTFontWeightUltraLight UIFontWeightUltraLight
44#define kCTFontWeightThin UIFontWeightThin
45#define kCTFontWeightLight UIFontWeightLight
46#define kCTFontWeightRegular UIFontWeightRegular
47#define kCTFontWeightMedium UIFontWeightMedium
48#define kCTFontWeightSemibold UIFontWeightSemibold
49#define kCTFontWeightBold UIFontWeightBold
50#define kCTFontWeightHeavy UIFontWeightHeavy
51#define kCTFontWeightBlack UIFontWeightBlack
66 CFIndex tableLength = CFDataGetLength(
table);
68 CFDataGetBytes(
table, CFRangeMake(0, tableLength),
buffer);
76#define COMPARE_WEIGHT_DISTANCE(ct_weight, qt_weight) \
79 if ((d = qAbs(value - ct_weight)) < distance) { \
99#undef COMPARE_WEIGHT_DISTANCE
106 CGAffineTransform
transform = CGAffineTransformIdentity;
108 transform = CGAffineTransformMakeScale(
float(fontDef.
stretch) /
float(100), 1);
134 const QMap<QFont::Tag, float> &variableAxisValues)
139 QCFType<CFDataRef> fontDataReference =
fontData.toRawCFData();
140 QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithCFData(fontDataReference);
148 QCFType<CGFontRef>
cgFont = CGFontCreateWithDataProvider(dataProvider);
151 qWarning(
"QCoreTextFontEngine::create: CGFontCreateWithDataProvider failed");
165 cgFont = CTFontCopyGraphicsFont(
font,
nullptr);
201 QCFString styleName = (CFStringRef) CTFontCopyAttribute(
ctfont, kCTFontStyleNameAttribute);
205 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(
ctfont);
207 if (traits & kCTFontColorGlyphsTrait)
214 if (traits & kCTFontItalicTrait)
217 static const auto getTraitValue = [](CFDictionaryRef allTraits, CFStringRef trait) ->
float {
218 if (CFDictionaryContainsKey(allTraits, trait)) {
219 CFNumberRef traitNum = (CFNumberRef) CFDictionaryGetValue(allTraits, trait);
221 CFNumberGetValue(traitNum, kCFNumberFloatType, &
v);
227 QCFType<CFDictionaryRef> allTraits = CTFontCopyTraits(
ctfont);
228 int slant =
static_cast<int>(getTraitValue(allTraits, kCTFontSlantTrait) * 500 + 500);
229 if (slant > 500 && !(traits & kCTFontItalicTrait))
242 unsigned emSize = CTFontGetUnitsPerEm(
ctfont);
243 if (os2Table.size() >= 10) {
244 fsType = qFromBigEndian<quint16>(os2Table.constData() + 8);
264 if (
Q_UNLIKELY(QChar::requiresSurrogates(ucs4))) {
271 CGGlyph glyphIndices[2];
273 CTFontGetGlyphsForCharacters(
ctfont, (
const UniChar *)
str, glyphIndices,
len);
275 return glyphIndices[0];
279 int *nglyphs, QFontEngine::ShaperFlags
flags)
const
282 if (*nglyphs <
len) {
287 QVarLengthArray<CGGlyph> cgGlyphs(
len);
288 CTFontGetGlyphsForCharacters(
ctfont, (
const UniChar*)
str, cgGlyphs.
data(),
len);
291 int mappedGlyphs = 0;
293 while (
it.hasNext()) {
295 char32_t ucs4 =
it.next();
296 glyphs->
glyphs[glyph_pos] = cgGlyphs[idx];
298 cgGlyphs[glyph_pos] = cgGlyphs[idx];
304 *nglyphs = glyph_pos;
317 CGRect
rect = CTFontGetBoundingRectsForGlyphs(
ctfont, kCTFontOrientationHorizontal, &
g, 0, 1);
326 CTFontGetAdvancesForGlyphs(
ctfont, kCTFontOrientationHorizontal, &
g, advances, 1);
378 QVarLengthArray<glyph_t> glyphs;
382 if (glyphs.size() == 0)
387 CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(
ctx);
389 CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight);
392 Q_UNUSED(CGAffineTransformConcat(cgMatrix, oldTextMatrix));
395 cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -
SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
397 cgMatrix = CGAffineTransformConcat(cgMatrix,
transform);
399 CGContextSetTextMatrix(
ctx, cgMatrix);
401 CGContextSetTextDrawingMode(
ctx, kCGTextFill);
403 QVarLengthArray<CGPoint> cgPositions(glyphs.size());
404 QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size());
407 for (
int i = 0;
i < glyphs.size(); ++
i) {
408 cgPositions[
i].x =
positions[
i].x.toReal() - firstX;
409 cgPositions[
i].y = firstY -
positions[
i].y.toReal();
410 cgGlyphs[
i] = glyphs[
i];
416 CTFontDrawGlyphs(
ctfont, cgGlyphs.data(), cgPositions.data(), glyphs.size(),
ctx);
419 QTransform matrix(cgMatrix.a, cgMatrix.b, cgMatrix.c, cgMatrix.d, cgMatrix.tx, cgMatrix.ty);
426 CGContextSetTextPosition(
ctx,
429 CTFontDrawGlyphs(
ctfont, cgGlyphs.data(), cgPositions.data(), glyphs.size(),
ctx);
432 CGContextSetTextMatrix(
ctx, oldTextMatrix);
447 switch(element->type) {
448 case kCGPathElementMoveToPoint:
449 myInfo->
path->
moveTo((element->points[0].x * myInfo->stretch) + myInfo->pos.x(),
450 element->points[0].y + myInfo->pos.y());
452 case kCGPathElementAddLineToPoint:
453 myInfo->path->lineTo((element->points[0].x * myInfo->stretch) + myInfo->pos.x(),
454 element->points[0].y + myInfo->pos.y());
456 case kCGPathElementAddQuadCurveToPoint:
457 myInfo->path->quadTo((element->points[0].x * myInfo->stretch) + myInfo->pos.x(),
458 element->points[0].y + myInfo->pos.y(),
459 (element->points[1].x * myInfo->stretch) + myInfo->pos.x(),
460 element->points[1].y + myInfo->pos.y());
462 case kCGPathElementAddCurveToPoint:
463 myInfo->path->cubicTo((element->points[0].x * myInfo->stretch) + myInfo->pos.x(),
464 element->points[0].y + myInfo->pos.y(),
465 (element->points[1].x * myInfo->stretch) + myInfo->pos.x(),
466 element->points[1].y + myInfo->pos.y(),
467 (element->points[2].x * myInfo->stretch) + myInfo->pos.x(),
468 element->points[2].y + myInfo->pos.y());
470 case kCGPathElementCloseSubpath:
471 myInfo->path->closeSubpath();
474 qCWarning(lcQpaFonts) <<
"Unhandled path transform type: " << element->type;
485 CGAffineTransform cgMatrix = CGAffineTransformIdentity;
486 cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1);
489 cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -
SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
492 for (
int i = 0;
i < nGlyphs; ++
i) {
493 QCFType<CGPathRef> cgpath = CTFontCreatePathForGlyph(
ctfont, glyphs[
i], &cgMatrix);
611 static const int kSize = 10;
612 QCFType<CTFontRef>
font = CTFontCreateWithName(CFSTR(
"Helvetica"), kSize,
nullptr);
614 UniChar character(
'X'); CGGlyph glyph;
615 CTFontGetGlyphsForCharacters(
font, &character, &glyph, 1);
617 auto drawGlyph = [&](
bool smooth) ->
QImage {
622 CGContextSetTextDrawingMode(
ctx, kCGTextFill);
623 CGContextSetGrayFillColor(
ctx, 1, 1);
627 CGContextSetShouldSmoothFonts(
ctx, smooth);
629 CTFontDrawGlyphs(
font, &glyph, &CGPointZero, 1,
ctx);
633 QImage nonSmoothed = drawGlyph(
false);
634 QImage smoothed = drawGlyph(
true);
638 for (
int x = 0;
x < kSize; ++
x) {
639 for (
int y = 0;
y < kSize; ++
y) {
646 if (
sp != nonSmoothed.pixel(
x,
y))
652 auto defaults = [NSUserDefaults standardUserDefaults];
653 qCDebug(lcQpaFonts) <<
"Resolved font smoothing algorithm. Defaults ="
654 << [[
defaults dictionaryRepresentation] dictionaryWithValuesForKeys:@[
655 @"AppleFontSmoothing",
656 @"CGFontRenderingFontSmoothingDisabled"
662 return cachedFontSmoothing;
706 QCFType<CGColorSpaceRef> colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
715 CGContextSetShouldSmoothFonts(
ctx, shouldSmooth);
717#if defined(Q_OS_MACOS)
718 auto glyphColor = [&] {
732 return kCGColorBlack;
735 return kCGColorWhite;
738 const bool blackOnWhiteGlyphs = glyphColor == kCGColorBlack;
739 if (blackOnWhiteGlyphs)
747 CGAffineTransform cgMatrix = CGAffineTransformIdentity;
750 cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0,
SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
753 cgMatrix = CGAffineTransformConcat(cgMatrix,
transform);
756 cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMakeScale(
matrix.m11(),
matrix.m22()));
758 CGGlyph cgGlyph = glyph;
764 CGContextSetTextMatrix(
ctx, cgMatrix);
765#if defined(Q_OS_MACOS)
766 CGContextSetFillColorWithColor(
ctx, CGColorGetConstantColor(glyphColor));
768 CGContextSetRGBFillColor(
ctx, 1, 1, 1, 1);
770 CGContextSetTextDrawingMode(
ctx, kCGTextFill);
771 CGContextSetTextPosition(
ctx, pos_x, pos_y);
773 CTFontDrawGlyphs(
ctfont, &cgGlyph, &CGPointZero, 1,
ctx);
782 CGContextSetTextPosition(
ctx, pos_x + boldOffset, pos_y);
783 CTFontDrawGlyphs(
ctfont, &cgGlyph, &CGPointZero, 1,
ctx);
791 CGContextTranslateCTM(
ctx, pos_x, pos_y);
792 CGContextConcatCTM(
ctx, cgMatrix);
796 CTFontDrawGlyphs(
ctfont, &cgGlyph, &CGPointZero, 1,
ctx);
802#if defined(Q_OS_MACOS)
803 if (blackOnWhiteGlyphs)
858 QVarLengthArray<CGGlyph> cgGlyphs(
numGlyphs);
871 QVarLengthArray<CGSize> advances(
numGlyphs);
872 CTFontGetAdvancesForGlyphs(
ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(),
numGlyphs);
886 QVarLengthArray<CGGlyph> cgGlyphs(
len);
887 return CTFontGetGlyphsForCharacters(
ctfont, (
const UniChar *)
string, cgGlyphs.data(),
len);
897 CGAffineTransform cgMatrix = CGAffineTransformIdentity;
901 cgMatrix = CGAffineTransformScale(cgMatrix,
scale, -
scale);
903 QCFType<CGPathRef> cgpath = CTFontCreatePathForGlyph(
ctfont, (CGGlyph) glyph, &cgMatrix);
962 psName = CTFontCopyPostScriptName(
ctfont);
963 copyright = CTFontCopyName(
ctfont, kCTFontCopyrightNameKey);
964 result.postscriptName = QString::fromCFString(psName).toUtf8();
965 result.copyright = QString::fromCFString(copyright).toUtf8();
970 CGRect cgRect = CTFontGetBoundingBox(
ctfont);
973 cgRect.size.width *
scale,
974 cgRect.size.height *
scale);
static QCFType constructFromGet(const T &t)
The QColor class provides colors based on RGB, HSV or CMYK values.
bool canRender(const QChar *string, int len) const override
Qt::HANDLE handle() const override
glyph_t glyphIndex(uint ucs4) const override
void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags) override
static qreal fontSmoothingGamma()
QCFType< CTFontRef > ctfont
QFixed emSquareSize() const override
QFixed capHeight() const override
QImage alphaMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition) override
static FontSmoothing fontSmoothing()
void loadAdvancesForGlyphs(QVarLengthArray< CGGlyph > &cgGlyphs, QGlyphLayout *glyphs) const
QFixed averageCharWidth() const override
QImage imageForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &m, const QColor &color=QColor())
glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QFixedPoint &, const QTransform &matrix, GlyphFormat) override
static QCoreTextFontEngine * create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference, const QMap< QFont::Tag, float > &variableAxisValue)
QFixed underlineThickness
bool getSfntTableData(uint, uchar *, uint *) const override
Returns true if the font table idetified by tag exists in the font; returns false otherwise.
QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t) override
int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override
QFixed lineThickness() const override
void initializeHeightMetrics() const override
QCoreTextFontEngine(CTFontRef font, const QFontDef &def)
static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length)
QFontEngine::FaceId face_id
QCFType< CGFontRef > cgFont
void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight)
static QFont::Weight qtWeightFromCFWeight(float value)
qreal maxCharWidth() const override
glyph_metrics_t boundingBox(glyph_t glyph) override
bool supportsTransformation(const QTransform &transform) const override
void recalcAdvances(QGlyphLayout *, ShaperFlags) const override
bool expectsGammaCorrectedBlending() const override
FaceId faceId() const override
bool hasColorGlyphs() const
QFontEngine::Properties properties() const override
QFixed underlinePosition() const override
bool shouldAntialias() const
void doKerning(QGlyphLayout *g, ShaperFlags flags) const override
void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override
bool shouldSmoothFont() const
QFixed xHeight() const override
QFontEngine * cloneWithSize(qreal pixelSize) const override
QImage bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color) override
static uchar highByte(glyph_t glyph)
void loadKerningPairs(QFixed scalingFactor)
QFixed calculatedCapHeight() const
virtual QImage bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color=QColor())
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QFixedPoint &, const QTransform &matrix, GlyphFormat)
bool m_heightMetricsQueried
static bool isIgnorableChar(char32_t ucs4)
virtual QImage alphaMapForGlyph(glyph_t)
virtual QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t)
QByteArray getSfntTable(uint tag) const
virtual QFixed averageCharWidth() const
virtual void doKerning(QGlyphLayout *, ShaperFlags) const
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray< glyph_t > &glyphs_out, QVarLengthArray< QFixedPoint > &positions)
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
static QPlatformTheme * platformTheme()
qsizetype bytesPerLine() const
Returns the number of bytes per image scanline.
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
QRgb pixel(int x, int y) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
int width() const
Returns the width of the image.
uchar * bits()
Returns a pointer to the first pixel data.
int height() const
Returns the height of the image.
Format
The following image formats are available in Qt.
@ Format_ARGB32_Premultiplied
void fill(uint pixel)
Fills the entire image with the given pixelValue.
void invertPixels(InvertMode=InvertRgb)
Inverts all pixel values in the image.
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
QChar * data()
Returns a pointer to the data stored in the QString.
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QList< QString > QStringList
Constructs a string list that contains the given string, str.
AudioChannelLayoutTag tag
QT_USE_NAMESPACE QT_BEGIN_NAMESPACE CGBitmapInfo qt_mac_bitmapInfoForImage(const QImage &image)
static const QCssKnownValue positions[NumKnownPositionModes - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void * user_data
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
Q_GUI_EXPORT int qt_defaultDpi()
static QT_BEGIN_NAMESPACE float SYNTHETIC_ITALIC_SKEW
CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef)
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
static void qcoretextfontengine_scaleMetrics(glyph_metrics_t &br, const QTransform &matrix)
static void convertCGPathToQPainterPath(void *info, const CGPathElement *element)
#define COMPARE_WEIGHT_DISTANCE(ct_weight, qt_weight)
CGAffineTransform Q_GUI_EXPORT qt_transform_from_fontdef(const QFontDef &fontDef)
void qGamma_correct_back_to_linear_cs(QImage *image)
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr T qAbs(const T &t)
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLenum GLsizei length
GLenum const void GLbitfield GLsizei numGlyphs
GLsizei GLsizei GLfloat distance
GLint GLsizei GLsizei GLenum format
GLenum GLsizeiptr const void * fontData
GLuint GLenum GLenum transform
GLsizei const GLchar *const * path
GLenum GLenum GLenum GLenum GLenum scale
GLenum GLenum GLsizei void * table
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
struct CGContext * CGContextRef
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
constexpr int qRed(QRgb rgb)
constexpr int qGreen(QRgb rgb)
constexpr int qGray(int r, int g, int b)
constexpr int qBlue(QRgb rgb)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
QFile defaults(defaultsPath)
ConvertPathInfo(QPainterPath *newPath, const QPointF &newPos, qreal newStretch=1.0)
static constexpr QFixed fromReal(qreal r)
constexpr int toInt() const
constexpr QFixed ceil() const
constexpr qreal toReal() const
constexpr int truncate() const
QMap< QFont::Tag, float > variableAxisValues
QMap< QFont::Tag, float > variableAxes
The QFont::Tag type provides access to advanced font features.