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

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

Issue 1634103003: Fix gfx::Canvas::DrawStringRectWithHalo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: check halo pixels Created 4 years, 10 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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.h" 5 #include "ui/gfx/canvas.h"
6 6
7 #include <limits.h> 7 #include <limits.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 10 matching lines...) Expand all
21 #include "ui/gfx/range/range.h" 21 #include "ui/gfx/range/range.h"
22 #include "ui/gfx/render_text.h" 22 #include "ui/gfx/render_text.h"
23 #include "ui/gfx/shadow_value.h" 23 #include "ui/gfx/shadow_value.h"
24 #include "ui/gfx/text_elider.h" 24 #include "ui/gfx/text_elider.h"
25 #include "ui/gfx/text_utils.h" 25 #include "ui/gfx/text_utils.h"
26 26
27 namespace gfx { 27 namespace gfx {
28 28
29 namespace { 29 namespace {
30 30
31 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If
32 // any of them are not the halo color, returns true. This defines the halo of
33 // pixels that will appear around the text. Note that we have to check each
34 // pixel against both the halo color and transparent since
35 // |DrawStringRectWithHalo| will modify the bitmap as it goes, and cleared
36 // pixels shouldn't count as changed.
37 bool PixelShouldGetHalo(const SkPixmap& pixmap,
38 int x, int y,
39 SkColor halo_color) {
40 if (x > 0 &&
41 *pixmap.addr32(x - 1, y) != halo_color &&
42 *pixmap.addr32(x - 1, y) != 0)
43 return true; // Touched pixel to the left.
44 if (x < pixmap.width() - 1 &&
45 *pixmap.addr32(x + 1, y) != halo_color &&
46 *pixmap.addr32(x + 1, y) != 0)
47 return true; // Touched pixel to the right.
48 if (y > 0 &&
49 *pixmap.addr32(x, y - 1) != halo_color &&
50 *pixmap.addr32(x, y - 1) != 0)
51 return true; // Touched pixel above.
52 if (y < pixmap.height() - 1 &&
53 *pixmap.addr32(x, y + 1) != halo_color &&
54 *pixmap.addr32(x, y + 1) != 0)
55 return true; // Touched pixel below.
56 return false;
57 }
58
59 // Strips accelerator character prefixes in |text| if needed, based on |flags|. 31 // Strips accelerator character prefixes in |text| if needed, based on |flags|.
60 // Returns a range in |text| to underline or Range::InvalidRange() if 32 // Returns a range in |text| to underline or Range::InvalidRange() if
61 // underlining is not needed. 33 // underlining is not needed.
62 Range StripAcceleratorChars(int flags, base::string16* text) { 34 Range StripAcceleratorChars(int flags, base::string16* text) {
63 if (flags & (Canvas::SHOW_PREFIX | Canvas::HIDE_PREFIX)) { 35 if (flags & (Canvas::SHOW_PREFIX | Canvas::HIDE_PREFIX)) {
64 int char_pos = -1; 36 int char_pos = -1;
65 int char_span = 0; 37 int char_span = 0;
66 *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span); 38 *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span);
67 if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1) 39 if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1)
68 return Range(char_pos, char_pos + char_span); 40 return Range(char_pos, char_pos + char_span);
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 Rect clip_rect(text_bounds); 165 Rect clip_rect(text_bounds);
194 clip_rect.Inset(ShadowValue::GetMargin(shadows)); 166 clip_rect.Inset(ShadowValue::GetMargin(shadows));
195 167
196 canvas_->save(); 168 canvas_->save();
197 ClipRect(clip_rect); 169 ClipRect(clip_rect);
198 170
199 Rect rect(text_bounds); 171 Rect rect(text_bounds);
200 172
201 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 173 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
202 render_text->set_shadows(shadows); 174 render_text->set_shadows(shadows);
175 render_text->set_halo_effect(!!(flags & HALO_EFFECT));
203 176
204 if (flags & MULTI_LINE) { 177 if (flags & MULTI_LINE) {
205 WordWrapBehavior wrap_behavior = IGNORE_LONG_WORDS; 178 WordWrapBehavior wrap_behavior = IGNORE_LONG_WORDS;
206 if (flags & CHARACTER_BREAK) 179 if (flags & CHARACTER_BREAK)
207 wrap_behavior = WRAP_LONG_WORDS; 180 wrap_behavior = WRAP_LONG_WORDS;
208 else if (!(flags & NO_ELLIPSIS)) 181 else if (!(flags & NO_ELLIPSIS))
209 wrap_behavior = ELIDE_LONG_WORDS; 182 wrap_behavior = ELIDE_LONG_WORDS;
210 183
211 std::vector<base::string16> strings; 184 std::vector<base::string16> strings;
212 ElideRectangleText(text, font_list, 185 ElideRectangleText(text, font_list,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 void Canvas::DrawStringRectWithHalo(const base::string16& text, 249 void Canvas::DrawStringRectWithHalo(const base::string16& text,
277 const FontList& font_list, 250 const FontList& font_list,
278 SkColor text_color, 251 SkColor text_color,
279 SkColor halo_color_in, 252 SkColor halo_color_in,
280 const Rect& display_rect, 253 const Rect& display_rect,
281 int flags) { 254 int flags) {
282 // Some callers will have semitransparent halo colors, which we don't handle 255 // Some callers will have semitransparent halo colors, which we don't handle
283 // (since the resulting image can have 1-bit transparency only). 256 // (since the resulting image can have 1-bit transparency only).
284 SkColor halo_color = SkColorSetA(halo_color_in, 0xFF); 257 SkColor halo_color = SkColorSetA(halo_color_in, 0xFF);
285 258
286 // Create a temporary buffer filled with the halo color. It must leave room 259 // Draw the halo.
287 // for the 1-pixel border around the text. 260 DrawStringRectWithFlags(text, font_list, halo_color, display_rect,
288 Size size(display_rect.width() + 2, display_rect.height() + 2); 261 flags | HALO_EFFECT | NO_SUBPIXEL_RENDERING);
289 Canvas text_canvas(size, image_scale(), false); 262 // Draw the text.
290 SkPaint bkgnd_paint; 263 DrawStringRectWithFlags(text, font_list, text_color, display_rect,
291 bkgnd_paint.setColor(halo_color); 264 flags | NO_SUBPIXEL_RENDERING);
292 text_canvas.DrawRect(Rect(size), bkgnd_paint);
293
294 // Draw the text into the temporary buffer. This will have correct
295 // ClearType since the background color is the same as the halo color.
296 text_canvas.DrawStringRectWithFlags(
297 text, font_list, text_color,
298 Rect(1, 1, display_rect.width(), display_rect.height()), flags);
299
300 uint32_t halo_premul = SkPreMultiplyColor(halo_color);
301 SkPixmap pixmap;
302 skia::GetWritablePixels(text_canvas.sk_canvas(), &pixmap);
303
304 for (int cur_y = 0; cur_y < pixmap.height(); cur_y++) {
305 uint32_t* text_row = pixmap.writable_addr32(0, cur_y);
306 for (int cur_x = 0; cur_x < pixmap.width(); cur_x++) {
307 if (text_row[cur_x] == halo_premul) {
308 // This pixel was not touched by the text routines. See if it borders
309 // a touched pixel in any of the 4 directions (not diagonally).
310 if (!PixelShouldGetHalo(pixmap, cur_x, cur_y, halo_premul))
311 text_row[cur_x] = 0; // Make transparent.
312 } else {
313 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque.
314 }
315 }
316 }
317
318 // Draw the halo bitmap with blur.
319 SkBitmap bitmap;
320 bitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
321 pixmap.rowBytes());
322 ImageSkia text_image = ImageSkia(ImageSkiaRep(bitmap,
323 text_canvas.image_scale()));
324 DrawImageInt(text_image, display_rect.x() - 1, display_rect.y() - 1);
325 } 265 }
326 266
327 void Canvas::DrawFadedString(const base::string16& text, 267 void Canvas::DrawFadedString(const base::string16& text,
328 const FontList& font_list, 268 const FontList& font_list,
329 SkColor color, 269 SkColor color,
330 const Rect& display_rect, 270 const Rect& display_rect,
331 int flags) { 271 int flags) {
332 // If the whole string fits in the destination then just draw it directly. 272 // If the whole string fits in the destination then just draw it directly.
333 if (GetStringWidth(text, font_list) <= display_rect.width()) { 273 if (GetStringWidth(text, font_list) <= display_rect.width()) {
334 DrawStringRectWithFlags(text, font_list, color, display_rect, flags); 274 DrawStringRectWithFlags(text, font_list, color, display_rect, flags);
(...skipping 10 matching lines...) Expand all
345 UpdateRenderText(rect, text, font_list, flags, color, render_text.get()); 285 UpdateRenderText(rect, text, font_list, flags, color, render_text.get());
346 render_text->SetElideBehavior(FADE_TAIL); 286 render_text->SetElideBehavior(FADE_TAIL);
347 287
348 canvas_->save(); 288 canvas_->save();
349 ClipRect(display_rect); 289 ClipRect(display_rect);
350 render_text->Draw(this); 290 render_text->Draw(this);
351 canvas_->restore(); 291 canvas_->restore();
352 } 292 }
353 293
354 } // namespace gfx 294 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/canvas.h ('k') | ui/gfx/render_text.h » ('j') | ui/gfx/render_text.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698