summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/gtk/FontGtk.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/platform/graphics/gtk/FontGtk.cpp
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebCore/platform/graphics/gtk/FontGtk.cpp')
-rw-r--r--WebCore/platform/graphics/gtk/FontGtk.cpp206
1 files changed, 152 insertions, 54 deletions
diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp
index 5d50c6e..288ba91 100644
--- a/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -5,6 +5,7 @@
* Copyright (c) 2007 Kouhei Sutou
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2008 Xan Lopez <xan@gnome.org>
+ * Copyright (C) 2008 Nuanti Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,8 +38,18 @@
#include "SimpleFontData.h"
#include <cairo.h>
+#include <gdk/gdk.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>
+#if defined(USE_FREETYPE)
+#include <pango/pangofc-fontmap.h>
+#endif
+
+#if !defined(PANGO_VERSION_CHECK)
+// PANGO_VERSION_CHECK() and pango_layout_get_line_readonly() appeared in 1.5.2
+#define pango_layout_get_line_readonly pango_layout_get_line
+#define PANGO_VERSION_CHECK(major,minor,micro) 0
+#endif
namespace WebCore {
@@ -88,7 +99,7 @@ static void utf16_to_utf8(const UChar* aText, gint aLength, char* &text, gint &l
}
glong items_written;
- text = g_utf16_to_utf8(aText, aLength, NULL, &items_written, NULL);
+ text = g_utf16_to_utf8(reinterpret_cast<const gunichar2*>(aText), aLength, NULL, &items_written, NULL);
length = items_written;
if (need_copy)
@@ -133,10 +144,29 @@ static gchar* convertUniCharToUTF8(const UChar* characters, gint length, int fro
static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout* layout)
{
+#if defined(USE_FREETYPE)
+ if (font->primaryFont()->m_font.m_pattern) {
+ PangoFontDescription* desc = pango_fc_font_description_from_pattern(font->primaryFont()->m_font.m_pattern, FALSE);
+ pango_layout_set_font_description(layout, desc);
+ pango_font_description_free(desc);
+ }
+#elif defined(USE_PANGO)
+ if (font->primaryFont()->m_font.m_font) {
+ PangoFontDescription* desc = pango_font_describe(font->primaryFont()->m_font.m_font);
+ pango_layout_set_font_description(layout, desc);
+ pango_font_description_free(desc);
+ }
+#endif
+
+ pango_layout_set_auto_dir(layout, FALSE);
+
+ PangoContext* pangoContext = pango_layout_get_context(layout);
+ PangoDirection direction = run.rtl() ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+ pango_context_set_base_dir(pangoContext, direction);
PangoAttrList* list = pango_attr_list_new();
PangoAttribute* attr;
- attr = pango_attr_size_new_absolute((int)(font->size() * PANGO_SCALE));
+ attr = pango_attr_size_new_absolute(font->pixelSize() * PANGO_SCALE);
attr->end_index = G_MAXUINT;
pango_attr_list_insert_before(list, attr);
@@ -151,78 +181,111 @@ static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout
pango_layout_set_attributes(layout, list);
pango_attr_list_unref(list);
-
- pango_layout_set_auto_dir(layout, FALSE);
-
- PangoContext* pangoContext = pango_layout_get_context(layout);
- PangoDirection direction = run.rtl() ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
- pango_context_set_base_dir(pangoContext, direction);
}
-void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
- int from, int numGlyphs, const FloatPoint& point) const
+void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
- cairo_t* cr = graphicsContext->platformContext();
+ cairo_t* cr = context->platformContext();
cairo_save(cr);
+ cairo_translate(cr, point.x(), point.y());
- // Set the text color to use for drawing.
- float red, green, blue, alpha;
- Color penColor = graphicsContext->fillColor();
- penColor.getRGBA(red, green, blue, alpha);
- cairo_set_source_rgba(cr, red, green, blue, alpha);
-
- font->setFont(cr);
+ PangoLayout* layout = pango_cairo_create_layout(cr);
+ setPangoAttributes(this, run, layout);
- GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from);
+ gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
+ pango_layout_set_text(layout, utf8, -1);
- float offset = point.x();
+ // Our layouts are single line
+ PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0);
- for (int i = 0; i < numGlyphs; i++) {
- glyphs[i].x = offset;
- glyphs[i].y = point.y();
- offset += glyphBuffer.advanceAt(from + i);
+ GdkRegion* partialRegion = NULL;
+ if (to - from != run.length()) {
+ // Clip the region of the run to be rendered
+ char* start = g_utf8_offset_to_pointer(utf8, from);
+ char* end = g_utf8_offset_to_pointer(start, to - from);
+ int ranges[] = {start - utf8, end - utf8};
+ partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1);
+ gdk_region_shrink(partialRegion, 0, -pixelSize());
}
- cairo_show_glyphs(cr, glyphs, numGlyphs);
- cairo_restore(cr);
-}
+ Color fillColor = context->fillColor();
+ float red, green, blue, alpha;
-void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- cairo_t* cr = context->platformContext();
- cairo_save(cr);
+ // Text shadow, inspired by FontMac
+ IntSize shadowSize;
+ int shadowBlur = 0;
+ Color shadowColor;
+ bool hasShadow = context->textDrawingMode() == cTextFill &&
+ context->getShadow(shadowSize, shadowBlur, shadowColor);
- PangoLayout* layout = pango_cairo_create_layout(cr);
+ // 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);
- gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), from, to);
- pango_layout_set_text(layout, utf8, -1);
- g_free(utf8);
+ shadowFillColor.getRGBA(red, green, blue, alpha);
+ cairo_set_source_rgba(cr, red, green, blue, alpha);
- setPangoAttributes(this, run, layout);
+ cairo_translate(cr, shadowSize.width(), shadowSize.height());
- // Set the text color to use for drawing.
- float red, green, blue, alpha;
- Color penColor = context->fillColor();
- penColor.getRGBA(red, green, blue, alpha);
+ if (partialRegion) {
+ gdk_cairo_region(cr, partialRegion);
+ cairo_clip(cr);
+ }
+
+ pango_cairo_show_layout_line(cr, layoutLine);
+
+ cairo_restore(cr);
+ }
+
+ fillColor.getRGBA(red, green, blue, alpha);
cairo_set_source_rgba(cr, red, green, blue, alpha);
- // Our layouts are single line
- cairo_move_to(cr, point.x(), point.y());
- PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0);
+ if (partialRegion) {
+ gdk_cairo_region(cr, partialRegion);
+ cairo_clip(cr);
+ }
+
pango_cairo_show_layout_line(cr, layoutLine);
+ if (context->textDrawingMode() & cTextStroke) {
+ Color strokeColor = context->strokeColor();
+ strokeColor.getRGBA(red, green, blue, alpha);
+ cairo_set_source_rgba(cr, red, green, blue, alpha);
+ pango_cairo_layout_line_path(cr, layoutLine);
+ cairo_set_line_width(cr, context->strokeThickness());
+ cairo_stroke(cr);
+ }
+
+ // Re-enable the platform shadow we disabled earlier
+ if (hasShadow)
+ context->setShadow(shadowSize, shadowBlur, shadowColor);
+
+ // Pango sometimes leaves behind paths we don't want
+ cairo_new_path(cr);
+
+ if (partialRegion)
+ gdk_region_destroy(partialRegion);
+
+ g_free(utf8);
g_object_unref(layout);
+
cairo_restore(cr);
}
-// FIXME: we should create the layout with our actual context, but it seems
-// we can't access it from here
+// We should create the layout with our actual context but we can't access it from here.
static PangoLayout* getDefaultPangoLayout(const TextRun& run)
{
- PangoFontMap* map = pango_cairo_font_map_get_default();
- PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(map));
+ static PangoFontMap* map = pango_cairo_font_map_get_default();
+#if PANGO_VERSION_CHECK(1,21,5)
+ static PangoContext* pangoContext = pango_font_map_create_context(map);
+#else
+ // Deprecated in Pango 1.21.
+ static PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(map));
+#endif
PangoLayout* layout = pango_layout_new(pangoContext);
- g_object_unref(pangoContext);
return layout;
}
@@ -237,11 +300,11 @@ float Font::floatWidthForComplexText(const TextRun& run) const
gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
pango_layout_set_text(layout, utf8, -1);
- g_free(utf8);
- int layoutWidth;
- pango_layout_get_size(layout, &layoutWidth, 0);
- float width = (float)layoutWidth / (double)PANGO_SCALE;
+ int width;
+ pango_layout_get_pixel_size(layout, &width, 0);
+
+ g_free(utf8);
g_object_unref(layout);
return width;
@@ -258,6 +321,9 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includ
int index, trailing;
pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing);
glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index);
+ if (includePartialGlyphs)
+ offset += trailing;
+
g_free(utf8);
g_object_unref(layout);
@@ -266,8 +332,40 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includ
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
{
- notImplemented();
- return FloatRect();
+ PangoLayout* layout = getDefaultPangoLayout(run);
+ setPangoAttributes(this, run, layout);
+
+ gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
+ pango_layout_set_text(layout, utf8, -1);
+
+ char* start = g_utf8_offset_to_pointer(utf8, from);
+ char* end = g_utf8_offset_to_pointer(start, to - from);
+
+ if (run.ltr()) {
+ from = start - utf8;
+ to = end - utf8;
+ } else {
+ from = end - utf8;
+ to = start - utf8;
+ }
+
+ PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0);
+ int x_pos;
+
+ x_pos = 0;
+ if (from < layoutLine->length)
+ pango_layout_line_index_to_x(layoutLine, from, FALSE, &x_pos);
+ float beforeWidth = PANGO_PIXELS_FLOOR(x_pos);
+
+ x_pos = 0;
+ if (run.ltr() || to < layoutLine->length)
+ pango_layout_line_index_to_x(layoutLine, to, FALSE, &x_pos);
+ float afterWidth = PANGO_PIXELS(x_pos);
+
+ g_free(utf8);
+ g_object_unref(layout);
+
+ return FloatRect(point.x() + beforeWidth, point.y(), afterWidth - beforeWidth, h);
}
}