Chromium Code Reviews| 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 |