Changeset 29334 in webkit
- Timestamp:
- Jan 8, 2008 8:45:32 PM (16 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r29333 r29334 1 2008-01-08 Xan Lopez <xan@gnome.org> 2 3 Reviewed by Alp Toker. 4 5 http://bugs.webkit.org/show_bug.cgi?id=15610 6 [GTK] Text rendering using Pango 7 8 Use Pango to render Complex path text. 9 10 * platform/graphics/gtk/FontGtk.cpp: 11 (WebCore::utf16_to_utf8): 12 (WebCore::convertUniCharToUTF8): 13 (WebCore::setPangoAttributes): 14 (WebCore::Font::drawGlyphs): 15 (WebCore::Font::drawComplexText): 16 (WebCore::Font::floatWidthForComplexText): 17 (WebCore::Font::offsetForPositionForComplexText): 18 1 19 2008-01-08 Timothy Hatcher <timothy@apple.com> 2 20 -
trunk/WebCore/platform/graphics/gtk/FontGtk.cpp
r29250 r29334 2 2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. 3 3 * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com 4 * Copyright (c) 2007 Hiroyuki Ikezoe 5 * Copyright (c) 2007 Kouhei Sutou 6 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 7 * Copyright (C) 2008 Xan Lopez <xan@gnome.org> 4 8 * All rights reserved. 5 9 * … … 32 36 #include "NotImplemented.h" 33 37 #include "SimpleFontData.h" 38 34 39 #include <cairo.h> 40 #include <pango/pango.h> 41 #include <pango/pangocairo.h> 35 42 36 43 namespace WebCore { 44 45 #define IS_HIGH_SURROGATE(u) ((UChar)(u) >= (UChar)0xd800 && (UChar)(u) <= (UChar)0xdbff) 46 #define IS_LOW_SURROGATE(u) ((UChar)(u) >= (UChar)0xdc00 && (UChar)(u) <= (UChar)0xdfff) 47 48 static void utf16_to_utf8(const UChar* aText, gint aLength, char* &text, gint &length) 49 { 50 gboolean need_copy = FALSE; 51 int i; 52 53 for (i = 0; i < aLength; i++) { 54 if (!aText[i] || IS_LOW_SURROGATE(aText[i])) { 55 need_copy = TRUE; 56 break; 57 } 58 else if (IS_HIGH_SURROGATE(aText[i])) { 59 if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1])) 60 i++; 61 else { 62 need_copy = TRUE; 63 break; 64 } 65 } 66 } 67 68 if (need_copy) { 69 70 /* Pango doesn't correctly handle nuls. We convert them to 0xff. */ 71 /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */ 72 73 UChar* p = (UChar*)g_memdup(aText, aLength * sizeof(aText[0])); 74 75 /* don't need to reset i */ 76 for (i = 0; i < aLength; i++) { 77 if (!p[i] || IS_LOW_SURROGATE(p[i])) 78 p[i] = 0xFFFD; 79 else if (IS_HIGH_SURROGATE(p[i])) { 80 if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1])) 81 i++; 82 else 83 p[i] = 0xFFFD; 84 } 85 } 86 87 aText = p; 88 } 89 90 glong items_written; 91 text = g_utf16_to_utf8(aText, aLength, NULL, &items_written, NULL); 92 length = items_written; 93 94 if (need_copy) 95 g_free((gpointer)aText); 96 97 } 98 99 static gchar* convertUniCharToUTF8(const UChar* characters, gint length, int from, int to) 100 { 101 gchar* utf8 = 0; 102 gint new_length = 0; 103 utf16_to_utf8(characters, length, utf8, new_length); 104 if (!utf8) 105 return NULL; 106 107 if (from > 0) { 108 // discard the first 'from' characters 109 // FIXME: we should do this before the conversion probably 110 gchar* str_left = g_utf8_offset_to_pointer(utf8, from); 111 gchar* tmp = g_strdup(str_left); 112 g_free(utf8); 113 utf8 = tmp; 114 } 115 116 gchar* pos = utf8; 117 gint len = strlen(pos); 118 GString* ret = g_string_new_len(NULL, len); 119 120 // replace line break by space 121 while (len > 0) { 122 gint index, start; 123 pango_find_paragraph_boundary(pos, len, &index, &start); 124 g_string_append_len(ret, pos, index); 125 if (index == start) 126 break; 127 g_string_append_c(ret, ' '); 128 pos += start; 129 len -= start; 130 } 131 return g_string_free(ret, FALSE); 132 } 133 134 static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout* layout) 135 { 136 PangoAttrList* list = pango_attr_list_new(); 137 PangoAttribute* attr; 138 139 attr = pango_attr_size_new_absolute((int)(font->size() * PANGO_SCALE)); 140 attr->end_index = G_MAXUINT; 141 pango_attr_list_insert_before(list, attr); 142 143 if (!run.spacingDisabled()) { 144 attr = pango_attr_letter_spacing_new(font->letterSpacing() * PANGO_SCALE); 145 attr->end_index = G_MAXUINT; 146 pango_attr_list_insert_before(list, attr); 147 } 148 149 // Pango does not yet support synthesising small caps 150 // See http://bugs.webkit.org/show_bug.cgi?id=15610 151 152 pango_layout_set_attributes(layout, list); 153 pango_attr_list_unref(list); 154 155 pango_layout_set_auto_dir(layout, FALSE); 156 157 PangoContext* pangoContext = pango_layout_get_context(layout); 158 PangoDirection direction = run.rtl() ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; 159 pango_context_set_base_dir(pangoContext, direction); 160 } 37 161 38 162 void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, 39 163 int from, int numGlyphs, const FloatPoint& point) const 40 164 { 41 cairo_t* context = graphicsContext->platformContext(); 165 cairo_t* cr = graphicsContext->platformContext(); 166 cairo_save(cr); 42 167 43 168 // Set the text color to use for drawing. … … 45 170 Color penColor = graphicsContext->fillColor(); 46 171 penColor.getRGBA(red, green, blue, alpha); 47 cairo_set_source_rgba(context, red, green, blue, alpha); 48 49 // This was commented out as it made "some text invisible" but seems to work now. 50 font->setFont(context); 51 52 GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*) glyphBuffer.glyphs(from); 172 cairo_set_source_rgba(cr, red, green, blue, alpha); 173 174 font->setFont(cr); 175 176 GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from); 53 177 54 178 float offset = point.x(); … … 59 183 offset += glyphBuffer.advanceAt(from + i); 60 184 } 61 cairo_show_glyphs(context, glyphs, numGlyphs); 62 } 63 64 void Font::drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const 65 { 66 notImplemented(); 67 } 68 69 float Font::floatWidthForComplexText(const TextRun&) const 70 { 71 notImplemented(); 72 return 0.0f; 73 } 74 75 int Font::offsetForPositionForComplexText(const TextRun&, int, bool) const 76 { 77 notImplemented(); 78 return 0; 79 } 80 81 FloatRect Font::selectionRectForComplexText(const TextRun&, const IntPoint&, int, int, int) const 185 cairo_show_glyphs(cr, glyphs, numGlyphs); 186 187 cairo_restore(cr); 188 } 189 190 void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const 191 { 192 cairo_t* cr = context->platformContext(); 193 cairo_save(cr); 194 195 PangoLayout* layout = pango_cairo_create_layout(cr); 196 197 gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), from, to); 198 pango_layout_set_text(layout, utf8, -1); 199 g_free(utf8); 200 201 setPangoAttributes(this, run, layout); 202 203 // Set the text color to use for drawing. 204 float red, green, blue, alpha; 205 Color penColor = context->fillColor(); 206 penColor.getRGBA(red, green, blue, alpha); 207 cairo_set_source_rgba(cr, red, green, blue, alpha); 208 209 // Our layouts are single line 210 cairo_move_to(cr, point.x(), point.y()); 211 PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0); 212 pango_cairo_show_layout_line(cr, layoutLine); 213 214 g_object_unref(layout); 215 cairo_restore(cr); 216 } 217 218 // FIXME: we should create the layout with our actual context, but it seems 219 // we can't access it from here 220 static PangoLayout* getDefaultPangoLayout(const TextRun& run) 221 { 222 PangoFontMap* map = pango_cairo_font_map_get_default(); 223 PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(map)); 224 PangoLayout* layout = pango_layout_new(pangoContext); 225 g_object_unref(pangoContext); 226 227 return layout; 228 } 229 230 float Font::floatWidthForComplexText(const TextRun& run) const 231 { 232 if (run.length() == 0) 233 return 0.0f; 234 235 PangoLayout* layout = getDefaultPangoLayout(run); 236 setPangoAttributes(this, run, layout); 237 238 gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); 239 pango_layout_set_text(layout, utf8, -1); 240 g_free(utf8); 241 242 int layoutWidth; 243 pango_layout_get_size(layout, &layoutWidth, 0); 244 float width = (float)layoutWidth / (double)PANGO_SCALE; 245 g_object_unref(layout); 246 247 return width; 248 } 249 250 int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const 251 { 252 PangoLayout* layout = getDefaultPangoLayout(run); 253 setPangoAttributes(this, run, layout); 254 255 gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); 256 pango_layout_set_text(layout, utf8, -1); 257 258 int index, trailing; 259 pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing); 260 glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index); 261 g_free(utf8); 262 g_object_unref(layout); 263 264 return offset; 265 } 266 267 FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const 82 268 { 83 269 notImplemented();
Note: See TracChangeset
for help on using the changeset viewer.