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/canvas_skia.h" | 5 #include "ui/gfx/canvas_skia.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include <cairo/cairo.h> | 9 #include <cairo/cairo.h> |
10 #include <pango/pango.h> | 10 #include <pango/pango.h> |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 void DrawUnderline(cairo_t* cr, double extra_edge_width); | 57 void DrawUnderline(cairo_t* cr, double extra_edge_width); |
58 | 58 |
59 const gfx::Rect& bounds_; | 59 const gfx::Rect& bounds_; |
60 int flags_; | 60 int flags_; |
61 const gfx::Font& font_; | 61 const gfx::Font& font_; |
62 | 62 |
63 gfx::CanvasSkia* canvas_; | 63 gfx::CanvasSkia* canvas_; |
64 cairo_t* cr_; | 64 cairo_t* cr_; |
65 PangoLayout* layout_; | 65 PangoLayout* layout_; |
66 | 66 |
67 int text_x_; | 67 gfx::Rect text_rect_; |
68 int text_y_; | |
69 int text_width_; | |
70 int text_height_; | |
71 | 68 |
72 base::i18n::TextDirection text_direction_; | 69 base::i18n::TextDirection text_direction_; |
73 | 70 |
74 DISALLOW_COPY_AND_ASSIGN(DrawStringContext); | 71 DISALLOW_COPY_AND_ASSIGN(DrawStringContext); |
75 }; | 72 }; |
76 | 73 |
77 DrawStringContext::DrawStringContext(gfx::CanvasSkia* canvas, | 74 DrawStringContext::DrawStringContext(gfx::CanvasSkia* canvas, |
78 const string16& text, | 75 const string16& text, |
79 const gfx::Font& font, | 76 const gfx::Font& font, |
80 const gfx::Rect& bounds, | 77 const gfx::Rect& bounds, |
81 const gfx::Rect& clip, | 78 const gfx::Rect& clip, |
82 int flags) | 79 int flags) |
83 : bounds_(bounds), | 80 : bounds_(bounds), |
84 flags_(flags), | 81 flags_(flags), |
85 font_(font), | 82 font_(font), |
86 canvas_(canvas), | 83 canvas_(canvas), |
87 cr_(NULL), | 84 cr_(NULL), |
88 layout_(NULL), | 85 layout_(NULL), |
89 text_x_(bounds.x()), | 86 text_rect_(bounds.x(), bounds.y(), 0, 0), |
90 text_y_(bounds.y()), | |
91 text_width_(0), | |
92 text_height_(0), | |
93 text_direction_(base::i18n::GetFirstStrongCharacterDirection(text)) { | 87 text_direction_(base::i18n::GetFirstStrongCharacterDirection(text)) { |
94 DCHECK(!bounds_.IsEmpty()); | 88 DCHECK(!bounds_.IsEmpty()); |
95 | 89 |
96 cr_ = skia::BeginPlatformPaint(canvas_->sk_canvas()); | 90 cr_ = skia::BeginPlatformPaint(canvas_->sk_canvas()); |
97 layout_ = pango_cairo_create_layout(cr_); | 91 layout_ = pango_cairo_create_layout(cr_); |
98 | 92 |
99 gfx::SetupPangoLayout( | 93 gfx::SetupPangoLayout( |
100 layout_, text, font, bounds_.width(), text_direction_, flags_); | 94 layout_, text, font, bounds_.width(), text_direction_, flags_); |
101 | 95 |
102 pango_layout_set_height(layout_, bounds_.height() * PANGO_SCALE); | 96 pango_layout_set_height(layout_, bounds_.height() * PANGO_SCALE); |
103 | 97 |
104 cairo_save(cr_); | 98 cairo_save(cr_); |
105 | 99 |
106 cairo_rectangle(cr_, clip.x(), clip.y(), clip.width(), clip.height()); | 100 cairo_rectangle(cr_, clip.x(), clip.y(), clip.width(), clip.height()); |
107 cairo_clip(cr_); | 101 cairo_clip(cr_); |
108 | 102 |
109 pango_layout_get_pixel_size(layout_, &text_width_, &text_height_); | 103 AdjustTextRectBasedOnLayout(layout_, bounds_, flags_, &text_rect_); |
110 | |
111 if (flags_ & gfx::Canvas::TEXT_VALIGN_TOP) { | |
112 // Cairo should draw from the top left corner already. | |
113 } else if (flags_ & gfx::Canvas::TEXT_VALIGN_BOTTOM) { | |
114 text_y_ += (bounds.height() - text_height_); | |
115 } else { | |
116 // Vertically centered. | |
117 text_y_ += ((bounds.height() - text_height_) / 2); | |
118 } | |
119 } | 104 } |
120 | 105 |
121 DrawStringContext::~DrawStringContext() { | 106 DrawStringContext::~DrawStringContext() { |
122 cairo_restore(cr_); | 107 cairo_restore(cr_); |
123 skia::EndPlatformPaint(canvas_->sk_canvas()); | 108 skia::EndPlatformPaint(canvas_->sk_canvas()); |
124 g_object_unref(layout_); | 109 g_object_unref(layout_); |
125 // NOTE: BeginPlatformPaint returned its surface, we shouldn't destroy it. | 110 // NOTE: BeginPlatformPaint returned its surface, we shouldn't destroy it. |
126 } | 111 } |
127 | 112 |
128 void DrawStringContext::Draw(const SkColor& text_color) { | 113 void DrawStringContext::Draw(const SkColor& text_color) { |
129 double r = SkColorGetR(text_color) / 255.0, | 114 DrawPangoLayout(cr_, layout_, font_, bounds_, text_rect_, text_color, |
130 g = SkColorGetG(text_color) / 255.0, | 115 text_direction_, flags_); |
131 b = SkColorGetB(text_color) / 255.0, | |
132 a = SkColorGetA(text_color) / 255.0; | |
133 | |
134 cairo_pattern_t* pattern = NULL; | |
135 | |
136 cairo_save(cr_); | |
137 | |
138 // If we're not eliding, use a fixed color. | |
139 // Otherwise, create a gradient pattern to use as the source. | |
140 if (text_direction_ == base::i18n::RIGHT_TO_LEFT || | |
141 (flags_ & gfx::Canvas::NO_ELLIPSIS) || | |
142 text_width_ <= bounds_.width()) { | |
143 cairo_set_source_rgba(cr_, r, g, b, a); | |
144 } else { | |
145 // Fade to semi-transparent to elide. | |
146 int fade_width = static_cast<double>(text_height_) * kFadeWidthFactor; | |
147 if (fade_width > (bounds_.width() / 2)) { | |
148 // Don't fade more than half the text. | |
149 fade_width = bounds_.width() / 2; | |
150 } | |
151 int fade_x = bounds_.x() + bounds_.width() - fade_width; | |
152 | |
153 pattern = cairo_pattern_create_linear( | |
154 fade_x, bounds_.y(), bounds_.x() + bounds_.width(), bounds_.y()); | |
155 cairo_pattern_add_color_stop_rgba(pattern, 0, r, g, b, a); | |
156 cairo_pattern_add_color_stop_rgba(pattern, 1, r, g, b, kFadeFinalAlpha); | |
157 cairo_set_source(cr_, pattern); | |
158 } | |
159 | |
160 cairo_move_to(cr_, text_x_, text_y_); | |
161 pango_cairo_show_layout(cr_, layout_); | |
162 | |
163 if (font_.GetStyle() & gfx::Font::UNDERLINED) | |
164 DrawUnderline(cr_, 0.0); | |
165 | |
166 if (pattern) | |
167 cairo_pattern_destroy(pattern); | |
168 | |
169 cairo_restore(cr_); | |
170 } | 116 } |
171 | 117 |
172 void DrawStringContext::DrawWithHalo(const SkColor& text_color, | 118 void DrawStringContext::DrawWithHalo(const SkColor& text_color, |
173 const SkColor& halo_color) { | 119 const SkColor& halo_color) { |
174 gfx::CanvasSkia text_canvas(bounds_.width() + 2, bounds_.height() + 2, false); | 120 gfx::CanvasSkia text_canvas(bounds_.width() + 2, bounds_.height() + 2, false); |
175 text_canvas.FillRectInt(static_cast<SkColor>(0), | 121 text_canvas.FillRectInt(static_cast<SkColor>(0), |
176 0, 0, bounds_.width() + 2, bounds_.height() + 2); | 122 0, 0, bounds_.width() + 2, bounds_.height() + 2); |
177 | 123 |
178 { | 124 { |
179 skia::ScopedPlatformPaint scoped_platform_paint(text_canvas.sk_canvas()); | 125 skia::ScopedPlatformPaint scoped_platform_paint(text_canvas.sk_canvas()); |
(...skipping 30 matching lines...) Expand all Loading... |
210 SkColorGetB(text_color) / 255.0, | 156 SkColorGetB(text_color) / 255.0, |
211 SkColorGetA(text_color) / 255.0); | 157 SkColorGetA(text_color) / 255.0); |
212 cairo_fill(text_cr); | 158 cairo_fill(text_cr); |
213 | 159 |
214 if (font_.GetStyle() & gfx::Font::UNDERLINED) | 160 if (font_.GetStyle() & gfx::Font::UNDERLINED) |
215 DrawUnderline(text_cr, 0.0); | 161 DrawUnderline(text_cr, 0.0); |
216 } | 162 } |
217 | 163 |
218 const SkBitmap& text_bitmap = const_cast<SkBitmap&>( | 164 const SkBitmap& text_bitmap = const_cast<SkBitmap&>( |
219 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(false)); | 165 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(false)); |
220 canvas_->DrawBitmapInt(text_bitmap, text_x_ - 1, text_y_ - 1); | 166 canvas_->DrawBitmapInt(text_bitmap, text_rect_.x() - 1, text_rect_.y() - 1); |
221 } | 167 } |
222 | 168 |
223 void DrawStringContext::DrawUnderline(cairo_t* cr, double extra_edge_width) { | 169 void DrawStringContext::DrawUnderline(cairo_t* cr, double extra_edge_width) { |
224 gfx::PlatformFontPango* platform_font = | 170 gfx::PlatformFontPango* platform_font = |
225 static_cast<gfx::PlatformFontPango*>(font_.platform_font()); | 171 static_cast<gfx::PlatformFontPango*>(font_.platform_font()); |
226 const double underline_y = | 172 gfx::DrawPangoTextUnderline(cr, |
227 static_cast<double>(text_y_) + text_height_ + | 173 platform_font, |
228 platform_font->underline_position(); | 174 extra_edge_width, |
229 cairo_set_line_width( | 175 text_rect_); |
230 cr, platform_font->underline_thickness() + 2 * extra_edge_width); | |
231 cairo_move_to(cr, text_x_ - extra_edge_width, underline_y); | |
232 cairo_line_to(cr, text_x_ + text_width_ + extra_edge_width, underline_y); | |
233 cairo_stroke(cr); | |
234 } | 176 } |
235 | 177 |
236 } // namespace | 178 } // namespace |
237 | 179 |
238 namespace gfx { | 180 namespace gfx { |
239 | 181 |
240 // static | 182 // static |
241 void CanvasSkia::SizeStringInt(const string16& text, | 183 void CanvasSkia::SizeStringInt(const string16& text, |
242 const gfx::Font& font, | 184 const gfx::Font& font, |
243 int* width, int* height, | 185 int* width, int* height, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 cairo_paint(cr); | 276 cairo_paint(cr); |
335 } | 277 } |
336 #endif // defined(TOOLKIT_USES_GTK) | 278 #endif // defined(TOOLKIT_USES_GTK) |
337 | 279 |
338 ui::TextureID CanvasSkia::GetTextureID() { | 280 ui::TextureID CanvasSkia::GetTextureID() { |
339 // TODO(wjmaclean) | 281 // TODO(wjmaclean) |
340 return 0; | 282 return 0; |
341 } | 283 } |
342 | 284 |
343 } // namespace gfx | 285 } // namespace gfx |
OLD | NEW |