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

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

Powered by Google App Engine
This is Rietveld 408576698