OLD | NEW |
---|---|
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/pango_util.h" | 5 #include "ui/gfx/pango_util.h" |
6 | 6 |
7 #include <cairo/cairo.h> | 7 #include <cairo/cairo.h> |
8 #include <pango/pango.h> | 8 #include <pango/pango.h> |
9 #include <pango/pangocairo.h> | 9 #include <pango/pangocairo.h> |
10 | 10 |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "ui/gfx/canvas.h" | 13 #include "ui/gfx/canvas.h" |
14 #include "ui/gfx/font.h" | 14 #include "ui/gfx/font.h" |
15 #include "ui/gfx/platform_font_pango.h" | |
16 #include "ui/gfx/rect.h" | |
15 | 17 |
16 #if !defined(USE_WAYLAND) && defined(TOOLKIT_USES_GTK) | 18 #if !defined(USE_WAYLAND) && defined(TOOLKIT_USES_GTK) |
17 #include <gtk/gtk.h> | 19 #include <gtk/gtk.h> |
18 #include "ui/gfx/gtk_util.h" | 20 #include "ui/gfx/gtk_util.h" |
19 #else | 21 #else |
20 #include "ui/gfx/linux_util.h" | 22 #include "ui/gfx/linux_util.h" |
21 #endif | 23 #endif |
22 | 24 |
23 #include "ui/gfx/skia_util.h" | 25 #include "ui/gfx/skia_util.h" |
24 | 26 |
25 namespace { | 27 namespace { |
26 | 28 |
27 // Marker for accelerators in the text. | 29 // Marker for accelerators in the text. |
28 const gunichar kAcceleratorChar = '&'; | 30 const gunichar kAcceleratorChar = '&'; |
29 | 31 |
32 // Multiply by the text height to determine how much text should be faded | |
33 // when elliding. | |
34 const double kFadeWidthFactor = 1.5; | |
35 | |
36 // End state of the elliding fade. | |
37 const double kFadeFinalAlpha = 0.15; | |
38 | |
30 // Return |cairo_font_options|. If needed, allocate and update it based on | 39 // Return |cairo_font_options|. If needed, allocate and update it based on |
31 // GtkSettings. | 40 // GtkSettings. |
32 cairo_font_options_t* GetCairoFontOptions() { | 41 cairo_font_options_t* GetCairoFontOptions() { |
33 // Font settings that we initialize once and then use when drawing text. | 42 // Font settings that we initialize once and then use when drawing text. |
34 static cairo_font_options_t* cairo_font_options = NULL; | 43 static cairo_font_options_t* cairo_font_options = NULL; |
35 | 44 |
36 if (cairo_font_options) | 45 if (cairo_font_options) |
37 return cairo_font_options; | 46 return cairo_font_options; |
38 | 47 |
39 cairo_font_options = cairo_font_options_create(); | 48 cairo_font_options = cairo_font_options_create(); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
186 NULL, NULL); | 195 NULL, NULL); |
187 utf8 = UTF16ToUTF8(accelerator_removed); | 196 utf8 = UTF16ToUTF8(accelerator_removed); |
188 } else { | 197 } else { |
189 utf8 = UTF16ToUTF8(text); | 198 utf8 = UTF16ToUTF8(text); |
190 } | 199 } |
191 | 200 |
192 pango_layout_set_text(layout, utf8.data(), utf8.size()); | 201 pango_layout_set_text(layout, utf8.data(), utf8.size()); |
193 } | 202 } |
194 } | 203 } |
195 | 204 |
205 | |
206 PangoDrawString::PangoDrawString(cairo_t* cr, | |
207 const string16& text, | |
208 const gfx::Font& font, | |
209 const gfx::Rect& bounds, | |
210 const gfx::Rect& clip, | |
211 int flags) | |
212 : bounds_(bounds), | |
213 flags_(flags), | |
214 font_(font), | |
215 cr_(cr), | |
216 layout_(pango_cairo_create_layout(cr_)), | |
217 text_x_(bounds.x()), | |
218 text_y_(bounds.y()), | |
219 text_width_(0), | |
220 text_height_(0), | |
221 text_direction_(base::i18n::GetFirstStrongCharacterDirection(text)) { | |
222 DCHECK(!bounds_.IsEmpty()); | |
223 | |
224 gfx::SetupPangoLayout( | |
225 layout_, text, font, bounds_.width(), text_direction_, flags_); | |
226 | |
227 pango_layout_set_height(layout_, bounds_.height() * PANGO_SCALE); | |
228 | |
229 cairo_save(cr_); | |
230 | |
231 cairo_rectangle(cr_, clip.x(), clip.y(), clip.width(), clip.height()); | |
232 cairo_clip(cr_); | |
233 | |
234 pango_layout_get_pixel_size(layout_, &text_width_, &text_height_); | |
235 | |
236 if (flags_ & gfx::Canvas::TEXT_VALIGN_TOP) { | |
237 // Cairo should draw from the top left corner already. | |
238 } else if (flags_ & gfx::Canvas::TEXT_VALIGN_BOTTOM) { | |
239 text_y_ += (bounds.height() - text_height_); | |
240 } else { | |
241 // Vertically centered. | |
242 text_y_ += ((bounds.height() - text_height_) / 2); | |
243 } | |
244 } | |
245 | |
246 PangoDrawString::~PangoDrawString() { | |
247 cairo_restore(cr_); | |
248 g_object_unref(layout_); | |
249 } | |
250 | |
251 void PangoDrawString::Draw(const SkColor& text_color) { | |
252 double r = SkColorGetR(text_color) / 255.0, | |
253 g = SkColorGetG(text_color) / 255.0, | |
254 b = SkColorGetB(text_color) / 255.0, | |
255 a = SkColorGetA(text_color) / 255.0; | |
256 | |
257 cairo_pattern_t* pattern = NULL; | |
258 | |
259 cairo_save(cr_); | |
260 | |
261 // If we're not eliding, use a fixed color. | |
262 // Otherwise, create a gradient pattern to use as the source. | |
263 if (text_direction_ == base::i18n::RIGHT_TO_LEFT || | |
264 (flags_ & gfx::Canvas::NO_ELLIPSIS) || | |
265 text_width_ <= bounds_.width()) { | |
266 cairo_set_source_rgba(cr_, r, g, b, a); | |
267 } else { | |
268 // Fade to semi-transparent to elide. | |
269 int fade_width = static_cast<double>(text_height_) * kFadeWidthFactor; | |
270 if (fade_width > (bounds_.width() / 2)) { | |
Evan Stade
2011/10/25 23:33:30
remove excess parens
Elliot Glaysher
2011/10/26 21:06:57
I believe we should make order of operations expli
Evan Stade
2011/10/26 21:46:05
the C++ style guide doesn't touch on this, but the
| |
271 // Don't fade more than half the text. | |
272 fade_width = bounds_.width() / 2; | |
273 } | |
274 int fade_x = bounds_.x() + bounds_.width() - fade_width; | |
275 | |
276 pattern = cairo_pattern_create_linear( | |
277 fade_x, bounds_.y(), bounds_.x() + bounds_.width(), bounds_.y()); | |
278 cairo_pattern_add_color_stop_rgba(pattern, 0, r, g, b, a); | |
279 cairo_pattern_add_color_stop_rgba(pattern, 1, r, g, b, kFadeFinalAlpha); | |
280 cairo_set_source(cr_, pattern); | |
281 } | |
282 | |
283 cairo_move_to(cr_, text_x_, text_y_); | |
284 pango_cairo_show_layout(cr_, layout_); | |
285 | |
286 if (font_.GetStyle() & gfx::Font::UNDERLINED) | |
287 DrawUnderline(cr_, 0.0); | |
288 | |
289 if (pattern) | |
290 cairo_pattern_destroy(pattern); | |
291 | |
292 cairo_restore(cr_); | |
293 } | |
294 | |
295 void PangoDrawString::DrawUnderline(cairo_t* cr, double extra_edge_width) { | |
296 gfx::PlatformFontPango* platform_font = | |
297 static_cast<gfx::PlatformFontPango*>(font_.platform_font()); | |
298 const double underline_y = | |
299 static_cast<double>(text_y_) + text_height_ + | |
300 platform_font->underline_position(); | |
301 cairo_set_line_width( | |
302 cr, platform_font->underline_thickness() + 2 * extra_edge_width); | |
303 cairo_move_to(cr, text_x_ - extra_edge_width, underline_y); | |
304 cairo_line_to(cr, text_x_ + text_width_ + extra_edge_width, underline_y); | |
305 cairo_stroke(cr); | |
306 } | |
307 | |
196 } // namespace gfx | 308 } // namespace gfx |
OLD | NEW |