Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: ui/gfx/gtk_util.cc

Issue 7511029: Implement Pango RenderText for Linux. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: fix compilation error. using ICU functions for utf8/utf16 conversion Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/gtk_util.h" 5 #include "ui/gfx/gtk_util.h"
6 6
7 #include <cairo/cairo.h>
7 #include <gdk/gdk.h> 8 #include <gdk/gdk.h>
8 #include <gtk/gtk.h> 9 #include <gtk/gtk.h>
10 #include <pango/pango.h>
11 #include <pango/pangocairo.h>
9 #include <stdlib.h> 12 #include <stdlib.h>
10 13
11 #include "base/basictypes.h" 14 #include "base/basictypes.h"
12 #include "base/command_line.h" 15 #include "base/command_line.h"
13 #include "base/linux_util.h" 16 #include "base/linux_util.h"
17 #include "base/logging.h"
18 #include "base/utf_string_conversions.h"
14 #include "third_party/skia/include/core/SkBitmap.h" 19 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "third_party/skia/include/core/SkUnPreMultiply.h" 20 #include "third_party/skia/include/core/SkUnPreMultiply.h"
21 #include "ui/gfx/canvas.h"
22 #include "ui/gfx/skia_util.h"
23 #include "ui/gfx/font.h"
16 #include "ui/gfx/rect.h" 24 #include "ui/gfx/rect.h"
17 25
18 namespace { 26 namespace {
19 27
20 // A process wide singleton that manages our usage of gdk 28 // A process wide singleton that manages our usage of gdk
21 // cursors. gdk_cursor_new() hits the disk in several places and GdkCursor 29 // cursors. gdk_cursor_new() hits the disk in several places and GdkCursor
22 // instances can be reused throughout the process. 30 // instances can be reused throughout the process.
23 class GdkCursorCache { 31 class GdkCursorCache {
24 public: 32 public:
25 GdkCursorCache() {} 33 GdkCursorCache() {}
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 ret.append(target); 84 ret.append(target);
77 } 85 }
78 } else { 86 } else {
79 ret.push_back(label[i]); 87 ret.push_back(label[i]);
80 } 88 }
81 } 89 }
82 90
83 return ret; 91 return ret;
84 } 92 }
85 93
94 const gunichar kAcceleratorChar = '&';
msw 2011/08/23 08:01:01 I think constants are usually defined above all fu
xji 2011/08/23 23:52:52 done comment. moved those to pango_util
95
96 // Font settings that we initialize once and then use when drawing text in
97 // DrawStringInt().
98 cairo_font_options_t* cairo_font_options = NULL;
msw 2011/08/23 08:01:01 Can you make this a function static in UpdateCairo
xji 2011/08/23 23:52:52 this is defined in unnamed scope, so should be the
99
100 // Update |cairo_font_options| based on GtkSettings, allocating it if needed.
101 void UpdateCairoFontOptions() {
102 if (!cairo_font_options)
103 cairo_font_options = cairo_font_options_create();
104
105 gint antialias = 0;
106 gint hinting = 0;
107 gchar* hint_style = NULL;
108 gchar* rgba_style = NULL;
109
110 #if !defined(USE_WAYLAND)
111 GtkSettings* gtk_settings = gtk_settings_get_default();
xji 2011/08/23 23:52:52 hm.. this has gtk dependency. Oshima, could you ch
112 g_object_get(gtk_settings,
113 "gtk-xft-antialias", &antialias,
114 "gtk-xft-hinting", &hinting,
115 "gtk-xft-hintstyle", &hint_style,
116 "gtk-xft-rgba", &rgba_style,
117 NULL);
118 #endif
119
120 // g_object_get() doesn't tell us whether the properties were present or not,
121 // but if they aren't (because gnome-settings-daemon isn't running), we'll get
122 // NULL values for the strings.
123 if (hint_style && rgba_style) {
124 if (!antialias) {
125 cairo_font_options_set_antialias(cairo_font_options,
126 CAIRO_ANTIALIAS_NONE);
127 } else if (strcmp(rgba_style, "none") == 0) {
128 cairo_font_options_set_antialias(cairo_font_options,
129 CAIRO_ANTIALIAS_GRAY);
130 } else {
131 cairo_font_options_set_antialias(cairo_font_options,
132 CAIRO_ANTIALIAS_SUBPIXEL);
133 cairo_subpixel_order_t cairo_subpixel_order =
134 CAIRO_SUBPIXEL_ORDER_DEFAULT;
135 if (strcmp(rgba_style, "rgb") == 0) {
136 cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
137 } else if (strcmp(rgba_style, "bgr") == 0) {
138 cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
139 } else if (strcmp(rgba_style, "vrgb") == 0) {
140 cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
141 } else if (strcmp(rgba_style, "vbgr") == 0) {
142 cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
143 }
144 cairo_font_options_set_subpixel_order(cairo_font_options,
145 cairo_subpixel_order);
146 }
147
148 cairo_hint_style_t cairo_hint_style = CAIRO_HINT_STYLE_DEFAULT;
149 if (hinting == 0 || strcmp(hint_style, "hintnone") == 0) {
150 cairo_hint_style = CAIRO_HINT_STYLE_NONE;
151 } else if (strcmp(hint_style, "hintslight") == 0) {
152 cairo_hint_style = CAIRO_HINT_STYLE_SLIGHT;
153 } else if (strcmp(hint_style, "hintmedium") == 0) {
154 cairo_hint_style = CAIRO_HINT_STYLE_MEDIUM;
155 } else if (strcmp(hint_style, "hintfull") == 0) {
156 cairo_hint_style = CAIRO_HINT_STYLE_FULL;
157 }
158 cairo_font_options_set_hint_style(cairo_font_options, cairo_hint_style);
159 }
160
161 if (hint_style)
162 g_free(hint_style);
163 if (rgba_style)
164 g_free(rgba_style);
165 }
86 } // namespace 166 } // namespace
msw 2011/08/23 08:01:01 Add a blank line here.
xji 2011/08/23 23:52:52 Done.
87 167
88 namespace gfx { 168 namespace gfx {
89 169
90 void GtkInitFromCommandLine(const CommandLine& command_line) { 170 void GtkInitFromCommandLine(const CommandLine& command_line) {
91 const std::vector<std::string>& args = command_line.argv(); 171 const std::vector<std::string>& args = command_line.argv();
92 int argc = args.size(); 172 int argc = args.size();
93 scoped_array<char *> argv(new char *[argc + 1]); 173 scoped_array<char *> argv(new char *[argc + 1]);
94 for (size_t i = 0; i < args.size(); ++i) { 174 for (size_t i = 0; i < args.size(); ++i) {
95 // TODO(piman@google.com): can gtk_init modify argv? Just being safe 175 // TODO(piman@google.com): can gtk_init modify argv? Just being safe
96 // here. 176 // here.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 const std::vector<Rect>& cutouts) { 237 const std::vector<Rect>& cutouts) {
158 for (size_t i = 0; i < cutouts.size(); ++i) { 238 for (size_t i = 0; i < cutouts.size(); ++i) {
159 GdkRectangle rect = cutouts[i].ToGdkRectangle(); 239 GdkRectangle rect = cutouts[i].ToGdkRectangle();
160 GdkRegion* rect_region = gdk_region_rectangle(&rect); 240 GdkRegion* rect_region = gdk_region_rectangle(&rect);
161 gdk_region_subtract(region, rect_region); 241 gdk_region_subtract(region, rect_region);
162 // TODO(deanm): It would be nice to be able to reuse the GdkRegion here. 242 // TODO(deanm): It would be nice to be able to reuse the GdkRegion here.
163 gdk_region_destroy(rect_region); 243 gdk_region_destroy(rect_region);
164 } 244 }
165 } 245 }
166 246
247 // Pass a width > 0 to force wrapping and elliding.
msw 2011/08/23 08:01:01 remove the extra L from "eliding"; use the phrase
xji 2011/08/23 23:52:52 Done.
248 void SetupPangoLayout(PangoLayout* layout,
249 const string16& text,
250 const Font& font,
251 int width,
252 base::i18n::TextDirection text_direction,
253 int flags) {
254 if (!cairo_font_options)
255 UpdateCairoFontOptions();
256 // This needs to be done early on; it has no effect when called just before
257 // pango_cairo_show_layout().
258 pango_cairo_context_set_font_options(
259 pango_layout_get_context(layout), cairo_font_options);
260
261 // Callers of DrawStringInt handle RTL layout themselves, so tell pango to not
262 // scope out RTL characters.
263 pango_layout_set_auto_dir(layout, FALSE);
264
265 if (width > 0)
266 pango_layout_set_width(layout, width * PANGO_SCALE);
267
268 if (flags & Canvas::TEXT_ALIGN_CENTER) {
269 // We don't support center aligned w/ eliding.
270 DCHECK(gfx::Canvas::NO_ELLIPSIS);
271 pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
272 } else if (flags & Canvas::TEXT_ALIGN_RIGHT) {
273 pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
274 }
275
276 if (flags & Canvas::NO_ELLIPSIS) {
277 pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
278 if (flags & Canvas::MULTI_LINE) {
279 pango_layout_set_wrap(layout,
280 (flags & Canvas::CHARACTER_BREAK) ?
281 PANGO_WRAP_WORD_CHAR : PANGO_WRAP_WORD);
282 }
283 } else if (text_direction == base::i18n::RIGHT_TO_LEFT) {
284 pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
285 } else {
286 // Fading the text will be handled in the draw operation.
287 // Ensure that the text is only on one line.
288 pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
289 pango_layout_set_width(layout, -1);
290 }
291
292 // Set the resolution to match that used by Gtk. If we don't set the
293 // resolution and the resolution differs from the default, Gtk and Chrome end
294 // up drawing at different sizes.
295 double resolution = GetPangoResolution();
296 if (resolution > 0) {
297 pango_cairo_context_set_resolution(pango_layout_get_context(layout),
298 resolution);
299 }
300
301 PangoFontDescription* desc = font.GetNativeFont();
302 pango_layout_set_font_description(layout, desc);
303 pango_font_description_free(desc);
304
305 // Set text and accelerator character if needed.
306 std::string utf8 = UTF16ToUTF8(text);
307 if (flags & Canvas::SHOW_PREFIX) {
308 // Escape the text string to be used as markup.
309 gchar* escaped_text = g_markup_escape_text(utf8.c_str(), utf8.size());
310 pango_layout_set_markup_with_accel(layout,
311 escaped_text,
312 strlen(escaped_text),
313 kAcceleratorChar, NULL);
314 g_free(escaped_text);
315 } else if (flags & Canvas::HIDE_PREFIX) {
316 // Remove the ampersand character. A double ampersand is output as
317 // a single ampersand.
318 DCHECK_EQ(1, g_unichar_to_utf8(kAcceleratorChar, NULL));
319 const std::string accelerator_removed =
320 RemoveAcceleratorChar(utf8, static_cast<char>(kAcceleratorChar));
321
322 pango_layout_set_text(layout,
323 accelerator_removed.data(), accelerator_removed.size());
324 } else {
325 pango_layout_set_text(layout, utf8.data(), utf8.size());
326 }
327 }
328
167 PangoContext* GetPangoContext() { 329 PangoContext* GetPangoContext() {
168 #if defined(USE_WAYLAND) 330 #if defined(USE_WAYLAND)
169 PangoFontMap* font_map = pango_cairo_font_map_get_default(); 331 PangoFontMap* font_map = pango_cairo_font_map_get_default();
170 PangoContext* default_context = pango_font_map_create_context(font_map); 332 PangoContext* default_context = pango_font_map_create_context(font_map);
171 #else 333 #else
172 PangoContext* default_context = gdk_pango_context_get(); 334 PangoContext* default_context = gdk_pango_context_get();
173 #endif 335 #endif
174 return default_context; 336 return default_context;
175 } 337 }
176 338
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 new_pixels[idx + 1] = pixels[idx + 1]; 375 new_pixels[idx + 1] = pixels[idx + 1];
214 new_pixels[idx + 2] = pixels[idx]; 376 new_pixels[idx + 2] = pixels[idx];
215 new_pixels[idx + 3] = pixels[idx + 3]; 377 new_pixels[idx + 3] = pixels[idx + 3];
216 } 378 }
217 } 379 }
218 380
219 return new_pixels; 381 return new_pixels;
220 } 382 }
221 383
222 } // namespace gfx 384 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698