diff options
Diffstat (limited to 'WebCore/platform/graphics/cairo/FontCairo.cpp')
-rw-r--r-- | WebCore/platform/graphics/cairo/FontCairo.cpp | 152 |
1 files changed, 62 insertions, 90 deletions
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp index cd5d362..3d55c70 100644 --- a/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -31,6 +31,8 @@ #include "Font.h" #include "AffineTransform.h" +#include "CairoUtilities.h" +#include "ContextShadow.h" #include "GlyphBuffer.h" #include "Gradient.h" #include "GraphicsContext.h" @@ -38,18 +40,63 @@ #include "Pattern.h" #include "SimpleFontData.h" -#define SYNTHETIC_OBLIQUE_ANGLE 14 - namespace WebCore { -void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, - int from, int numGlyphs, const FloatPoint& point) const +static void prepareContextForGlyphDrawing(cairo_t* context, const SimpleFontData* font, const FloatPoint& point) { - cairo_t* cr = context->platformContext(); - cairo_save(cr); + static const float syntheticObliqueSkew = -tanf(14 * acosf(0) / 90); + cairo_set_scaled_font(context, font->platformData().scaledFont()); + if (font->platformData().syntheticOblique()) { + cairo_matrix_t mat = {1, 0, syntheticObliqueSkew, 1, point.x(), point.y()}; + cairo_transform(context, &mat); + } else + cairo_translate(context, point.x(), point.y()); +} - cairo_set_scaled_font(cr, font->platformData().scaledFont()); +static void drawGlyphsToContext(cairo_t* context, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs) +{ + cairo_show_glyphs(context, glyphs, numGlyphs); + if (font->syntheticBoldOffset()) { + // We could use cairo_save/cairo_restore here, but two translations are likely faster. + cairo_translate(context, font->syntheticBoldOffset(), 0); + cairo_show_glyphs(context, glyphs, numGlyphs); + cairo_translate(context, -font->syntheticBoldOffset(), 0); + } +} + +static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs) +{ + ContextShadow* shadow = graphicsContext->contextShadow(); + ASSERT(shadow); + + if (!(graphicsContext->textDrawingMode() & cTextFill) || shadow->m_type == ContextShadow::NoShadow) + return; + + if (shadow->m_type == ContextShadow::SolidShadow) { + // Optimize non-blurry shadows, by just drawing text without the ContextShadow. + cairo_save(context); + cairo_translate(context, shadow->m_offset.width(), shadow->m_offset.height()); + setSourceRGBAFromColor(context, shadow->m_color); + prepareContextForGlyphDrawing(context, font, point); + cairo_show_glyphs(context, glyphs, numGlyphs); + cairo_restore(context); + return; + } + + cairo_text_extents_t extents; + cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents); + FloatRect fontExtentsRect(point.x(), point.y() - extents.height, extents.width, extents.height); + cairo_t* shadowContext = shadow->beginShadowLayer(context, fontExtentsRect); + if (shadowContext) { + prepareContextForGlyphDrawing(shadowContext, font, point); + drawGlyphsToContext(shadowContext, font, glyphs, numGlyphs); + shadow->endShadowLayer(context); + } +} +void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, + int from, int numGlyphs, const FloatPoint& point) const +{ GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from); float offset = 0.0f; @@ -59,75 +106,11 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons offset += glyphBuffer.advanceAt(from + i); } - Color fillColor = context->fillColor(); - - // Synthetic Oblique - if(font->platformData().syntheticOblique()) { - cairo_matrix_t mat = {1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, point.x(), point.y()}; - cairo_transform(cr, &mat); - } else { - cairo_translate(cr, point.x(), point.y()); - } - - // Text shadow, inspired by FontMac - FloatSize shadowOffset; - float shadowBlur = 0; - Color shadowColor; - bool hasShadow = context->textDrawingMode() & cTextFill - && context->getShadow(shadowOffset, shadowBlur, shadowColor); - - // TODO: Blur support - if (hasShadow) { - // Disable graphics context shadows (not yet implemented) and paint them manually - context->clearShadow(); - Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); - cairo_save(cr); - - float red, green, blue, alpha; - shadowFillColor.getRGBA(red, green, blue, alpha); - cairo_set_source_rgba(cr, red, green, blue, alpha); - -#if ENABLE(FILTERS) - cairo_text_extents_t extents; - cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents); - - FloatRect rect(FloatPoint(), FloatSize(extents.width, extents.height)); - IntSize shadowBufferSize; - FloatRect shadowRect; - float radius = 0; - context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur); - - // Draw shadow into a new ImageBuffer - OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); - GraphicsContext* shadowContext = shadowBuffer->context(); - cairo_t* shadowCr = shadowContext->platformContext(); - - cairo_translate(shadowCr, radius, extents.height + radius); - - cairo_set_scaled_font(shadowCr, font->platformData().scaledFont()); - cairo_show_glyphs(shadowCr, glyphs, numGlyphs); - if (font->syntheticBoldOffset()) { - cairo_save(shadowCr); - cairo_translate(shadowCr, font->syntheticBoldOffset(), 0); - cairo_show_glyphs(shadowCr, glyphs, numGlyphs); - cairo_restore(shadowCr); - } - cairo_translate(cr, 0.0, -extents.height); - context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); -#else - cairo_translate(cr, shadowOffset.width(), shadowOffset.height()); - cairo_show_glyphs(cr, glyphs, numGlyphs); - if (font->syntheticBoldOffset()) { - cairo_save(cr); - cairo_translate(cr, font->syntheticBoldOffset(), 0); - cairo_show_glyphs(cr, glyphs, numGlyphs); - cairo_restore(cr); - } -#endif - - cairo_restore(cr); - } + cairo_t* cr = context->platformContext(); + drawGlyphsShadow(context, cr, point, font, glyphs, numGlyphs); + cairo_save(cr); + prepareContextForGlyphDrawing(cr, font, point); if (context->textDrawingMode() & cTextFill) { if (context->fillGradient()) { cairo_set_source(cr, context->fillGradient()->platformGradient()); @@ -148,16 +131,10 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons cairo_pattern_destroy(pattern); } else { float red, green, blue, alpha; - fillColor.getRGBA(red, green, blue, alpha); + context->fillColor().getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha()); } - cairo_show_glyphs(cr, glyphs, numGlyphs); - if (font->syntheticBoldOffset()) { - cairo_save(cr); - cairo_translate(cr, font->syntheticBoldOffset(), 0); - cairo_show_glyphs(cr, glyphs, numGlyphs); - cairo_restore(cr); - } + drawGlyphsToContext(cr, font, glyphs, numGlyphs); } // Prevent running into a long computation within cairo. If the stroke width is @@ -183,20 +160,15 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons } cairo_pattern_destroy(pattern); } else { - Color strokeColor = context->strokeColor(); float red, green, blue, alpha; - strokeColor.getRGBA(red, green, blue, alpha); + context->strokeColor().getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha()); - } + } cairo_glyph_path(cr, glyphs, numGlyphs); cairo_set_line_width(cr, context->strokeThickness()); cairo_stroke(cr); } - // Re-enable the platform shadow we disabled earlier - if (hasShadow) - context->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace); - cairo_restore(cr); } |