summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/cairo/FontCairo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/cairo/FontCairo.cpp')
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp152
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);
}