| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |