44 #include <QtCore/qendian.h> 45 #include <QtCore/qsettings.h> 47 #include <private/qimage_p.h> 49 #if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 53 static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90);
55 static void loadAdvancesForGlyphs(CTFontRef ctfont,
58 QTextEngine::ShaperFlags flags,
63 CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.
data(), advances.data(), len);
65 for (
int i = 0; i < len; ++i) {
66 if (glyphs->
glyphs[i] & 0xff000000)
73 for (
int i = 0; i < len; ++i) {
84 CTFontSymbolicTraits symbolicTraits = 0;
86 symbolicTraits |= kCTFontBoldTrait;
87 switch (fontDef.
style) {
92 symbolicTraits |= kCTFontItalicTrait;
96 transform = CGAffineTransformIdentity;
98 transform = CGAffineTransformMakeScale(
float(fontDef.
stretch) /
float(100), 1);
109 ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.
pixelSize, &transform, symbolicTraits, symbolicTraits);
124 ctfont = (CTFontRef) CFRetain(ctFontRef);
136 attributeDict = CFDictionaryCreateMutable(0, 2,
137 &kCFTypeDictionaryKeyCallBacks,
138 &kCFTypeDictionaryValueCallBacks);
139 CFDictionaryAddValue(attributeDict, kCTFontAttributeName, ctfont);
143 CFDictionaryAddValue(attributeDict, kCTKernAttributeName, noKern);
157 if (CFEqual(engineAt(i)->ctfont, font))
169 int *nglyphs, QTextEngine::ShaperFlags flags,
170 unsigned short *logClusters,
const HB_CharAttributes *,
174 reinterpret_cast<const UniChar *>(str),
175 len, kCFAllocatorNull);
179 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 181 const void *optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
182 const short rtlForcedEmbeddingLevelValue = 1;
183 const void *rtlOptionValues[] = { CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &rtlForcedEmbeddingLevelValue) };
185 &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
186 typeSetter = CTTypesetterCreateWithAttributedStringAndOptions(attributedString, options);
191 typeSetter = CTTypesetterCreateWithAttributedString(attributedString);
193 CFRange range = {0, 0};
196 uint arraySize = CFArrayGetCount(array);
198 HB_GlyphAttributes *outAttributes = glyphs->
attributes;
201 glyph_t *initialGlyph = outGlyphs;
203 if (arraySize == 0) {
207 for (
int i = 0; i < len; ++i) {
211 outAdvances_x[i] =
QFixed();
212 outAdvances_y[i] =
QFixed();
213 outAttributes[i].clusterStart =
true;
218 const bool rtl = (CTRunGetStatus(static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, 0))) & kCTRunStatusRightToLeft);
220 bool outOBounds =
false;
221 for (
uint i = 0; i < arraySize; ++i) {
222 CTRunRef
run =
static_cast<CTRunRef
>(CFArrayGetValueAtIndex(array, rtl ? (arraySize - 1 - i) : i));
227 Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl);
228 CFRange stringRange = CTRunGetStringRange(run);
229 CGAffineTransform textMatrix = CTRunGetTextMatrix(run);
231 #if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5 232 UniChar beginGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location);
235 if (beginWithOverride) {
236 logClusters[stringRange.location] = 0;
237 outGlyphs[0] = 0xFFFF;
238 outAdvances_x[0] = 0;
239 outAdvances_y[0] = 0;
240 outAttributes[0].clusterStart =
true;
241 outAttributes[0].dontPrint =
true;
249 UniChar endGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location + stringRange.length - 1);
254 if (!outOBounds && outGlyphs + glyphCount - initialGlyph > *nglyphs) {
258 CFDictionaryRef runAttribs = CTRunGetAttributes(run);
261 runAttribs = attributeDict;
262 CTFontRef runFont =
static_cast<CTFontRef
>(CFDictionaryGetValue(runAttribs, kCTFontAttributeName));
263 uint fontIndex = fontIndexForFont(runFont);
274 const CGGlyph *tmpGlyphs = CTRunGetGlyphsPtr(run);
276 cgglyphs.resize(glyphCount);
277 CTRunGetGlyphs(run, range, cgglyphs.data());
278 tmpGlyphs = cgglyphs.constData();
281 const CGPoint *tmpPoints = CTRunGetPositionsPtr(run);
283 cgpoints.resize(glyphCount);
284 CTRunGetPositions(run, range, cgpoints.data());
285 tmpPoints = cgpoints.constData();
288 const int rtlOffset = rtl ? (glyphCount - 1) : 0;
289 const int rtlSign = rtl ? -1 : 1;
292 CFRange stringRange = CTRunGetStringRange(run);
294 const CFIndex *tmpIndices = CTRunGetStringIndicesPtr(run);
296 stringIndices.resize(glyphCount);
297 CTRunGetStringIndices(run, range, stringIndices.data());
298 tmpIndices = stringIndices.constData();
301 const int firstGlyphIndex = outGlyphs - initialGlyph;
302 outAttributes[0].clusterStart =
true;
306 for (i = stringRange.location + prepend;
307 (i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) {
308 if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location + prepend) {
309 logClusters[i] = k + firstGlyphIndex;
310 outAttributes[k].clusterStart =
true;
313 logClusters[i] = k + firstGlyphIndex - 1;
317 for (;i < stringRange.location + stringRange.length; i++) {
318 logClusters[i] = k + firstGlyphIndex - 1;
321 for (CFIndex i = 0; i < glyphCount - 1; ++i) {
322 int idx = rtlOffset + rtlSign * i;
323 outGlyphs[idx] = tmpGlyphs[i] | fontIndex;
324 CGSize advance = CGSizeMake(tmpPoints[i + 1].x - tmpPoints[i].x, tmpPoints[i].y - tmpPoints[i + 1].y);
325 if (transformAdvances)
326 advance = CGSizeApplyAffineTransform(advance, textMatrix);
333 outAdvances_x[idx] = outAdvances_x[idx].
round();
334 outAdvances_y[idx] = outAdvances_y[idx].
round();
337 CGSize lastGlyphAdvance;
338 CTFontGetAdvancesForGlyphs(runFont, kCTFontHorizontalOrientation, tmpGlyphs + glyphCount - 1, &lastGlyphAdvance, 1);
340 outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex;
341 outAdvances_x[rtl ? 0 : (glyphCount - 1)] =
347 logClusters[stringRange.location + stringRange.length - 1] = glyphCount + prepend;
351 outAttributes[
glyphCount].clusterStart =
true;
361 *nglyphs = (outGlyphs - initialGlyph);
366 int *nglyphs, QTextEngine::ShaperFlags flags)
const 372 CTFontGetGlyphsForCharacters(ctfont, (
const UniChar*)str, cgGlyphs.
data(), len);
374 for (
int i = 0; i < len; ++i) {
376 glyphs->
glyphs[i] = cgGlyphs[i];
379 cfstring = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(str), len, kCFAllocatorNull);
380 QCFType<CTFontRef> substituteFont = CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 1));
381 CGGlyph substituteGlyph = 0;
382 CTFontGetGlyphsForCharacters(substituteFont, (
const UniChar*)str + i, &substituteGlyph, 1);
383 if (substituteGlyph) {
384 const uint fontIndex = (fontIndexForFont(substituteFont) << 24);
385 glyphs->
glyphs[i] = substituteGlyph | fontIndex;
388 CTFontGetAdvancesForGlyphs(substituteFont, kCTFontHorizontalOrientation, &substituteGlyph, &advance, 1);
399 loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, len, flags, fontDef);
413 CGAffineTransform transform = CGAffineTransformIdentity;
415 transform = CGAffineTransformMakeScale(
float(fontDef.
stretch) /
float(100), 1);
425 cgFont = CTFontCopyGraphicsFont(font, NULL);
436 ctfont = CTFontCreateWithGraphicsFont(font, fontDef.
pixelSize, &transform, NULL);
448 int getTraitValue(CFDictionaryRef allTraits,
CFStringRef trait)
450 if (CFDictionaryContainsKey(allTraits, trait)) {
451 CFNumberRef traitNum = (CFNumberRef) CFDictionaryGetValue(allTraits, trait);
453 CFNumberGetValue(traitNum, kCFNumberFloatType, &v);
455 int value = v * 500 + 500;
467 QCFString family = CTFontCopyFamilyName(ctfont);
474 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont);
475 if (traits & kCTFontItalicTrait)
478 CFDictionaryRef allTraits = CTFontCopyTraits(ctfont);
480 int slant = getTraitValue(allTraits, kCTFontSlantTrait);
481 if (slant > 500 && !(traits & kCTFontItalicTrait))
483 CFRelease(allTraits);
493 unsigned emSize = CTFontGetUnitsPerEm(ctfont);
494 if (os2Table.
size() >= 10) {
504 int *nglyphs, QTextEngine::ShaperFlags flags)
const 510 CTFontGetGlyphsForCharacters(ctfont, (
const UniChar*)str, cgGlyphs.
data(), len);
512 for (
int i = 0; i < len; ++i)
514 glyphs->
glyphs[i] = cgGlyphs[i];
519 loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, len, flags, fontDef);
528 for (
int i = 0; i < glyphs.
numGlyphs; ++i) {
539 CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1);
541 rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW;
548 CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1);
591 ? avgCharWidth.
round() : avgCharWidth;
616 if (glyphs.
size() == 0)
619 CGContextSetFontSize(ctx, fontDef.
pixelSize);
621 CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
623 CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight);
625 CGAffineTransformConcat(cgMatrix, oldTextMatrix);
627 if (synthesisFlags & QFontEngine::SynthesizedItalic)
628 cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
630 cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
632 CGContextSetTextMatrix(ctx, cgMatrix);
634 CGContextSetTextDrawingMode(ctx, kCGTextFill);
640 for (
int i = 0; i < glyphs.
size() - 1; ++i) {
641 advances[i].width = (positions[i + 1].x - positions[i].x).
toReal();
642 advances[i].height = (positions[i + 1].y - positions[i].y).
toReal();
643 cgGlyphs[i] = glyphs[i];
645 advances[glyphs.
size() - 1].width = 0;
646 advances[glyphs.
size() - 1].height = 0;
647 cgGlyphs[glyphs.
size() - 1] = glyphs[glyphs.
size() - 1];
649 CGContextSetFont(ctx, cgFont);
652 CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal());
654 CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.
data(), advances.data(), glyphs.
size());
658 positions[0].y.toReal());
660 CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.
data(), advances.data(), glyphs.
size());
663 CGContextSetTextMatrix(ctx, oldTextMatrix);
666 struct ConvertPathInfo
668 ConvertPathInfo(
QPainterPath *newPath,
const QPointF &newPos) : path(newPath), pos(newPos) {}
673 static void convertCGPathToQPainterPath(
void *
info,
const CGPathElement *element)
675 ConvertPathInfo *myInfo =
static_cast<ConvertPathInfo *
>(
info);
676 switch(element->type) {
677 case kCGPathElementMoveToPoint:
678 myInfo->path->moveTo(element->points[0].x + myInfo->pos.x(),
679 element->points[0].y + myInfo->pos.y());
681 case kCGPathElementAddLineToPoint:
682 myInfo->path->lineTo(element->points[0].x + myInfo->pos.x(),
683 element->points[0].y + myInfo->pos.y());
685 case kCGPathElementAddQuadCurveToPoint:
686 myInfo->path->quadTo(element->points[0].x + myInfo->pos.x(),
687 element->points[0].y + myInfo->pos.y(),
688 element->points[1].x + myInfo->pos.x(),
689 element->points[1].y + myInfo->pos.y());
691 case kCGPathElementAddCurveToPoint:
692 myInfo->path->cubicTo(element->points[0].x + myInfo->pos.x(),
693 element->points[0].y + myInfo->pos.y(),
694 element->points[1].x + myInfo->pos.x(),
695 element->points[1].y + myInfo->pos.y(),
696 element->points[2].x + myInfo->pos.x(),
697 element->points[2].y + myInfo->pos.y());
699 case kCGPathElementCloseSubpath:
700 myInfo->path->closeSubpath();
703 qDebug() <<
"Unhandled path transform type: " << element->type;
711 CGAffineTransform cgMatrix = CGAffineTransformIdentity;
712 cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1);
714 if (synthesisFlags & QFontEngine::SynthesizedItalic)
715 cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
717 for (
int i = 0; i < nGlyphs; ++i) {
719 ConvertPathInfo
info(path, positions[i].toPointF());
720 CGPathApply(cgpath, &info, convertCGPathToQPainterPath);
733 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
735 CGColorSpaceCreateDeviceRGB();
737 uint cgflags = kCGImageAlphaNoneSkipFirst;
738 #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version 739 cgflags |= kCGBitmapByteOrder32Host;
741 CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(),
742 8, im.bytesPerLine(), colorspace,
744 CGContextSetFontSize(ctx, fontDef.
pixelSize);
745 CGContextSetShouldAntialias(ctx, (aa || fontDef.
pointSize > qt_antialiasing_threshold)
747 CGContextSetShouldSmoothFonts(ctx, aa);
748 CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
749 CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
751 CGAffineTransformConcat(cgMatrix, oldTextMatrix);
753 if (synthesisFlags & QFontEngine::SynthesizedItalic)
754 cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
756 cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
758 CGContextSetTextMatrix(ctx, cgMatrix);
759 CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
760 CGContextSetTextDrawingMode(ctx, kCGTextFill);
762 CGContextSetFont(ctx, cgFont);
766 CGContextSetTextPosition(ctx, pos_x, pos_y);
771 CGGlyph cgGlyph = glyph;
772 CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
774 if (synthesisFlags & QFontEngine::SynthesizedBold) {
776 CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
779 CGContextRelease(ctx);
786 QImage im = imageForGlyph(glyph, subPixelPosition, 0,
false);
790 for (
int i=0; i<256; ++i)
791 colors[i] =
qRgba(0, 0, 0, i);
792 indexed.setColorTable(colors);
794 for (
int y=0; y<im.
height(); ++y) {
796 uchar *dst = indexed.scanLine(y);
797 for (
int x=0; x<im.
width(); ++x) {
812 QImage im = imageForGlyph(glyph, subPixelPosition, margin,
true);
822 for (i = 0; i < numGlyphs; ++i) {
823 if (glyphs->
glyphs[i] & 0xff000000)
826 cgGlyphs[i] = glyphs->
glyphs[i];
829 loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, numGlyphs, flags, fontDef);
840 return CTFontGetGlyphsForCharacters(ctfont, (
const UniChar *)
string, cgGlyphs.
data(), len);
846 if (!table || !length)
848 CFIndex tableLength = CFDataGetLength(table);
849 int availableLength = *length;
850 *length = tableLength;
852 if (tableLength > availableLength)
854 CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer);
880 #endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) virtual QFixed ascent() const
virtual qreal minLeftBearing() const
virtual FaceId faceId() const
QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, bool colorful)
const struct __CFString * CFStringRef
virtual QFixed averageCharWidth() const
QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning)
virtual QFixed lineThickness() const
virtual int glyphCount() const
static mach_timebase_info_data_t info
virtual QFontEngine * cloneWithSize(qreal pixelSize) const
#define QT_END_NAMESPACE
This macro expands to.
virtual bool getSfntTableData(uint, uchar *, uint *) const
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
int count(const T &t) const
Returns the number of occurrences of value in the vector.
QCoreTextFontEngine(CTFontRef font, const QFontDef &def)
The QByteArray class provides an array of bytes.
The QPointF class defines a point in the plane using floating point precision.
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)
virtual qreal minRightBearing() const
Weight
Qt uses a weighting scale from 0 to 99 similar to, but not the same as, the scales used in Windows or...
QFont::Weight weightFromInteger(int weight)
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t)
virtual QFixed averageCharWidth() const
uint fontIndexForFont(CTFontRef font) const
void qGamma_correct_back_to_linear_cs(QImage *image)
bool ref()
Atomically increments the value of this QAtomicInt.
static QFixed fromReal(qreal r)
Q_DECL_CONSTEXPR T qAbs(const T &t)
The QChar class provides a 16-bit Unicode character.
virtual qreal maxCharWidth() const
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
int qt_antialiasing_threshold
#define MAKE_TAG(ch1, ch2, ch3, ch4)
Q_CORE_EXPORT void qDebug(const char *,...)
virtual QFixed xHeight() const
QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round=false)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Q_GUI_EXPORT_INLINE QRgb qRgba(int r, int g, int b, int a)
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags)
static float pixelSize(const QFontDef &request, int dpi)
static const QCssKnownValue positions[NumKnownPositionModes - 1]
virtual void loadEngine(int at)
virtual QFixed ascent() const =0
virtual bool canRender(const QChar *string, int len)
virtual QFixed descent() const =0
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray< glyph_t > &glyphs_out, QVarLengthArray< QFixedPoint > &positions)
void append(const T &t)
Inserts value at the end of the vector.
virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
qint16 qFromBigEndian< qint16 >(const uchar *src)
The QImage class provides a hardware-independent image representation that allows direct access to th...
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
~QCoreTextFontEngineMulti()
QVector< QFontEngine * > engines
quint16 qFromBigEndian< quint16 >(const uchar *src)
const char * constData() const
Returns a pointer to the data stored in the byte array.
Q_GUI_EXPORT_INLINE int qGray(int r, int g, int b)
int width() const
Returns the width of the image.
struct CGColorSpace * CGColorSpaceRef
virtual QFixed ascent() const
CGAffineTransform transform
virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition)
Q_GUI_EXPORT int qt_defaultDpi()
virtual QFixed leading() const
virtual QFixed descent() const
int height() const
Returns the height of the image.
int size() const
Returns the number of bytes in this byte array.
void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight)
QFuture< T > run(Function function,...)
QFixed effectiveAdvance(int item) const
virtual QFixed descent() const
HB_GlyphAttributes * attributes
static const MacVersion MacintoshVersion
the version of the Macintosh operating system on which the application is run (Mac only)...
CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef)
static QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)
virtual QFixed emSquareSize() const
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
struct CGContext * CGContextRef
Direction direction() const
Returns the character's direction.
const struct __CFArray * CFArrayRef
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)
Q_DECL_CONSTEXPR int qRound(qreal d)
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
QFontEngine * engine(int at) const
virtual QFixed leading() const =0
static qreal toReal(Register *reg, int type, bool *ok=0)
QByteArray getSfntTable(uint) const