CGAffineTransform PDFPageGetDrawingTransform(CGPDFPageRef page, CGPDFBox box, float scale) { CGRect boxRect = CGPDFPageGetBoxRect(page, box); int rotation = PDFPageGetRotation(page); CGAffineTransform transform = CGAffineTransformMakeScale(scale, scale); transform = CGAffineTransformRotate(transform, -(rotation * M_PI_2)); switch (rotation) { case 1: transform = CGAffineTransformTranslate(transform, -CGRectGetWidth(boxRect), 0); break; case 2: transform = CGAffineTransformTranslate(transform, -CGRectGetWidth(boxRect), 0); transform = CGAffineTransformTranslate(transform, 0, -CGRectGetHeight(boxRect)); break; case 3: transform = CGAffineTransformTranslate(transform, 0, -CGRectGetHeight(boxRect)); break; default: break; } transform = CGAffineTransformTranslate(transform, -boxRect.origin.x, -boxRect.origin.y); return transform; }
DRAW_TEST_F(CGImageDrawing, DrawAContextIntoAnImage, UIKitMimicTest<>) { // This test will create a bitmap context, draw some entity into the context, then create a image out of the bitmap context. // Thereafter it will draw the image into the Canvas context static woc::unique_cf<CGColorSpaceRef> rgbColorSpace(CGColorSpaceCreateDeviceRGB()); // Create a bitmap context to draw the Image into woc::unique_cf<CGContextRef> contextImage(CGBitmapContextCreate( nullptr, 10, 10, 8, 4 * 10 /* bytesPerRow = bytesPerPixel*width*/, rgbColorSpace.get(), kCGImageAlphaPremultipliedFirst)); ASSERT_NE(contextImage, nullptr); CGContextSetRGBFillColor(contextImage.get(), 1.0, 0.0, 0.0, 1.0); CGContextFillRect(contextImage.get(), { 0, 0, 10, 10 }); // Create the image out of the bitmap context woc::unique_cf<CGImageRef> image(CGBitmapContextCreateImage(contextImage.get())); ASSERT_NE(image, nullptr); CGContextRef context = GetDrawingContext(); CGRect bounds = GetDrawingBounds(); CGAffineTransform flip = CGAffineTransformMakeScale(1, -1); CGAffineTransform shift = CGAffineTransformTranslate(flip, 0, bounds.size.height * -1); CGContextConcatCTM(context, shift); // draw the image CGContextDrawImage(context, bounds, image.get()); }
void PlatformCALayer::drawRepaintIndicator(CGContextRef context, PlatformCALayer* platformCALayer, int repaintCount, CGColorRef customBackgroundColor) { char text[16]; // that's a lot of repaints snprintf(text, sizeof(text), "%d", repaintCount); CGRect indicatorBox = platformCALayer->bounds(); indicatorBox.size.width = 12 + 10 * strlen(text); indicatorBox.size.height = 27; CGContextSaveGState(context); CGContextSetAlpha(context, 0.5f); CGContextBeginTransparencyLayerWithRect(context, indicatorBox, 0); if (customBackgroundColor) CGContextSetFillColorWithColor(context, customBackgroundColor); else CGContextSetRGBFillColor(context, 0, 0.5f, 0.25f, 1); CGContextFillRect(context, indicatorBox); if (platformCALayer->acceleratesDrawing()) CGContextSetRGBFillColor(context, 1, 0, 0, 1); else CGContextSetRGBFillColor(context, 1, 1, 1, 1); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1, -1)); CGContextSelectFont(context, "Helvetica", 22, kCGEncodingMacRoman); CGContextShowTextAtPoint(context, indicatorBox.origin.x + 5, indicatorBox.origin.y + 22, text, strlen(text)); #pragma clang diagnostic pop CGContextEndTransparencyLayer(context); CGContextRestoreGState(context); }
// This function is needed to work around a bug in Windows CG <rdar://problem/22703470> void PlatformCALayer::drawTextAtPoint(CGContextRef context, CGFloat x, CGFloat y, CGSize scale, CGFloat fontSize, const char* text, size_t length) const { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" CGContextSetTextMatrix(context, CGAffineTransformMakeScale(scale.width, scale.height)); CGContextSelectFont(context, "Helvetica", fontSize, kCGEncodingMacRoman); CGContextShowTextAtPoint(context, x, y, text, length); #pragma clang diagnostic pop }
void WKCACFLayer::display(PlatformGraphicsContext* context) { if (!m_owner) return; CGContextSaveGState(context); CGRect layerBounds = bounds(); if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) { CGContextScaleCTM(context, 1, -1); CGContextTranslateCTM(context, 0, -layerBounds.size.height); } if (m_owner->client()) { GraphicsContext graphicsContext(context); // It's important to get the clip from the context, because it may be significantly // smaller than the layer bounds (e.g. tiled layers) CGRect clipBounds = CGContextGetClipBoundingBox(context); IntRect clip(enclosingIntRect(clipBounds)); m_owner->paintGraphicsLayerContents(graphicsContext, clip); } #ifndef NDEBUG else { ASSERT_NOT_REACHED(); // FIXME: ideally we'd avoid calling -setNeedsDisplay on a layer that is a plain color, // so CA never makes backing store for it (which is what -setNeedsDisplay will do above). CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 1.0f); CGContextFillRect(context, layerBounds); } #endif if (m_owner->showRepaintCounter()) { char text[16]; // that's a lot of repaints _snprintf(text, sizeof(text), "%d", m_owner->incrementRepaintCount()); CGContextSaveGState(context); CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f); CGRect aBounds = layerBounds; aBounds.size.width = 10 + 12 * strlen(text); aBounds.size.height = 25; CGContextFillRect(context, aBounds); CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 1.0f); CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0f, -1.0f)); CGContextSelectFont(context, "Helvetica", 25, kCGEncodingMacRoman); CGContextShowTextAtPoint(context, aBounds.origin.x + 3.0f, aBounds.origin.y + 20.0f, text, strlen(text)); CGContextRestoreGState(context); } CGContextRestoreGState(context); }
//----------------------------------------------------------------------------- void CGDrawContext::drawCGImageRef (CGContextRef context, CGImageRef image, CGLayerRef layer, double bitmapScaleFactor, const CRect& inRect, const CPoint& inOffset, float alpha, CBitmap* bitmap) { CRect rect (inRect); CPoint offset (inOffset); CGContextSetAlpha (context, (CGFloat)alpha*currentState.globalAlpha); CGRect dest; dest.origin.x = static_cast<CGFloat> (rect.left - offset.x); dest.origin.y = static_cast<CGFloat> (-(rect.top) - (bitmap->getHeight () - offset.y)); dest.size.width = static_cast<CGFloat> (bitmap->getWidth ()); dest.size.height = static_cast<CGFloat> (bitmap->getHeight ()); CGRect clipRect; clipRect.origin.x = static_cast<CGFloat> (rect.left); clipRect.origin.y = static_cast<CGFloat> (-(rect.top) - rect.getHeight ()); clipRect.size.width = static_cast<CGFloat> (rect.getWidth ()); clipRect.size.height = static_cast<CGFloat> (rect.getHeight ()); if (bitmapScaleFactor != 1.) { CGContextConcatCTM (context, CGAffineTransformMakeScale (static_cast<CGFloat> (1./bitmapScaleFactor), static_cast<CGFloat> (1./bitmapScaleFactor))); CGAffineTransform transform = CGAffineTransformMakeScale (static_cast<CGFloat> (bitmapScaleFactor), static_cast<CGFloat> (bitmapScaleFactor)); clipRect.origin = CGPointApplyAffineTransform (clipRect.origin, transform); clipRect.size = CGSizeApplyAffineTransform (clipRect.size, transform); dest.origin = CGPointApplyAffineTransform (dest.origin, transform); dest.size = CGSizeApplyAffineTransform (dest.size, transform); } dest = pixelAlligned (dest); clipRect = pixelAlligned (clipRect); CGContextClipToRect (context, clipRect); if (layer) { CGContextDrawLayerInRect (context, dest, layer); } else { CGContextDrawImage (context, dest, image); } }
//----------------------------------------------------------------------------- CGDrawContext::CGDrawContext (CGBitmap* _bitmap) : COffscreenContext (new CBitmap (_bitmap)) , cgContext (_bitmap->createCGContext ()) , scaleFactor (_bitmap->getScaleFactor ()) { if (scaleFactor != 1.) { CGContextConcatCTM (cgContext, CGAffineTransformMakeScale (static_cast<CGFloat> (scaleFactor), static_cast<CGFloat> (scaleFactor))); } init (); bitmap->forget (); }
// This function is needed to work around a bug in Windows CG <rdar://problem/22703470> void PlatformCALayer::drawTextAtPoint(CGContextRef context, CGFloat x, CGFloat y, CGSize scale, CGFloat fontSize, const char* text, size_t length) const { auto matrix = CGAffineTransformMakeScale(scale.width, scale.height); auto font = adoptCF(CTFontCreateWithName(CFSTR("Helvetica"), fontSize, &matrix)); CFTypeRef keys[] = { kCTFontAttributeName, kCTForegroundColorFromContextAttributeName }; CFTypeRef values[] = { font.get(), kCFBooleanTrue }; auto attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); auto string = adoptCF(CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(text), length, kCFStringEncodingUTF8, false, kCFAllocatorNull)); auto attributedString = adoptCF(CFAttributedStringCreate(kCFAllocatorDefault, string.get(), attributes.get())); auto line = adoptCF(CTLineCreateWithAttributedString(attributedString.get())); CGContextSetTextPosition(context, x, y); CTLineDraw(line.get(), context); }
DRAW_TEST_F(CGImageDrawing, DrawAnImage, UIKitMimicTest<>) { // Load an Image and draw it into the canvas context auto drawingConfig = DrawingTestConfig::Get(); woc::unique_cf<CFStringRef> testFilename{ _CFStringCreateWithStdString(drawingConfig->GetResourcePath("jpg1.jpg")) }; woc::unique_cf<CGImageRef> image{ _CGImageCreateFromJPEGFile(testFilename.get()) }; ASSERT_NE(image, nullptr); CGContextRef context = GetDrawingContext(); CGRect bounds = GetDrawingBounds(); CGAffineTransform flip = CGAffineTransformMakeScale(1, -1); CGAffineTransform shift = CGAffineTransformTranslate(flip, 0, bounds.size.height * -1); CGContextConcatCTM(context, shift); CGContextDrawImage(context, bounds, image.get()); }
DISABLED_DRAW_TEST_F(CGImageDrawing, DrawIntoRect, UIKitMimicTest<>) { // Draw a portion of an image into a different region. auto drawingConfig = DrawingTestConfig::Get(); woc::unique_cf<CFStringRef> testFilename{ _CFStringCreateWithStdString(drawingConfig->GetResourcePath("png3.9.png")) }; woc::unique_cf<CGImageRef> image{ _CGImageCreateFromPNGFile(testFilename.get()) }; ASSERT_NE(image, nullptr); CGContextRef context = GetDrawingContext(); CGRect bounds = GetDrawingBounds(); CGAffineTransform flip = CGAffineTransformMakeScale(1, -1); CGAffineTransform shift = CGAffineTransformTranslate(flip, 0, bounds.size.height * -1); CGContextConcatCTM(context, shift); _CGContextDrawImageRect(context, image.get(), { 0, 0, bounds.size.width / 4, bounds.size.height / 4 }, { 0, 0, bounds.size.width, bounds.size.height }); }
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { #if __WXMSW__ // under Windows / wxMSW we currently always use GDI fonts. return widthForGDIGlyph(glyph); #elif OS(DARWIN) float pointSize = m_platformData.size(); CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize); CGSize advance; NSFont* nsfont = (NSFont*)m_platformData.nsFont(); if (!wkGetGlyphTransformedAdvances(m_platformData.cgFont(), nsfont, &m, &glyph, &advance)) { // LOG_ERROR("Unable to cache glyph widths for %@ %f", [nsfont displayName], pointSize); advance.width = 0; } return advance.width + m_syntheticBoldOffset; #else // TODO: fix this! Make GetTextExtents a method of wxFont in 2.9 int width = 10; GetTextExtent(*m_platformData.font(), (wxChar)glyph, &width, NULL); return width; #endif }
void ScaledFontMac::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint) { if (!(aBackendType == BackendType::COREGRAPHICS || aBackendType == BackendType::COREGRAPHICS_ACCELERATED)) { ScaledFontBase::CopyGlyphsToBuilder(aBuffer, aBuilder, aBackendType, aTransformHint); return; } PathBuilderCG *pathBuilderCG = static_cast<PathBuilderCG*>(aBuilder); // XXX: check builder type for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) { // XXX: we could probably fold both of these transforms together to avoid extra work CGAffineTransform flip = CGAffineTransformMakeScale(1, -1); CGPathRef glyphPath = ::CGFontGetGlyphPath(mFont, &flip, 0, aBuffer.mGlyphs[i].mIndex); CGAffineTransform matrix = CGAffineTransformMake(mSize, 0, 0, mSize, aBuffer.mGlyphs[i].mPosition.x, aBuffer.mGlyphs[i].mPosition.y); CGPathAddPath(pathBuilderCG->mCGPath, &matrix, glyphPath); CGPathRelease(glyphPath); } }
TemporaryRef<Path> ScaledFontMac::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) { if (aTarget->GetType() == BackendType::COREGRAPHICS || aTarget->GetType() == BackendType::COREGRAPHICS_ACCELERATED) { CGMutablePathRef path = CGPathCreateMutable(); for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) { // XXX: we could probably fold both of these transforms together to avoid extra work CGAffineTransform flip = CGAffineTransformMakeScale(1, -1); CGPathRef glyphPath = ::CGFontGetGlyphPath(mFont, &flip, 0, aBuffer.mGlyphs[i].mIndex); CGAffineTransform matrix = CGAffineTransformMake(mSize, 0, 0, mSize, aBuffer.mGlyphs[i].mPosition.x, aBuffer.mGlyphs[i].mPosition.y); CGPathAddPath(path, &matrix, glyphPath); CGPathRelease(glyphPath); } TemporaryRef<Path> ret = new PathCG(path, FillRule::FILL_WINDING); CGPathRelease(path); return ret; } return ScaledFontBase::GetPathForGlyphs(aBuffer, aTarget); }
CGContextRef BitLockerSkia::cgContext() { SkDevice* device = m_canvas->getDevice(); ASSERT(device); if (!device) return 0; releaseIfNeeded(); const SkBitmap& bitmap = device->accessBitmap(true); bitmap.lockPixels(); void* pixels = bitmap.getPixels(); m_cgContext = CGBitmapContextCreate(pixels, device->width(), device->height(), 8, bitmap.rowBytes(), CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst); // Apply device matrix. CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1); contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -device->height()); CGContextConcatCTM(m_cgContext, contentsTransform); // Apply clip in device coordinates. CGMutablePathRef clipPath = CGPathCreateMutable(); SkRegion::Iterator iter(m_canvas->getTotalClip()); for (; !iter.done(); iter.next()) { IntRect rect = iter.rect(); CGPathAddRect(clipPath, 0, rect); } CGContextAddPath(m_cgContext, clipPath); CGContextClip(m_cgContext); CGPathRelease(clipPath); // Apply content matrix. const SkMatrix& skMatrix = m_canvas->getTotalMatrix(); CGAffineTransform affine = SkMatrixToCGAffineTransform(skMatrix); CGContextConcatCTM(m_cgContext, affine); return m_cgContext; }
void QFontDatabase::load(const QFontPrivate *d, int script) { // sanity checks if(!qApp) qWarning("QFont: Must construct a QApplication before a QFont"); Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount); Q_UNUSED(script); QFontDef req = d->request; req.pixelSize = qt_mac_pixelsize(req, d->dpi); // set the point size to 0 to get better caching req.pointSize = 0; QFontCache::Key key = QFontCache::Key(req, QUnicodeTables::Common, d->screen); if(!(d->engineData = QFontCache::instance()->findEngineData(key))) { d->engineData = new QFontEngineData; QFontCache::instance()->insertEngineData(key, d->engineData); } else { d->engineData->ref.ref(); } if(d->engineData->engine) // already loaded return; // set it to the actual pointsize, so QFontInfo will do the right thing req.pointSize = qRound(qt_mac_pointsize(d->request, d->dpi)); QFontEngine *e = QFontCache::instance()->findEngine(key); if(!e && qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { e = new QTestFontEngine(req.pixelSize); e->fontDef = req; } if(e) { e->ref.ref(); d->engineData->engine = e; return; // the font info and fontdef should already be filled } //find the font QStringList family_list = familyList(req); const char *stylehint = styleHint(req); if (stylehint) family_list << QLatin1String(stylehint); // add QFont::defaultFamily() to the list, for compatibility with // previous versions family_list << QApplication::font().defaultFamily(); ATSFontFamilyRef familyRef = 0; ATSFontRef fontRef = 0; QMutexLocker locker(fontDatabaseMutex()); QFontDatabasePrivate *db = privateDb(); if (!db->count) initializeDb(); for(int i = 0; i < family_list.size(); ++i) { for (int k = 0; k < db->count; ++k) { if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) { QByteArray family_name = db->families[k]->name.toUtf8(); familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); if (familyRef) { fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); goto FamilyFound; } else { #if defined(QT_MAC_USE_COCOA) // ATS and CT disagrees on what the family name should be, // use CT to look up the font if ATS fails. QCFString familyName = QString::fromAscii(family_name); QCFType<CTFontRef> CTfontRef = CTFontCreateWithName(familyName, 12, NULL); QCFType<CTFontDescriptorRef> fontDescriptor = CTFontCopyFontDescriptor(CTfontRef); QCFString displayName = (CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontDisplayNameAttribute); familyRef = ATSFontFamilyFindFromName(displayName, kATSOptionFlagsDefault); if (familyRef) { fontRef = ATSFontFindFromName(displayName, kATSOptionFlagsDefault); goto FamilyFound; } #endif } } } } FamilyFound: //fill in the engine's font definition QFontDef fontDef = d->request; //copy.. if(fontDef.pointSize < 0) fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi); else fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi); #if 0 ItemCount name_count; if(ATSUCountFontNames(fontID, &name_count) == noErr && name_count) { ItemCount actualName_size; if(ATSUGetIndFontName(fontID, 0, 0, 0, &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) { QByteArray actualName(actualName_size); if(ATSUGetIndFontName(fontID, 0, actualName_size, actualName.data(), &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) fontDef.family = QString::fromUtf8(actualName); } } #else { QCFString actualName; if(ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr) fontDef.family = actualName; } #endif #ifdef QT_MAC_USE_COCOA QFontEngine *engine = new QCoreTextFontEngineMulti(familyRef, fontRef, fontDef, d->kerning); #elif 1 QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning); #else ATSFontFamilyRef atsFamily = familyRef; ATSFontFamilyRef atsFontRef = fontRef; FMFont fontID; FMFontFamily fmFamily; FMFontStyle fntStyle = 0; fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily); if (fmFamily == kInvalidFontFamily) { // Use the ATSFont then... fontID = FMGetFontFromATSFontRef(atsFontRef); } else { if (fontDef.weight >= QFont::Bold) fntStyle |= ::bold; if (fontDef.style != QFont::StyleNormal) fntStyle |= ::italic; FMFontStyle intrinsicStyle; FMFont fnt = 0; if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr) fontID = FMGetATSFontRefFromFont(fnt); } OSStatus status; const int maxAttributeCount = 5; ATSUAttributeTag tags[maxAttributeCount + 1]; ByteCount sizes[maxAttributeCount + 1]; ATSUAttributeValuePtr values[maxAttributeCount + 1]; int attributeCount = 0; Fixed size = FixRatio(fontDef.pixelSize, 1); tags[attributeCount] = kATSUSizeTag; sizes[attributeCount] = sizeof(size); values[attributeCount] = &size; ++attributeCount; tags[attributeCount] = kATSUFontTag; sizes[attributeCount] = sizeof(fontID); values[attributeCount] = &fontID; ++attributeCount; CGAffineTransform transform = CGAffineTransformIdentity; if (fontDef.stretch != 100) { transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); tags[attributeCount] = kATSUFontMatrixTag; sizes[attributeCount] = sizeof(transform); values[attributeCount] = &transform; ++attributeCount; } ATSUStyle style; status = ATSUCreateStyle(&style); Q_ASSERT(status == noErr); Q_ASSERT(attributeCount < maxAttributeCount + 1); status = ATSUSetAttributes(style, attributeCount, tags, sizes, values); Q_ASSERT(status == noErr); QFontEngine *engine = new QFontEngineMac(style, fontID, fontDef, /*multiEngine*/ 0); ATSUDisposeStyle(style); #endif d->engineData->engine = engine; engine->ref.ref(); //a ref for the engineData->engine QFontCache::instance()->insertEngine(key, engine); }
CGAffineTransform CGAffineTransformScale(CGAffineTransform T,CGFloat sx,CGFloat sy) { return CGAffineTransformConcat(T,CGAffineTransformMakeScale(sx,sy)); }
QFontEngineMacMulti::QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning) : QFontEngineMulti(0) { this->fontDef = fontDef; this->kerning = kerning; FMFontFamily fmFamily; FMFontStyle fntStyle = 0; fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily); if (fmFamily == kInvalidFontFamily) { // Use the ATSFont then... fontID = FMGetFontFromATSFontRef(atsFontRef); } else { if (fontDef.weight >= QFont::Bold) fntStyle |= ::bold; if (fontDef.style != QFont::StyleNormal) fntStyle |= ::italic; FMFontStyle intrinsicStyle; FMFont fnt = 0; if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr) fontID = FMGetATSFontRefFromFont(fnt); } OSStatus status; status = ATSUCreateTextLayout(&textLayout); Q_ASSERT(status == noErr); const int maxAttributeCount = 5; ATSUAttributeTag tags[maxAttributeCount + 1]; ByteCount sizes[maxAttributeCount + 1]; ATSUAttributeValuePtr values[maxAttributeCount + 1]; int attributeCount = 0; Fixed size = FixRatio(fontDef.pixelSize, 1); tags[attributeCount] = kATSUSizeTag; sizes[attributeCount] = sizeof(size); values[attributeCount] = &size; ++attributeCount; tags[attributeCount] = kATSUFontTag; sizes[attributeCount] = sizeof(fontID); values[attributeCount] = &this->fontID; ++attributeCount; transform = CGAffineTransformIdentity; if (fontDef.stretch != 100) { transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); tags[attributeCount] = kATSUFontMatrixTag; sizes[attributeCount] = sizeof(transform); values[attributeCount] = &transform; ++attributeCount; } status = ATSUCreateStyle(&style); Q_ASSERT(status == noErr); Q_ASSERT(attributeCount < maxAttributeCount + 1); status = ATSUSetAttributes(style, attributeCount, tags, sizes, values); Q_ASSERT(status == noErr); QFontEngineMac *fe = new QFontEngineMac(style, fontID, fontDef, this); fe->ref.ref(); engines.append(fe); }