void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* font, const wxColour& color, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) { graphicsContext->save(); wxGCDC* dc = static_cast<wxGCDC*>(graphicsContext->platformContext()); wxFont* wxfont = font->getWxFont(); graphicsContext->setFillColor(graphicsContext->fillColor(), ColorSpaceDeviceRGB); CGContextRef cgContext = static_cast<CGContextRef>(dc->GetGraphicsContext()->GetNativeContext()); CGFontRef cgFont = font->platformData().cgFont(); CGContextSetFont(cgContext, cgFont); CGContextSetFontSize(cgContext, wxfont->GetPointSize()); CGFloat red, green, blue, alpha; graphicsContext->fillColor().getRGBA(red, green, blue, alpha); CGContextSetRGBFillColor(cgContext, red, green, blue, alpha); CGAffineTransform matrix = CGAffineTransformIdentity; matrix.b = -matrix.b; matrix.d = -matrix.d; CGContextSetTextMatrix(cgContext, matrix); CGContextSetTextPosition(cgContext, point.x(), point.y()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (cgFont) CGFontRelease(cgFont); graphicsContext->restore(); }
void quartz_draw_layout(void *layout, CGContextRef context, CGPoint position) { CGContextSetTextPosition(context, position.x, position.y); CFArrayRef runs = CTLineGetGlyphRuns((CTLineRef)layout); CFIndex run_count = CFArrayGetCount(runs); CFIndex run_index; for (run_index = 0; run_index < run_count; ++run_index) { CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, run_index); CTFontRef run_font = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName); CGFontRef glyph_font = CTFontCopyGraphicsFont(run_font, NULL); CFIndex glyph_count = CTRunGetGlyphCount(run); CGGlyph glyphs[glyph_count]; CGPoint positions[glyph_count]; CFRange everything = CFRangeMake(0, 0); CTRunGetGlyphs(run, everything, glyphs); CTRunGetPositions(run, everything, positions); CGContextSetFont(context, glyph_font); CGContextSetFontSize(context, CTFontGetSize(run_font)); CGContextShowGlyphsAtPositions(context, glyphs, positions, glyph_count); CGFontRelease(glyph_font); } }
FX_BOOL CQuartz2D::drawGraphicsString(void* graphics, void* font, FX_FLOAT fontSize, FX_WORD* glyphIndices, CGPoint* glyphPositions, FX_INT32 charsCount, FX_ARGB argb, CFX_AffineMatrix* matrix ) { if (!graphics) { return FALSE; } CGContextRef context = (CGContextRef) graphics; CGContextSetFont(context, (CGFontRef)font); CGContextSetFontSize(context, fontSize); if (matrix) { CGAffineTransform m = CGContextGetTextMatrix(context); m = CGAffineTransformConcat(m, CGAffineTransformMake(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, matrix->f)); CGContextSetTextMatrix(context, m); } FX_INT32 a, r, g, b; ArgbDecode(argb, a, r, g, b); CGContextSetRGBFillColor(context, r / 255.f, g / 255.f, b / 255.f, a / 255.f); CGContextSaveGState(context); #if CGFLOAT_IS_DOUBLE CGPoint* glyphPositionsCG = new CGPoint[charsCount]; if (!glyphPositionsCG) { return FALSE; } for (int index = 0; index < charsCount; ++index) { glyphPositionsCG[index].x = glyphPositions[index].x; glyphPositionsCG[index].y = glyphPositions[index].y; } #else CGPoint* glyphPositionsCG = (CGPoint*)glyphPositions; #endif CGContextShowGlyphsAtPositions(context, (CGGlyph *) glyphIndices, glyphPositionsCG, charsCount); #if CGFLOAT_IS_DOUBLE delete[] glyphPositionsCG; #endif CGContextRestoreGState(context); return TRUE; }
void QFontEngineMac::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) { QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> glyphs; QTransform matrix; matrix.translate(x, y); getGlyphPositions(ti.glyphs, ti.num_glyphs, matrix, ti.flags, glyphs, positions); if (glyphs.size() == 0) return; CGContextSetFontSize(ctx, fontDef.pixelSize); CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight); CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, multiEngine->transform); CGContextSetTextMatrix(ctx, cgMatrix); CGContextSetTextDrawingMode(ctx, kCGTextFill); QVarLengthArray<CGSize> advances(glyphs.size()); QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size()); for (int i = 0; i < glyphs.size() - 1; ++i) { advances[i].width = (positions[i + 1].x - positions[i].x).toReal(); advances[i].height = (positions[i + 1].y - positions[i].y).toReal(); cgGlyphs[i] = glyphs[i]; } advances[glyphs.size() - 1].width = 0; advances[glyphs.size() - 1].height = 0; cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1]; CGContextSetFont(ctx, cgFont); CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal()); CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); if (synthesisFlags & QFontEngine::SynthesizedBold) { CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(), positions[0].y.toReal()); CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); } CGContextSetTextMatrix(ctx, oldTextMatrix); }
void Font::drawGlyphs(GraphicsContext* graphicsContext, const FontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const { CGContextRef cgContext = graphicsContext->platformContext(); uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext); const FontPlatformData& platformData = font->platformData(); //NSFont* drawFont; //if ([gContext isDrawingToScreen]) { // drawFont = [platformData.font screenFont]; // if (drawFont != platformData.font) // // We are getting this in too many places (3406411); use ERROR so it only prints on debug versions for now. (We should debug this also, eventually). // LOG_ERROR("Attempting to set non-screen font (%@) when drawing to screen. Using screen font anyway, may result in incorrect metrics.", // [[[platformData.font fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]); //} else { // drawFont = [platformData.font printerFont]; // if (drawFont != platformData.font) // NSLog(@"Attempting to set non-printer font (%@) when printing. Using printer font anyway, may result in incorrect metrics.", // [[[platformData.font fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]); //} CGContextSetFont(cgContext, platformData.cgFont()); CGAffineTransform matrix = CGAffineTransformIdentity; matrix.b = -matrix.b; matrix.d = -matrix.d; if (platformData.syntheticOblique()) { static float skew = -tanf(syntheticObliqueAngle * acosf(0) / 90); matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, skew, 1, 0, 0)); } // Uniscribe gives us offsets to help refine the positioning of combining glyphs. FloatSize translation = glyphBuffer.offsetAt(from); if (translation.width() || translation.height()) CGAffineTransformTranslate(matrix, translation.width(), translation.height()); CGContextSetTextMatrix(cgContext, matrix); //wkSetCGFontRenderingMode(cgContext, drawFont); CGContextSetFontSize(cgContext, platformData.size()); CGContextSetTextPosition(cgContext, point.x(), point.y()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (font->m_syntheticBoldOffset) { CGContextSetTextPosition(cgContext, point.x() + font->m_syntheticBoldOffset, point.y()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); } wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle); }
void MacVegaPrinterListener::DrawString(const OpPoint& pos, const uni_char* text, UINT32 len, INT32 extra_char_spacing, short word_width) { CGContextSaveGState(m_ctx); CGContextTranslateCTM(m_ctx, 0, m_winHeight); OpPoint pt(pos.x, pos.y); if (m_font) { CGContextSetFont(m_ctx, m_font->GetCGFontRef()); CGContextSetFontSize(m_ctx, m_font->GetSize()); m_font->DrawStringUsingFallback(pt, text, len, extra_char_spacing, m_ctx); } CGContextRestoreGState(m_ctx); }
static void cgSetPaintForText(CGContextRef cg, const SkPaint& paint) { SkColor c = paint.getColor(); CGFloat rgba[] = { SkColorGetB(c) / 255.0f, SkColorGetG(c) / 255.0f, SkColorGetR(c) / 255.0f, SkColorGetA(c) / 255.0f, }; CGContextSetRGBFillColor(cg, rgba[0], rgba[1], rgba[2], rgba[3]); CGContextSetTextDrawingMode(cg, kCGTextFill); CGContextSetFont(cg, typefaceToCGFont(paint.getTypeface())); CGContextSetFontSize(cg, SkScalarToFloat(paint.getTextSize())); CGContextSetAllowsFontSubpixelPositioning(cg, paint.isSubpixelText()); CGContextSetShouldSubpixelPositionFonts(cg, paint.isSubpixelText()); CGContextSetShouldAntialias(cg, paint.isAntiAlias()); CGContextSetShouldSmoothFonts(cg, paint.isLCDRenderText()); }
bool sdl_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) { UniChar uni_char; CGGlyph glyph; CTFontRef ct_font = (CTFontRef)font; const CFIndex count = 1; CGRect bounding_rect, success_rect; CGContextRef context_ref; if( chnum == ' ' ) { uni_char = 'n'; CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count ); success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count ); uni_char = chnum; CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count ); } else { uni_char = chnum; CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count ); success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count ); } if( CGRectEqualToRect( success_rect, CGRectNull ) == false ) { size_t bitmap_width; size_t bitmap_height; bitmap_width = ceilf(bounding_rect.size.width * EXTRA_WIDTH); bitmap_width = bitmap_width == 0 ? 1 : bitmap_width; bitmap_height = ceilf( (CTFontGetAscent(ct_font) + CTFontGetDescent(ct_font) + CTFontGetLeading(ct_font)) * EXTRA_HEIGHT); xoffs = yoffs = 0; width = bitmap_width; size_t bits_per_component; CGColorSpaceRef color_space; CGBitmapInfo bitmap_info = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst; color_space = CGColorSpaceCreateDeviceRGB(); bits_per_component = 8; bitmap.allocate(bitmap_width, bitmap_height); context_ref = CGBitmapContextCreate( bitmap.raw_pixptr(0), bitmap_width, bitmap_height, bits_per_component, bitmap.rowpixels()*4, color_space, bitmap_info ); if( context_ref != NULL ) { CGFontRef font_ref; font_ref = CTFontCopyGraphicsFont( ct_font, NULL ); CGContextSetTextPosition(context_ref, -bounding_rect.origin.x*EXTRA_WIDTH, CTFontGetDescent(ct_font)+CTFontGetLeading(ct_font) ); CGContextSetRGBFillColor(context_ref, 1.0, 1.0, 1.0, 1.0); CGContextSetFont( context_ref, font_ref ); CGContextSetFontSize( context_ref, POINT_SIZE ); CGContextShowGlyphs( context_ref, &glyph, count ); CGFontRelease( font_ref ); CGContextRelease( context_ref ); } CGColorSpaceRelease( color_space ); } return bitmap.valid(); }
void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const { CGContextRef cgContext = graphicsContext->platformContext(); bool shouldUseFontSmoothing = WebCoreShouldUseFontSmoothing(); switch(fontDescription().fontSmoothing()) { case Antialiased: { graphicsContext->setShouldAntialias(true); shouldUseFontSmoothing = false; break; } case SubpixelAntialiased: { graphicsContext->setShouldAntialias(true); shouldUseFontSmoothing = true; break; } case NoSmoothing: { graphicsContext->setShouldAntialias(false); shouldUseFontSmoothing = false; break; } case AutoSmoothing: { // For the AutoSmooth case, don't do anything! Keep the default settings. break; } default: ASSERT_NOT_REACHED(); } if (font->platformData().useGDI() && !shouldUseFontSmoothing) { drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point); return; } uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext, shouldUseFontSmoothing); const FontPlatformData& platformData = font->platformData(); CGContextSetFont(cgContext, platformData.cgFont()); CGAffineTransform matrix = CGAffineTransformIdentity; matrix.b = -matrix.b; matrix.d = -matrix.d; if (platformData.syntheticOblique()) { static float skew = -tanf(syntheticObliqueAngle * piFloat / 180.0f); matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, skew, 1, 0, 0)); } CGContextSetTextMatrix(cgContext, matrix); // Uniscribe gives us offsets to help refine the positioning of combining glyphs. FloatSize translation = glyphBuffer.offsetAt(from); CGContextSetFontSize(cgContext, platformData.size()); wkSetCGContextFontRenderingStyle(cgContext, font->isSystemFont(), false, font->platformData().useGDI()); FloatSize shadowOffset; float shadowBlur; Color shadowColor; ColorSpace shadowColorSpace; graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); bool hasSimpleShadow = graphicsContext->textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && (!graphicsContext->shadowsIgnoreTransforms() || graphicsContext->getCTM().isIdentityOrTranslationOrFlipped()); if (hasSimpleShadow) { // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing. graphicsContext->clearShadow(); Color fillColor = graphicsContext->fillColor(); Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); graphicsContext->setFillColor(shadowFillColor, ColorSpaceDeviceRGB); float shadowTextX = point.x() + translation.width() + shadowOffset.width(); // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative. float shadowTextY = point.y() + translation.height() + shadowOffset.height() * (graphicsContext->shadowsIgnoreTransforms() ? -1 : 1); CGContextSetTextPosition(cgContext, shadowTextX, shadowTextY); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (font->syntheticBoldOffset()) { CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowOffset.height()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); } graphicsContext->setFillColor(fillColor, ColorSpaceDeviceRGB); } CGContextSetTextPosition(cgContext, point.x() + translation.width(), point.y() + translation.height()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (font->syntheticBoldOffset()) { CGContextSetTextPosition(cgContext, point.x() + translation.width() + font->syntheticBoldOffset(), point.y() + translation.height()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); } if (hasSimpleShadow) graphicsContext->setShadow(shadowOffset, shadowBlur, shadowColor, ColorSpaceDeviceRGB); wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle); }
void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* font, const wxColour& color, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) { graphicsContext->save(); wxGCDC* dc = static_cast<wxGCDC*>(graphicsContext->platformContext()); wxFont* wxfont = font->getWxFont(); graphicsContext->setFillColor(graphicsContext->fillColor(), DeviceColorSpace); CGContextRef cgContext = static_cast<CGContextRef>(dc->GetGraphicsContext()->GetNativeContext()); CGFontRef cgFont; #ifdef wxOSX_USE_CORE_TEXT && wxOSX_USE_CORE_TEXT cgFont = CTFontCopyGraphicsFont((CTFontRef)wxfont->OSXGetCTFont(), NULL); #else ATSFontRef fontRef; fontRef = FMGetATSFontRefFromFont(wxfont->MacGetATSUFontID()); if (fontRef) cgFont = CGFontCreateWithPlatformFont((void*)&fontRef); #endif CGContextSetFont(cgContext, cgFont); CGContextSetFontSize(cgContext, wxfont->GetPointSize()); CGFloat red, green, blue, alpha; graphicsContext->fillColor().getRGBA(red, green, blue, alpha); CGContextSetRGBFillColor(cgContext, red, green, blue, alpha); CGAffineTransform matrix = CGAffineTransformIdentity; matrix.b = -matrix.b; matrix.d = -matrix.d; CGContextSetTextMatrix(cgContext, matrix); CGContextSetTextPosition(cgContext, point.x(), point.y()); const FloatSize* advanceSizes = static_cast<const FloatSize*>(glyphBuffer.advances(from)); int size = glyphBuffer.size() - from; CGSize sizes[size]; CGGlyph glyphs[numGlyphs]; // if the function doesn't exist, we're probably on tiger and need to grab the // function under its old name, CGFontGetGlyphsForUnicodes if (!CGFontGetGlyphsForUnichars) CGFontGetGlyphsForUnichars = (CGFontGetGlyphsForUnicharsPtr)dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnicodes"); // Let's make sure we got the function under one name or another! ASSERT(CGFontGetGlyphsForUnichars); CGFontGetGlyphsForUnichars(cgFont, glyphBuffer.glyphs(from), glyphs, numGlyphs); for (int i = 0; i < size; i++) { FloatSize fsize = advanceSizes[i]; sizes[i] = CGSizeMake(fsize.width(), fsize.height()); } CGContextShowGlyphsWithAdvances(cgContext, glyphs, sizes, numGlyphs); if (cgFont) CGFontRelease(cgFont); graphicsContext->restore(); }
static cairo_int_status_t _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, cairo_scaled_glyph_t *scaled_glyph) { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); cairo_image_surface_t *surface = NULL; CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); int advance; CGRect bbox; double width, height; double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); CGContextRef cgContext = NULL; CGAffineTransform textMatrix; CGRect glyphRect, glyphRectInt; CGPoint glyphOrigin; //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface); /* Create blank 2x2 image if we don't have this character. * Maybe we should draw a better missing-glyph slug or something, * but this is ok for now. */ if (glyph == INVALID_GLYPH) { surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2); status = cairo_surface_status ((cairo_surface_t *) surface); if (status) return status; _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface); return CAIRO_STATUS_SUCCESS; } if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) || !CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox)) { return CAIRO_INT_STATUS_UNSUPPORTED; } /* scale(1,-1) * font->base.scale * scale(1,-1) */ textMatrix = CGAffineTransformMake (font->base.scale.xx, -font->base.scale.yx, -font->base.scale.xy, font->base.scale.yy, 0, -0); glyphRect = CGRectMake (bbox.origin.x / emscale, bbox.origin.y / emscale, bbox.size.width / emscale, bbox.size.height / emscale); glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix); /* Round the rectangle outwards, so that we don't have to deal * with non-integer-pixel origins or dimensions. */ glyphRectInt = CGRectIntegral (glyphRect); #if 0 fprintf (stderr, "glyphRect[o]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); fprintf (stderr, "glyphRectInt: %f %f %f %f\n", glyphRectInt.origin.x, glyphRectInt.origin.y, glyphRectInt.size.width, glyphRectInt.size.height); #endif glyphOrigin = glyphRectInt.origin; //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm)); width = glyphRectInt.size.width; height = glyphRectInt.size.height; //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); if (surface->base.status) return surface->base.status; if (surface->width != 0 && surface->height != 0) { cgContext = CGBitmapContextCreate (surface->data, surface->width, surface->height, 8, surface->stride, NULL, kCGImageAlphaOnly); if (cgContext == NULL) { cairo_surface_destroy (&surface->base); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } CGContextSetFont (cgContext, font_face->cgFont); CGContextSetFontSize (cgContext, 1.0); CGContextSetTextMatrix (cgContext, textMatrix); switch (font->base.options.antialias) { case CAIRO_ANTIALIAS_SUBPIXEL: case CAIRO_ANTIALIAS_BEST: CGContextSetShouldAntialias (cgContext, TRUE); CGContextSetShouldSmoothFonts (cgContext, TRUE); if (CGContextSetAllowsFontSmoothingPtr && !CGContextGetAllowsFontSmoothingPtr (cgContext)) CGContextSetAllowsFontSmoothingPtr (cgContext, TRUE); break; case CAIRO_ANTIALIAS_NONE: CGContextSetShouldAntialias (cgContext, FALSE); break; case CAIRO_ANTIALIAS_GRAY: case CAIRO_ANTIALIAS_GOOD: case CAIRO_ANTIALIAS_FAST: CGContextSetShouldAntialias (cgContext, TRUE); CGContextSetShouldSmoothFonts (cgContext, FALSE); break; case CAIRO_ANTIALIAS_DEFAULT: default: /* Don't do anything */ break; } CGContextSetAlpha (cgContext, 1.0); CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1); CGContextRelease (cgContext); } cairo_surface_set_device_offset (&surface->base, - glyphOrigin.x, height + glyphOrigin.y); _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface); return status; }
static cairo_status_t _cairo_atsui_font_show_glyphs(void *abstract_font, cairo_operator_t operator, cairo_pattern_t *pattern, cairo_surface_t *generic_surface, int source_x, int source_y, int dest_x, int dest_y, unsigned int width, unsigned int height, const cairo_glyph_t *glyphs, int num_glyphs) { cairo_atsui_font_t *font = abstract_font; CGContextRef myBitmapContext; CGColorSpaceRef colorSpace; cairo_image_surface_t *destImageSurface; int i; void *extra = NULL; cairo_rectangle_t rect = {dest_x, dest_y, width, height}; _cairo_surface_acquire_dest_image(generic_surface, &rect, &destImageSurface, &rect, &extra); // Create a CGBitmapContext for the dest surface for drawing into colorSpace = CGColorSpaceCreateDeviceRGB(); myBitmapContext = CGBitmapContextCreate(destImageSurface->data, destImageSurface->width, destImageSurface->height, destImageSurface->depth / 4, destImageSurface->stride, colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height); CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f); ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID); CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont); CGContextSetFont(myBitmapContext, cgFont); CGAffineTransform textTransform = CGAffineTransformMakeWithCairoFontScale(&font->scale); textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f); CGContextSetFontSize(myBitmapContext, 1.0); CGContextSetTextMatrix(myBitmapContext, textTransform); if (pattern->type == CAIRO_PATTERN_SOLID && _cairo_pattern_is_opaque_solid(pattern)) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern; CGContextSetRGBFillColor(myBitmapContext, solid->color.red, solid->color.green, solid->color.blue, 1.0f); } else { CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f); } // TODO - bold and italic text // // We could draw the text using ATSUI and get bold, italics // etc. for free, but ATSUI does a lot of text layout work // that we don't really need... for (i = 0; i < num_glyphs; i++) { CGGlyph theGlyph = glyphs[i].index; CGContextShowGlyphsAtPoint(myBitmapContext, glyphs[i].x, glyphs[i].y, &theGlyph, 1); } CGColorSpaceRelease(colorSpace); CGContextRelease(myBitmapContext); _cairo_surface_release_dest_image(generic_surface, &rect, destImageSurface, &rect, extra); return CAIRO_STATUS_SUCCESS; }
static cairo_int_status_t _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, cairo_scaled_glyph_t *scaled_glyph) { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); cairo_image_surface_t *surface = NULL; CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); int advance; CGRect bbox; double width, height; double xscale, yscale; double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); CGColorSpaceRef gray; CGContextRef cgContext = NULL; CGAffineTransform textMatrix; CGRect glyphRect, glyphRectInt; CGPoint glyphOrigin; //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface); /* Create blank 2x2 image if we don't have this character. * Maybe we should draw a better missing-glyph slug or something, * but this is ok for now. */ if (glyph == INVALID_GLYPH) { surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2); status = cairo_surface_status ((cairo_surface_t *) surface); if (status) return status; _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface); return CAIRO_STATUS_SUCCESS; } if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) || !CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox)) { return CAIRO_INT_STATUS_UNSUPPORTED; } status = _cairo_matrix_compute_basis_scale_factors (&font->base.scale, &xscale, &yscale, 1); if (status) return status; textMatrix = CGAffineTransformMake (font->base.scale.xx, -font->base.scale.yx, -font->base.scale.xy, font->base.scale.yy, 0.0f, 0.0f); glyphRect = CGRectMake (bbox.origin.x / emscale, bbox.origin.y / emscale, bbox.size.width / emscale, bbox.size.height / emscale); glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix); /* Round the rectangle outwards, so that we don't have to deal * with non-integer-pixel origins or dimensions. */ glyphRectInt = CGRectIntegral (glyphRect); #if 0 fprintf (stderr, "glyphRect[o]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); fprintf (stderr, "glyphRectInt: %f %f %f %f\n", glyphRectInt.origin.x, glyphRectInt.origin.y, glyphRectInt.size.width, glyphRectInt.size.height); #endif glyphOrigin = glyphRectInt.origin; //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm)); width = glyphRectInt.size.width; height = glyphRectInt.size.height; //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); if (surface->base.status) return surface->base.status; gray = CGColorSpaceCreateDeviceGray (); cgContext = CGBitmapContextCreate (surface->data, surface->width, surface->height, 8, surface->stride, gray, kCGImageAlphaNone); CGColorSpaceRelease (gray); CGContextSetFont (cgContext, font_face->cgFont); CGContextSetFontSize (cgContext, 1.0); CGContextSetTextMatrix (cgContext, textMatrix); CGContextClearRect (cgContext, CGRectMake (0.0f, 0.0f, width, height)); if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE) CGContextSetShouldAntialias (cgContext, false); CGContextSetRGBFillColor (cgContext, 1.0, 1.0, 1.0, 1.0); CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1); CGContextRelease (cgContext); cairo_surface_set_device_offset (&surface->base, - glyphOrigin.x, height + glyphOrigin.y); _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface); return status; }
FX_BOOL CFX_QuartzDeviceDriver::CG_DrawGlypRun(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, CFX_FontCache* pCache, const CFX_AffineMatrix* pGlyphMatrix, const CFX_AffineMatrix* pObject2Device, FX_FLOAT font_size, FX_DWORD argb, int alpha_flag, void* pIccTransform) { if (nChars == 0) { return TRUE; } CQuartz2D& quartz2d = ((CApplePlatform *) CFX_GEModule::Get()->GetPlatformData())->_quartz2d; if (!pFont->m_pPlatformFont) { if (pFont->GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) { return FALSE; } pFont->m_pPlatformFont = quartz2d.CreateFont(pFont->m_pFontData, pFont->m_dwSize); if (NULL == pFont->m_pPlatformFont) { return FALSE; } } CFX_FixedBufGrow<FX_WORD, 32> glyph_indices(nChars); CFX_FixedBufGrow<CGPoint, 32> glyph_positions(nChars); for (int i = 0; i < nChars; i++ ) { glyph_indices[i] = pCharPos[i].m_ExtGID; glyph_positions[i].x = pCharPos[i].m_OriginX; glyph_positions[i].y = pCharPos[i].m_OriginY; } CFX_AffineMatrix text_matrix; if (pObject2Device) { text_matrix.Concat(*pObject2Device); } CGAffineTransform matrix_cg = CGAffineTransformMake(text_matrix.a, text_matrix.b, text_matrix.c, text_matrix.d, text_matrix.e, text_matrix.f); matrix_cg = CGAffineTransformConcat(matrix_cg, _foxitDevice2User); CGContextSetTextMatrix(_context, matrix_cg); CGContextSetFont(_context, (CGFontRef)pFont->m_pPlatformFont); CGContextSetFontSize(_context, FXSYS_fabs(font_size)); FX_INT32 a, r, g, b; ArgbDecode(argb, a, r, g, b); CGContextSetRGBFillColor(_context, r / 255.f, g / 255.f, b / 255.f, a / 255.f); SaveState(); if (pGlyphMatrix) { CGPoint origin = CGPointMake( glyph_positions[0].x, glyph_positions[0].y); origin = CGPointApplyAffineTransform(origin, matrix_cg); CGContextTranslateCTM(_context, origin.x, origin.y); CGAffineTransform glyph_matrix = CGAffineTransformMake(pGlyphMatrix->a, pGlyphMatrix->b, pGlyphMatrix->c, pGlyphMatrix->d, pGlyphMatrix->e, pGlyphMatrix->f); if (_foxitDevice2User.d < 0) { glyph_matrix = CGAffineTransformInvert(glyph_matrix); } CGContextConcatCTM(_context, glyph_matrix); CGContextTranslateCTM(_context, -origin.x, -origin.y); } CGContextShowGlyphsAtPositions(_context, (CGGlyph*)glyph_indices, glyph_positions, nChars); RestoreState(FALSE); return TRUE; }
QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph) { const glyph_metrics_t br = boundingBox(glyph); QImage im(qRound(br.width)+2, qRound(br.height)+2, QImage::Format_RGB32); im.fill(0); CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint cgflags = kCGImageAlphaNoneSkipFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) cgflags |= kCGBitmapByteOrder32Host; #endif #else CGImageAlphaInfo cgflags = kCGImageAlphaNoneSkipFirst; #endif CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), 8, im.bytesPerLine(), colorspace, cgflags); CGColorSpaceRelease(colorspace); CGContextSetFontSize(ctx, fontDef.pixelSize); CGContextSetShouldAntialias(ctx, fontDef.pointSize > qt_antialiasing_threshold && !(fontDef.styleStrategy & QFont::NoAntialias)); CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0); CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, multiEngine->transform); CGContextSetTextMatrix(ctx, cgMatrix); CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); CGContextSetTextDrawingMode(ctx, kCGTextFill); CGContextSetFont(ctx, cgFont); qreal pos_x = -br.x.toReal()+1, pos_y = im.height()+br.y.toReal(); CGContextSetTextPosition(ctx, pos_x, pos_y); CGSize advance; advance.width = 0; advance.height = 0; CGGlyph cgGlyph = glyph; CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); if (synthesisFlags & QFontEngine::SynthesizedBold) { CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y); CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); } CGContextRelease(ctx); QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); QVector<QRgb> colors(256); for (int i=0; i<256; ++i) colors[i] = qRgba(0, 0, 0, i); indexed.setColorTable(colors); for (int y=0; y<im.height(); ++y) { uint *src = (uint*) im.scanLine(y); uchar *dst = indexed.scanLine(y); for (int x=0; x<im.width(); ++x) { *dst = qGray(*src); ++dst; ++src; } } return indexed; }
void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const { CGContextRef cgContext = graphicsContext->platformContext(); bool shouldUseFontSmoothing = WebCoreShouldUseFontSmoothing(); if (font->platformData().useGDI()) { static bool canUsePlatformNativeGlyphs = wkCanUsePlatformNativeGlyphs(); if (!canUsePlatformNativeGlyphs || !shouldUseFontSmoothing || (graphicsContext->textDrawingMode() & cTextStroke)) { drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point); return; } } uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext, shouldUseFontSmoothing); const FontPlatformData& platformData = font->platformData(); CGContextSetFont(cgContext, platformData.cgFont()); CGAffineTransform matrix = CGAffineTransformIdentity; matrix.b = -matrix.b; matrix.d = -matrix.d; if (platformData.syntheticOblique()) { static float skew = -tanf(syntheticObliqueAngle * piFloat / 180.0f); matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, skew, 1, 0, 0)); } CGContextSetTextMatrix(cgContext, matrix); // Uniscribe gives us offsets to help refine the positioning of combining glyphs. FloatSize translation = glyphBuffer.offsetAt(from); CGContextSetFontSize(cgContext, platformData.size()); wkSetCGContextFontRenderingStyle(cgContext, font->isSystemFont(), false, font->platformData().useGDI()); IntSize shadowSize; int shadowBlur; Color shadowColor; graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor); bool hasSimpleShadow = graphicsContext->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur; if (hasSimpleShadow) { // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing. graphicsContext->clearShadow(); Color fillColor = graphicsContext->fillColor(); Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); graphicsContext->setFillColor(shadowFillColor); CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width(), point.y() + translation.height() + shadowSize.height()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (font->m_syntheticBoldOffset) { CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width() + font->m_syntheticBoldOffset, point.y() + translation.height() + shadowSize.height()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); } graphicsContext->setFillColor(fillColor); } CGContextSetTextPosition(cgContext, point.x() + translation.width(), point.y() + translation.height()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (font->m_syntheticBoldOffset) { CGContextSetTextPosition(cgContext, point.x() + translation.width() + font->m_syntheticBoldOffset, point.y() + translation.height()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); } if (hasSimpleShadow) graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor); wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle); }