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

Side by Side Diff: gfx/canvas_skia_linux.cc

Issue 5071002: Add 1px black border for ChromeOS status button. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: change how common code is shared Created 10 years, 1 month 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
« no previous file with comments | « gfx/canvas_skia.h ('k') | views/controls/button/text_button.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 "gfx/canvas_skia.h" 5 #include "gfx/canvas_skia.h"
6 6
7 #include <cairo/cairo.h> 7 #include <cairo/cairo.h>
8 #include <gtk/gtk.h> 8 #include <gtk/gtk.h>
9 #include <pango/pango.h> 9 #include <pango/pango.h>
10 #include <pango/pangocairo.h> 10 #include <pango/pangocairo.h>
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 } 81 }
82 cairo_font_options_set_hint_style(cairo_font_options, cairo_hint_style); 82 cairo_font_options_set_hint_style(cairo_font_options, cairo_hint_style);
83 } 83 }
84 84
85 if (hint_style) 85 if (hint_style)
86 g_free(hint_style); 86 g_free(hint_style);
87 if (rgba_style) 87 if (rgba_style)
88 g_free(rgba_style); 88 g_free(rgba_style);
89 } 89 }
90 90
91 } // namespace
92
93 namespace gfx {
94
95 CanvasSkia::CanvasSkia(int width, int height, bool is_opaque)
96 : skia::PlatformCanvas(width, height, is_opaque) {
97 }
98
99 CanvasSkia::CanvasSkia() : skia::PlatformCanvas() {
100 }
101
102 CanvasSkia::~CanvasSkia() {
103 }
104
105 // Pass a width > 0 to force wrapping and elliding. 91 // Pass a width > 0 to force wrapping and elliding.
106 static void SetupPangoLayout(PangoLayout* layout, 92 static void SetupPangoLayout(PangoLayout* layout,
107 const std::wstring& text, 93 const std::wstring& text,
108 const gfx::Font& font, 94 const gfx::Font& font,
109 int width, 95 int width,
110 int flags) { 96 int flags) {
111 if (!cairo_font_options) 97 if (!cairo_font_options)
112 UpdateCairoFontOptions(); 98 UpdateCairoFontOptions();
113 // This needs to be done early on; it has no effect when called just before 99 // This needs to be done early on; it has no effect when called just before
114 // pango_cairo_show_layout(). 100 // pango_cairo_show_layout().
115 pango_cairo_context_set_font_options( 101 pango_cairo_context_set_font_options(
116 pango_layout_get_context(layout), cairo_font_options); 102 pango_layout_get_context(layout), cairo_font_options);
117 103
118 // Callers of DrawStringInt handle RTL layout themselves, so tell pango to not 104 // Callers of DrawStringInt handle RTL layout themselves, so tell pango to not
119 // scope out RTL characters. 105 // scope out RTL characters.
120 pango_layout_set_auto_dir(layout, FALSE); 106 pango_layout_set_auto_dir(layout, FALSE);
121 107
122 if (width > 0) 108 if (width > 0)
123 pango_layout_set_width(layout, width * PANGO_SCALE); 109 pango_layout_set_width(layout, width * PANGO_SCALE);
124 110
125 if (flags & Canvas::NO_ELLIPSIS) { 111 if (flags & gfx::Canvas::NO_ELLIPSIS) {
126 pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); 112 pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
127 } else { 113 } else {
128 pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); 114 pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
129 } 115 }
130 116
131 if (flags & Canvas::TEXT_ALIGN_CENTER) { 117 if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) {
132 pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); 118 pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
133 } else if (flags & Canvas::TEXT_ALIGN_RIGHT) { 119 } else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) {
134 pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); 120 pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
135 } 121 }
136 122
137 if (flags & Canvas::MULTI_LINE) { 123 if (flags & gfx::Canvas::MULTI_LINE) {
138 pango_layout_set_wrap(layout, 124 pango_layout_set_wrap(layout,
139 (flags & Canvas::CHARACTER_BREAK) ? 125 (flags & gfx::Canvas::CHARACTER_BREAK) ?
140 PANGO_WRAP_WORD_CHAR : PANGO_WRAP_WORD); 126 PANGO_WRAP_WORD_CHAR : PANGO_WRAP_WORD);
141 } 127 }
142 128
143 // Set the resolution to match that used by Gtk. If we don't set the 129 // Set the resolution to match that used by Gtk. If we don't set the
144 // resolution and the resolution differs from the default, Gtk and Chrome end 130 // resolution and the resolution differs from the default, Gtk and Chrome end
145 // up drawing at different sizes. 131 // up drawing at different sizes.
146 double resolution = gfx::GetPangoResolution(); 132 double resolution = gfx::GetPangoResolution();
147 if (resolution > 0) { 133 if (resolution > 0) {
148 pango_cairo_context_set_resolution(pango_layout_get_context(layout), 134 pango_cairo_context_set_resolution(pango_layout_get_context(layout),
149 resolution); 135 resolution);
(...skipping 15 matching lines...) Expand all
165 g_free(escaped_text); 151 g_free(escaped_text);
166 } else if (flags & gfx::Canvas::HIDE_PREFIX) { 152 } else if (flags & gfx::Canvas::HIDE_PREFIX) {
167 // Remove the ampersand character. 153 // Remove the ampersand character.
168 utf8 = gfx::RemoveWindowsStyleAccelerators(utf8); 154 utf8 = gfx::RemoveWindowsStyleAccelerators(utf8);
169 pango_layout_set_text(layout, utf8.data(), utf8.size()); 155 pango_layout_set_text(layout, utf8.data(), utf8.size());
170 } else { 156 } else {
171 pango_layout_set_text(layout, utf8.data(), utf8.size()); 157 pango_layout_set_text(layout, utf8.data(), utf8.size());
172 } 158 }
173 } 159 }
174 160
161 // A class to encapsulate string drawing params and operations.
162 class DrawStringContext {
163 public:
164 DrawStringContext(gfx::CanvasSkia* canvas,
165 const std::wstring& text,
166 const gfx::Font& font,
167 const gfx::Rect& bounds,
168 const gfx::Rect& clip,
169 int flags);
170 ~DrawStringContext();
171
172 void Draw(const SkColor& text_color);
173 void DrawWithHalo(const SkColor& text_color,
174 const SkColor& halo_color);
175
176 private:
177 const gfx::Rect& bounds_;
178 int flags_;
179 const gfx::Font& font_;
180
181 gfx::CanvasSkia* canvas_;
182 cairo_t* cr_;
183 PangoLayout* layout_;
184
185 int text_x_;
186 int text_y_;
187 int text_width_;
188 int text_height_;
189
190 DISALLOW_COPY_AND_ASSIGN(DrawStringContext);
191 };
192
193 DrawStringContext::DrawStringContext(gfx::CanvasSkia* canvas,
194 const std::wstring& text,
195 const gfx::Font& font,
196 const gfx::Rect& bounds,
197 const gfx::Rect& clip,
198 int flags)
199 : bounds_(bounds),
200 flags_(flags),
201 font_(font),
202 canvas_(canvas),
203 cr_(NULL),
204 layout_(NULL),
205 text_x_(bounds.x()),
206 text_y_(bounds.y()),
207 text_width_(0),
208 text_height_(0) {
209 DCHECK(!bounds_.IsEmpty());
210
211 cr_ = canvas_->beginPlatformPaint();
212 layout_ = pango_cairo_create_layout(cr_);
213
214 SetupPangoLayout(layout_, text, font, bounds_.width(), flags_);
215
216 pango_layout_set_height(layout_, bounds_.height() * PANGO_SCALE);
217
218 cairo_save(cr_);
219
220 cairo_rectangle(cr_, clip.x(), clip.y(), clip.width(), clip.height());
221 cairo_clip(cr_);
222
223 pango_layout_get_pixel_size(layout_, &text_width_, &text_height_);
224
225 if (flags_ & gfx::Canvas::TEXT_VALIGN_TOP) {
226 // Cairo should draw from the top left corner already.
227 } else if (flags_ & gfx::Canvas::TEXT_VALIGN_BOTTOM) {
228 text_y_ += (bounds.height() - text_height_);
229 } else {
230 // Vertically centered.
231 text_y_ += ((bounds.height() - text_height_) / 2);
232 }
233 }
234
235 DrawStringContext::~DrawStringContext() {
236 if (font_.GetStyle() & gfx::Font::UNDERLINED) {
237 gfx::PlatformFontGtk* platform_font =
238 static_cast<gfx::PlatformFontGtk*>(font_.platform_font());
239 double underline_y =
240 static_cast<double>(text_y_) + text_height_ +
241 platform_font->underline_position();
242 cairo_set_line_width(cr_, platform_font->underline_thickness());
243 cairo_move_to(cr_, text_x_, underline_y);
244 cairo_line_to(cr_, text_x_ + text_width_, underline_y);
245 cairo_stroke(cr_);
246 }
247 cairo_restore(cr_);
248
249 g_object_unref(layout_);
250 // NOTE: beginPlatformPaint returned its surface, we shouldn't destroy it.
251 }
252
253 void DrawStringContext::Draw(const SkColor& text_color) {
254 cairo_set_source_rgba(cr_,
255 SkColorGetR(text_color) / 255.0,
256 SkColorGetG(text_color) / 255.0,
257 SkColorGetB(text_color) / 255.0,
258 SkColorGetA(text_color) / 255.0);
259 cairo_move_to(cr_, text_x_, text_y_);
260 pango_cairo_show_layout(cr_, layout_);
261 }
262
263 void DrawStringContext::DrawWithHalo(const SkColor& text_color,
264 const SkColor& halo_color) {
265 gfx::CanvasSkia text_canvas(bounds_.width() + 2, bounds_.height() + 2, false);
266 text_canvas.FillRectInt(static_cast<SkColor>(0),
267 0, 0, bounds_.width() + 2, bounds_.height() + 2);
268
269 cairo_t* text_cr = text_canvas.beginPlatformPaint();
270
271 cairo_move_to(text_cr, 1, 1);
272 pango_cairo_layout_path(text_cr, layout_);
273
274 cairo_set_source_rgba(text_cr,
275 SkColorGetR(halo_color) / 255.0,
276 SkColorGetG(halo_color) / 255.0,
277 SkColorGetB(halo_color) / 255.0,
278 SkColorGetA(halo_color) / 255.0);
279 cairo_set_line_width(text_cr, 2.0);
280 cairo_stroke_preserve(text_cr);
281
282 cairo_set_operator(text_cr, CAIRO_OPERATOR_SOURCE);
283 cairo_set_source_rgba(text_cr,
284 SkColorGetR(text_color) / 255.0,
285 SkColorGetG(text_color) / 255.0,
286 SkColorGetB(text_color) / 255.0,
287 SkColorGetA(text_color) / 255.0);
288 cairo_fill(text_cr);
289
290 text_canvas.endPlatformPaint();
291
292 const SkBitmap& text_bitmap = const_cast<SkBitmap&>(
293 text_canvas.getTopPlatformDevice().accessBitmap(false));
294 canvas_->DrawBitmapInt(text_bitmap, text_x_ - 1, text_y_ - 1);
295 }
296
297 } // namespace
298
299 namespace gfx {
300
301 CanvasSkia::CanvasSkia(int width, int height, bool is_opaque)
302 : skia::PlatformCanvas(width, height, is_opaque) {
303 }
304
305 CanvasSkia::CanvasSkia() : skia::PlatformCanvas() {
306 }
307
308 CanvasSkia::~CanvasSkia() {
309 }
310
175 // static 311 // static
176 void CanvasSkia::SizeStringInt(const std::wstring& text, 312 void CanvasSkia::SizeStringInt(const std::wstring& text,
177 const gfx::Font& font, 313 const gfx::Font& font,
178 int* width, int* height, 314 int* width, int* height,
179 int flags) { 315 int flags) {
180 int org_width = *width; 316 int org_width = *width;
181 cairo_surface_t* surface = 317 cairo_surface_t* surface =
182 cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); 318 cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
183 cairo_t* cr = cairo_create(surface); 319 cairo_t* cr = cairo_create(surface);
184 PangoLayout* layout = pango_cairo_create_layout(cr); 320 PangoLayout* layout = pango_cairo_create_layout(cr);
(...skipping 16 matching lines...) Expand all
201 // asked for. See the loop in pango-layout.c process_item that determines 337 // asked for. See the loop in pango-layout.c process_item that determines
202 // where to wrap. 338 // where to wrap.
203 *width = org_width; 339 *width = org_width;
204 } 340 }
205 341
206 g_object_unref(layout); 342 g_object_unref(layout);
207 cairo_destroy(cr); 343 cairo_destroy(cr);
208 cairo_surface_destroy(surface); 344 cairo_surface_destroy(surface);
209 } 345 }
210 346
347 void CanvasSkia::DrawStringWithHalo(const std::wstring& text,
348 const gfx::Font& font,
349 const SkColor& text_color,
350 const SkColor& halo_color,
351 int x, int y, int w, int h,
352 int flags) {
353 if (w <= 0 || h <= 0)
354 return;
355
356 gfx::Rect bounds(x, y, w, h);
357 gfx::Rect clip(x - 1, y - 1, w + 2, h + 2); // Bigger clip for halo
358 DrawStringContext context(this, text, font, bounds, clip,flags);
359 context.DrawWithHalo(text_color, halo_color);
360 }
361
211 void CanvasSkia::DrawStringInt(const std::wstring& text, 362 void CanvasSkia::DrawStringInt(const std::wstring& text,
212 const gfx::Font& font, 363 const gfx::Font& font,
213 const SkColor& color, 364 const SkColor& color,
214 int x, int y, int w, int h, 365 int x, int y, int w, int h,
215 int flags) { 366 int flags) {
216 if (w <= 0 || h <= 0) 367 if (w <= 0 || h <= 0)
217 return; 368 return;
218 369
219 cairo_t* cr = beginPlatformPaint(); 370 gfx::Rect bounds(x, y, w, h);
220 PangoLayout* layout = pango_cairo_create_layout(cr); 371 DrawStringContext context(this, text, font, bounds, bounds, flags);
221 372 context.Draw(color);
222 SetupPangoLayout(layout, text, font, w, flags);
223
224 pango_layout_set_height(layout, h * PANGO_SCALE);
225
226 cairo_save(cr);
227 cairo_set_source_rgba(cr,
228 SkColorGetR(color) / 255.0,
229 SkColorGetG(color) / 255.0,
230 SkColorGetB(color) / 255.0,
231 SkColorGetA(color) / 255.0);
232
233 int width, height;
234 pango_layout_get_pixel_size(layout, &width, &height);
235
236 cairo_rectangle(cr, x, y, w, h);
237 cairo_clip(cr);
238
239 if (flags & Canvas::TEXT_VALIGN_TOP) {
240 // Cairo should draw from the top left corner already.
241 } else if (flags & Canvas::TEXT_VALIGN_BOTTOM) {
242 y += (h - height);
243 } else {
244 // Vertically centered.
245 y += ((h - height) / 2);
246 }
247
248 cairo_move_to(cr, x, y);
249 pango_cairo_show_layout(cr, layout);
250 if (font.GetStyle() & gfx::Font::UNDERLINED) {
251 gfx::PlatformFontGtk* platform_font =
252 static_cast<gfx::PlatformFontGtk*>(font.platform_font());
253 double underline_y =
254 static_cast<double>(y) + height + platform_font->underline_position();
255 cairo_set_line_width(cr, platform_font->underline_thickness());
256 cairo_move_to(cr, x, underline_y);
257 cairo_line_to(cr, x + width, underline_y);
258 cairo_stroke(cr);
259 }
260 cairo_restore(cr);
261
262 g_object_unref(layout);
263 // NOTE: beginPlatformPaint returned its surface, we shouldn't destroy it.
264 } 373 }
265 374
266 void CanvasSkia::DrawGdkPixbuf(GdkPixbuf* pixbuf, int x, int y) { 375 void CanvasSkia::DrawGdkPixbuf(GdkPixbuf* pixbuf, int x, int y) {
267 if (!pixbuf) { 376 if (!pixbuf) {
268 NOTREACHED(); 377 NOTREACHED();
269 return; 378 return;
270 } 379 }
271 380
272 cairo_t* cr = beginPlatformPaint(); 381 cairo_t* cr = beginPlatformPaint();
273 gdk_cairo_set_source_pixbuf(cr, pixbuf, x, y); 382 gdk_cairo_set_source_pixbuf(cr, pixbuf, x, y);
274 cairo_paint(cr); 383 cairo_paint(cr);
275 } 384 }
276 385
277 } // namespace gfx 386 } // namespace gfx
OLDNEW
« no previous file with comments | « gfx/canvas_skia.h ('k') | views/controls/button/text_button.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698