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

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

Issue 22835002: Supports gfx::FontList in gfx::Canvas and ui::ElideText family. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Introduces layout_text.h to provide GetStringWidth(). Created 7 years, 4 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 | Annotate | Revision Log
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 "base/i18n/rtl.h" 7 #include "base/i18n/rtl.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "ui/base/range/range.h" 10 #include "ui/base/range/range.h"
11 #include "ui/base/text/text_elider.h" 11 #include "ui/base/text/text_elider.h"
12 #include "ui/gfx/font.h"
13 #include "ui/gfx/font_list.h" 12 #include "ui/gfx/font_list.h"
14 #include "ui/gfx/insets.h" 13 #include "ui/gfx/insets.h"
15 #include "ui/gfx/rect.h" 14 #include "ui/gfx/rect.h"
16 #include "ui/gfx/render_text.h" 15 #include "ui/gfx/render_text.h"
17 #include "ui/gfx/shadow_value.h" 16 #include "ui/gfx/shadow_value.h"
18 #include "ui/gfx/text_utils.h" 17 #include "ui/gfx/text_utils.h"
19 18
20 namespace gfx { 19 namespace gfx {
21 20
22 namespace { 21 namespace {
(...skipping 27 matching lines...) Expand all
50 // default directionality is LTR, so the text doesn't need to be wrapped. 49 // default directionality is LTR, so the text doesn't need to be wrapped.
51 // Note that individual runs within the string may still be rendered RTL 50 // Note that individual runs within the string may still be rendered RTL
52 // (which will be the case for RTL text under non-RTL locales, since under RTL 51 // (which will be the case for RTL text under non-RTL locales, since under RTL
53 // locales it will be handled by the if statement above). 52 // locales it will be handled by the if statement above).
54 return false; 53 return false;
55 } 54 }
56 55
57 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If 56 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If
58 // any of them are not the halo color, returns true. This defines the halo of 57 // any of them are not the halo color, returns true. This defines the halo of
59 // pixels that will appear around the text. Note that we have to check each 58 // pixels that will appear around the text. Note that we have to check each
60 // pixel against both the halo color and transparent since |DrawStringWithHalo| 59 // pixel against both the halo color and transparent since
61 // will modify the bitmap as it goes, and cleared pixels shouldn't count as 60 // |DrawStringRectWithHalo| will modify the bitmap as it goes, and cleared
62 // changed. 61 // pixels shouldn't count as changed.
63 bool PixelShouldGetHalo(const SkBitmap& bitmap, 62 bool PixelShouldGetHalo(const SkBitmap& bitmap,
64 int x, int y, 63 int x, int y,
65 SkColor halo_color) { 64 SkColor halo_color) {
66 if (x > 0 && 65 if (x > 0 &&
67 *bitmap.getAddr32(x - 1, y) != halo_color && 66 *bitmap.getAddr32(x - 1, y) != halo_color &&
68 *bitmap.getAddr32(x - 1, y) != 0) 67 *bitmap.getAddr32(x - 1, y) != 0)
69 return true; // Touched pixel to the left. 68 return true; // Touched pixel to the left.
70 if (x < bitmap.width() - 1 && 69 if (x < bitmap.width() - 1 &&
71 *bitmap.getAddr32(x + 1, y) != halo_color && 70 *bitmap.getAddr32(x + 1, y) != halo_color &&
72 *bitmap.getAddr32(x + 1, y) != 0) 71 *bitmap.getAddr32(x + 1, y) != 0)
(...skipping 18 matching lines...) Expand all
91 int char_span = 0; 90 int char_span = 0;
92 *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span); 91 *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span);
93 if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1) 92 if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1)
94 return ui::Range(char_pos, char_pos + char_span); 93 return ui::Range(char_pos, char_pos + char_span);
95 } 94 }
96 return ui::Range::InvalidRange(); 95 return ui::Range::InvalidRange();
97 } 96 }
98 97
99 // Elides |text| and adjusts |range| appropriately. If eliding causes |range| 98 // Elides |text| and adjusts |range| appropriately. If eliding causes |range|
100 // to no longer point to the same character in |text|, |range| is made invalid. 99 // to no longer point to the same character in |text|, |range| is made invalid.
101 void ElideTextAndAdjustRange(const Font& font, 100 void ElideTextAndAdjustRange(const FontList& font_list,
102 int width, 101 int width,
103 base::string16* text, 102 base::string16* text,
104 ui::Range* range) { 103 ui::Range* range) {
105 const base::char16 start_char = 104 const base::char16 start_char =
106 (range->IsValid() ? text->at(range->start()) : 0); 105 (range->IsValid() ? text->at(range->start()) : 0);
107 *text = ui::ElideText(*text, font, width, ui::ELIDE_AT_END); 106 *text = ui::ElideText(*text, font_list, width, ui::ELIDE_AT_END);
108 if (!range->IsValid()) 107 if (!range->IsValid())
109 return; 108 return;
110 if (range->start() >= text->length() || 109 if (range->start() >= text->length() ||
111 text->at(range->start()) != start_char) { 110 text->at(range->start()) != start_char) {
112 *range = ui::Range::InvalidRange(); 111 *range = ui::Range::InvalidRange();
113 } 112 }
114 } 113 }
115 114
116 // Updates |render_text| from the specified parameters. 115 // Updates |render_text| from the specified parameters.
117 void UpdateRenderText(const Rect& rect, 116 void UpdateRenderText(const Rect& rect,
118 const base::string16& text, 117 const base::string16& text,
119 const Font& font, 118 const FontList& font_list,
120 int flags, 119 int flags,
121 SkColor color, 120 SkColor color,
122 RenderText* render_text) { 121 RenderText* render_text) {
123 render_text->SetFont(font); 122 render_text->SetFontList(font_list);
124 render_text->SetText(text); 123 render_text->SetText(text);
125 render_text->SetCursorEnabled(false); 124 render_text->SetCursorEnabled(false);
126 125
127 Rect display_rect = rect; 126 Rect display_rect = rect;
128 display_rect.set_height(font.GetHeight()); 127 display_rect.set_height(font_list.GetHeight());
129 render_text->SetDisplayRect(display_rect); 128 render_text->SetDisplayRect(display_rect);
130 129
131 // Set the text alignment explicitly based on the directionality of the UI, 130 // Set the text alignment explicitly based on the directionality of the UI,
132 // if not specified. 131 // if not specified.
133 if (!(flags & (Canvas::TEXT_ALIGN_CENTER | 132 if (!(flags & (Canvas::TEXT_ALIGN_CENTER |
134 Canvas::TEXT_ALIGN_RIGHT | 133 Canvas::TEXT_ALIGN_RIGHT |
135 Canvas::TEXT_ALIGN_LEFT))) { 134 Canvas::TEXT_ALIGN_LEFT))) {
136 flags |= Canvas::DefaultCanvasTextAlignment(); 135 flags |= Canvas::DefaultCanvasTextAlignment();
137 } 136 }
138 137
139 if (flags & Canvas::TEXT_ALIGN_RIGHT) 138 if (flags & Canvas::TEXT_ALIGN_RIGHT)
140 render_text->SetHorizontalAlignment(ALIGN_RIGHT); 139 render_text->SetHorizontalAlignment(ALIGN_RIGHT);
141 else if (flags & Canvas::TEXT_ALIGN_CENTER) 140 else if (flags & Canvas::TEXT_ALIGN_CENTER)
142 render_text->SetHorizontalAlignment(ALIGN_CENTER); 141 render_text->SetHorizontalAlignment(ALIGN_CENTER);
143 else 142 else
144 render_text->SetHorizontalAlignment(ALIGN_LEFT); 143 render_text->SetHorizontalAlignment(ALIGN_LEFT);
145 144
146 if (flags & Canvas::NO_SUBPIXEL_RENDERING) 145 if (flags & Canvas::NO_SUBPIXEL_RENDERING)
147 render_text->set_background_is_transparent(true); 146 render_text->set_background_is_transparent(true);
148 147
149 render_text->SetColor(color); 148 render_text->SetColor(color);
150 render_text->SetStyle(BOLD, (font.GetStyle() & Font::BOLD) != 0); 149 const int font_style = font_list.GetFontStyle();
151 render_text->SetStyle(ITALIC, (font.GetStyle() & Font::ITALIC) != 0); 150 render_text->SetStyle(BOLD, (font_style & Font::BOLD) != 0);
152 render_text->SetStyle(UNDERLINE, (font.GetStyle() & Font::UNDERLINE) != 0); 151 render_text->SetStyle(ITALIC, (font_style & Font::ITALIC) != 0);
152 render_text->SetStyle(UNDERLINE, (font_style & Font::UNDERLINE) != 0);
153 } 153 }
154 154
155 // Returns updated |flags| to match platform-specific expected behavior. 155 // Returns updated |flags| to match platform-specific expected behavior.
156 int AdjustPlatformSpecificFlags(const base::string16& text, int flags) { 156 int AdjustPlatformSpecificFlags(const base::string16& text, int flags) {
157 #if defined(OS_LINUX) 157 #if defined(OS_LINUX)
158 // TODO(asvitkine): ash/tooltips/tooltip_controller.cc adds \n's to the string 158 // TODO(asvitkine): ash/tooltips/tooltip_controller.cc adds \n's to the string
159 // without passing MULTI_LINE. 159 // without passing MULTI_LINE.
160 if (text.find('\n') != base::string16::npos) 160 if (text.find('\n') != base::string16::npos)
161 flags |= Canvas::MULTI_LINE; 161 flags |= Canvas::MULTI_LINE;
162 #endif 162 #endif
163 163
164 return flags; 164 return flags;
165 } 165 }
166 166
167 } // namespace 167 } // namespace
168 168
169 // static 169 // static
170 void Canvas::SizeStringInt(const base::string16& text, 170 void Canvas::SizeStringInt(const base::string16& text,
171 const Font& font, 171 const FontList& font_list,
172 int* width, int* height, 172 int* width, int* height,
173 int line_height, 173 int line_height,
174 int flags) { 174 int flags) {
175 DCHECK_GE(*width, 0); 175 DCHECK_GE(*width, 0);
176 DCHECK_GE(*height, 0); 176 DCHECK_GE(*height, 0);
177 177
178 flags = AdjustPlatformSpecificFlags(text, flags); 178 flags = AdjustPlatformSpecificFlags(text, flags);
179 179
180 base::string16 adjusted_text = text; 180 base::string16 adjusted_text = text;
181 #if defined(OS_WIN) 181 #if defined(OS_WIN)
182 AdjustStringDirection(flags, &adjusted_text); 182 AdjustStringDirection(flags, &adjusted_text);
183 #endif 183 #endif
184 184
185 if ((flags & MULTI_LINE) && *width != 0) { 185 if ((flags & MULTI_LINE) && *width != 0) {
186 ui::WordWrapBehavior wrap_behavior = ui::TRUNCATE_LONG_WORDS; 186 ui::WordWrapBehavior wrap_behavior = ui::TRUNCATE_LONG_WORDS;
187 if (flags & CHARACTER_BREAK) 187 if (flags & CHARACTER_BREAK)
188 wrap_behavior = ui::WRAP_LONG_WORDS; 188 wrap_behavior = ui::WRAP_LONG_WORDS;
189 else if (!(flags & NO_ELLIPSIS)) 189 else if (!(flags & NO_ELLIPSIS))
190 wrap_behavior = ui::ELIDE_LONG_WORDS; 190 wrap_behavior = ui::ELIDE_LONG_WORDS;
191 191
192 Rect rect(*width, INT_MAX); 192 Rect rect(*width, INT_MAX);
193 std::vector<base::string16> strings; 193 std::vector<base::string16> strings;
194 ui::ElideRectangleText(adjusted_text, font, rect.width(), rect.height(), 194 ui::ElideRectangleText(adjusted_text, font_list,
195 rect.width(), rect.height(),
195 wrap_behavior, &strings); 196 wrap_behavior, &strings);
196 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 197 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
197 UpdateRenderText(rect, base::string16(), font, flags, 0, render_text.get()); 198 UpdateRenderText(rect, base::string16(), font_list, flags, 0,
199 render_text.get());
198 200
199 int h = 0; 201 int h = 0;
200 int w = 0; 202 int w = 0;
201 for (size_t i = 0; i < strings.size(); ++i) { 203 for (size_t i = 0; i < strings.size(); ++i) {
202 StripAcceleratorChars(flags, &strings[i]); 204 StripAcceleratorChars(flags, &strings[i]);
203 render_text->SetText(strings[i]); 205 render_text->SetText(strings[i]);
204 const Size string_size = render_text->GetStringSize(); 206 const Size& string_size = render_text->GetStringSize();
205 w = std::max(w, string_size.width()); 207 w = std::max(w, string_size.width());
206 h += (i > 0 && line_height > 0) ? line_height : string_size.height(); 208 h += (i > 0 && line_height > 0) ? line_height : string_size.height();
207 } 209 }
208 *width = w; 210 *width = w;
209 *height = h; 211 *height = h;
210 } else { 212 } else {
211 // If the string is too long, the call by |RenderTextWin| to |ScriptShape()| 213 // If the string is too long, the call by |RenderTextWin| to |ScriptShape()|
212 // will inexplicably fail with result E_INVALIDARG. Guard against this. 214 // will inexplicably fail with result E_INVALIDARG. Guard against this.
213 const size_t kMaxRenderTextLength = 5000; 215 const size_t kMaxRenderTextLength = 5000;
214 if (adjusted_text.length() >= kMaxRenderTextLength) { 216 if (adjusted_text.length() >= kMaxRenderTextLength) {
215 *width = adjusted_text.length() * font.GetAverageCharacterWidth(); 217 *width = font_list.GetExpectedTextWidth(adjusted_text.length());
216 *height = font.GetHeight(); 218 *height = font_list.GetHeight();
217 } else { 219 } else {
218 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 220 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
219 Rect rect(*width, *height); 221 Rect rect(*width, *height);
220 StripAcceleratorChars(flags, &adjusted_text); 222 StripAcceleratorChars(flags, &adjusted_text);
221 UpdateRenderText(rect, adjusted_text, font, flags, 0, render_text.get()); 223 UpdateRenderText(rect, adjusted_text, font_list, flags, 0,
222 const Size string_size = render_text->GetStringSize(); 224 render_text.get());
225 const Size& string_size = render_text->GetStringSize();
223 *width = string_size.width(); 226 *width = string_size.width();
224 *height = string_size.height(); 227 *height = string_size.height();
225 } 228 }
226 } 229 }
227 } 230 }
228 231
229 void Canvas::DrawStringWithShadows(const base::string16& text, 232 void Canvas::DrawStringRectWithShadows(const base::string16& text,
230 const Font& font, 233 const FontList& font_list,
231 SkColor color, 234 SkColor color,
232 const Rect& text_bounds, 235 const Rect& text_bounds,
233 int line_height, 236 int line_height,
234 int flags, 237 int flags,
235 const ShadowValues& shadows) { 238 const ShadowValues& shadows) {
236 if (!IntersectsClipRect(text_bounds)) 239 if (!IntersectsClipRect(text_bounds))
237 return; 240 return;
238 241
239 flags = AdjustPlatformSpecificFlags(text, flags); 242 flags = AdjustPlatformSpecificFlags(text, flags);
240 243
241 Rect clip_rect(text_bounds); 244 Rect clip_rect(text_bounds);
242 clip_rect.Inset(ShadowValue::GetMargin(shadows)); 245 clip_rect.Inset(ShadowValue::GetMargin(shadows));
243 246
244 canvas_->save(SkCanvas::kClip_SaveFlag); 247 canvas_->save(SkCanvas::kClip_SaveFlag);
245 ClipRect(clip_rect); 248 ClipRect(clip_rect);
(...skipping 10 matching lines...) Expand all
256 259
257 if (flags & MULTI_LINE) { 260 if (flags & MULTI_LINE) {
258 ui::WordWrapBehavior wrap_behavior = ui::IGNORE_LONG_WORDS; 261 ui::WordWrapBehavior wrap_behavior = ui::IGNORE_LONG_WORDS;
259 if (flags & CHARACTER_BREAK) 262 if (flags & CHARACTER_BREAK)
260 wrap_behavior = ui::WRAP_LONG_WORDS; 263 wrap_behavior = ui::WRAP_LONG_WORDS;
261 else if (!(flags & NO_ELLIPSIS)) 264 else if (!(flags & NO_ELLIPSIS))
262 wrap_behavior = ui::ELIDE_LONG_WORDS; 265 wrap_behavior = ui::ELIDE_LONG_WORDS;
263 266
264 std::vector<base::string16> strings; 267 std::vector<base::string16> strings;
265 ui::ElideRectangleText(adjusted_text, 268 ui::ElideRectangleText(adjusted_text,
266 font, 269 font_list,
267 text_bounds.width(), text_bounds.height(), 270 text_bounds.width(), text_bounds.height(),
268 wrap_behavior, 271 wrap_behavior,
269 &strings); 272 &strings);
270 273
271 for (size_t i = 0; i < strings.size(); i++) { 274 for (size_t i = 0; i < strings.size(); i++) {
272 ui::Range range = StripAcceleratorChars(flags, &strings[i]); 275 ui::Range range = StripAcceleratorChars(flags, &strings[i]);
273 UpdateRenderText(rect, strings[i], font, flags, color, render_text.get()); 276 UpdateRenderText(rect, strings[i], font_list, flags, color,
277 render_text.get());
274 int line_padding = 0; 278 int line_padding = 0;
275 if (line_height > 0) 279 if (line_height > 0)
276 line_padding = line_height - render_text->GetStringSize().height(); 280 line_padding = line_height - render_text->GetStringSize().height();
277 else 281 else
278 line_height = render_text->GetStringSize().height(); 282 line_height = render_text->GetStringSize().height();
279 283
280 // TODO(msw|asvitkine): Center Windows multi-line text: crbug.com/107357 284 // TODO(msw|asvitkine): Center Windows multi-line text: crbug.com/107357
281 #if !defined(OS_WIN) 285 #if !defined(OS_WIN)
282 if (i == 0) { 286 if (i == 0) {
283 // TODO(msw|asvitkine): Support multi-line text with varied heights. 287 // TODO(msw|asvitkine): Support multi-line text with varied heights.
(...skipping 20 matching lines...) Expand all
304 if (elide_text) { 308 if (elide_text) {
305 render_text->SetText(adjusted_text); 309 render_text->SetText(adjusted_text);
306 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) { 310 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) {
307 render_text->set_fade_tail(true); 311 render_text->set_fade_tail(true);
308 elide_text = false; 312 elide_text = false;
309 } 313 }
310 } 314 }
311 #endif 315 #endif
312 316
313 if (elide_text) { 317 if (elide_text) {
314 ElideTextAndAdjustRange(font, 318 ElideTextAndAdjustRange(font_list,
315 text_bounds.width(), 319 text_bounds.width(),
316 &adjusted_text, 320 &adjusted_text,
317 &range); 321 &range);
318 } 322 }
319 323
320 UpdateRenderText(rect, adjusted_text, font, flags, color, 324 UpdateRenderText(rect, adjusted_text, font_list, flags, color,
321 render_text.get()); 325 render_text.get());
322 326
323 const int text_height = render_text->GetStringSize().height(); 327 const int text_height = render_text->GetStringSize().height();
324 // Center the text vertically. 328 // Center the text vertically.
325 rect += Vector2d(0, (text_bounds.height() - text_height) / 2); 329 rect += Vector2d(0, (text_bounds.height() - text_height) / 2);
326 rect.set_height(text_height); 330 rect.set_height(text_height);
327 render_text->SetDisplayRect(rect); 331 render_text->SetDisplayRect(rect);
328 if (range.IsValid()) 332 if (range.IsValid())
329 render_text->ApplyStyle(UNDERLINE, true, range); 333 render_text->ApplyStyle(UNDERLINE, true, range);
330 render_text->Draw(this); 334 render_text->Draw(this);
331 } 335 }
332 336
333 canvas_->restore(); 337 canvas_->restore();
334 } 338 }
335 339
336 void Canvas::DrawStringWithHalo(const base::string16& text, 340 void Canvas::DrawStringRectWithHalo(const base::string16& text,
337 const Font& font, 341 const FontList& font_list,
338 SkColor text_color, 342 SkColor text_color,
339 SkColor halo_color_in, 343 SkColor halo_color_in,
340 int x, int y, int w, int h, 344 const Rect& display_rect,
341 int flags) { 345 int flags) {
342 // Some callers will have semitransparent halo colors, which we don't handle 346 // Some callers will have semitransparent halo colors, which we don't handle
343 // (since the resulting image can have 1-bit transparency only). 347 // (since the resulting image can have 1-bit transparency only).
344 SkColor halo_color = SkColorSetA(halo_color_in, 0xFF); 348 SkColor halo_color = SkColorSetA(halo_color_in, 0xFF);
345 349
346 // Create a temporary buffer filled with the halo color. It must leave room 350 // Create a temporary buffer filled with the halo color. It must leave room
347 // for the 1-pixel border around the text. 351 // for the 1-pixel border around the text.
348 Size size(w + 2, h + 2); 352 Size size(display_rect.width() + 2, display_rect.height() + 2);
349 Canvas text_canvas(size, scale_factor(), true); 353 Canvas text_canvas(size, scale_factor(), true);
350 SkPaint bkgnd_paint; 354 SkPaint bkgnd_paint;
351 bkgnd_paint.setColor(halo_color); 355 bkgnd_paint.setColor(halo_color);
352 text_canvas.DrawRect(Rect(size), bkgnd_paint); 356 text_canvas.DrawRect(Rect(size), bkgnd_paint);
353 357
354 // Draw the text into the temporary buffer. This will have correct 358 // Draw the text into the temporary buffer. This will have correct
355 // ClearType since the background color is the same as the halo color. 359 // ClearType since the background color is the same as the halo color.
356 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); 360 text_canvas.DrawStringRectWithFlags(
361 text, font_list, text_color,
362 Rect(1, 1, display_rect.width(), display_rect.height()), flags);
357 363
358 uint32_t halo_premul = SkPreMultiplyColor(halo_color); 364 uint32_t halo_premul = SkPreMultiplyColor(halo_color);
359 SkBitmap& text_bitmap = const_cast<SkBitmap&>( 365 SkBitmap& text_bitmap = const_cast<SkBitmap&>(
360 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(true)); 366 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(true));
361 367
362 for (int cur_y = 0; cur_y < text_bitmap.height(); cur_y++) { 368 for (int cur_y = 0; cur_y < text_bitmap.height(); cur_y++) {
363 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); 369 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y);
364 for (int cur_x = 0; cur_x < text_bitmap.width(); cur_x++) { 370 for (int cur_x = 0; cur_x < text_bitmap.width(); cur_x++) {
365 if (text_row[cur_x] == halo_premul) { 371 if (text_row[cur_x] == halo_premul) {
366 // This pixel was not touched by the text routines. See if it borders 372 // This pixel was not touched by the text routines. See if it borders
367 // a touched pixel in any of the 4 directions (not diagonally). 373 // a touched pixel in any of the 4 directions (not diagonally).
368 if (!PixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) 374 if (!PixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul))
369 text_row[cur_x] = 0; // Make transparent. 375 text_row[cur_x] = 0; // Make transparent.
370 } else { 376 } else {
371 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. 377 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque.
372 } 378 }
373 } 379 }
374 } 380 }
375 381
376 // Draw the halo bitmap with blur. 382 // Draw the halo bitmap with blur.
377 ImageSkia text_image = ImageSkia(ImageSkiaRep(text_bitmap, 383 ImageSkia text_image = ImageSkia(ImageSkiaRep(text_bitmap,
378 text_canvas.scale_factor())); 384 text_canvas.scale_factor()));
379 DrawImageInt(text_image, x - 1, y - 1); 385 DrawImageInt(text_image, display_rect.x() - 1, display_rect.y() - 1);
380 } 386 }
381 387
382 void Canvas::DrawFadeTruncatingString( 388 void Canvas::DrawFadeTruncatingStringRect(
383 const base::string16& text, 389 const base::string16& text,
384 TruncateFadeMode truncate_mode, 390 TruncateFadeMode truncate_mode,
385 size_t desired_characters_to_truncate_from_head, 391 size_t desired_characters_to_truncate_from_head,
386 const Font& font, 392 const FontList& font_list,
387 SkColor color, 393 SkColor color,
388 const Rect& display_rect) { 394 const Rect& display_rect) {
389 int flags = NO_ELLIPSIS; 395 int flags = NO_ELLIPSIS;
390 396
391 // If the whole string fits in the destination then just draw it directly. 397 // If the whole string fits in the destination then just draw it directly.
392 if (GetStringWidth(text, font) <= display_rect.width()) { 398 if (GetStringWidth(text, font_list) <= display_rect.width()) {
393 DrawStringInt(text, font, color, display_rect.x(), display_rect.y(), 399 DrawStringRectWithFlags(text, font_list, color, display_rect, flags);
394 display_rect.width(), display_rect.height(), flags);
395 return; 400 return;
396 } 401 }
397 402
398 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 403 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
399 base::string16 clipped_text = text; 404 base::string16 clipped_text = text;
400 const bool is_rtl = AdjustStringDirection(flags, &clipped_text); 405 const bool is_rtl = AdjustStringDirection(flags, &clipped_text);
401 406
402 switch (truncate_mode) { 407 switch (truncate_mode) {
403 case TruncateFadeTail: 408 case TruncateFadeTail:
404 render_text->set_fade_tail(true); 409 render_text->set_fade_tail(true);
(...skipping 25 matching lines...) Expand all
430 render_text->set_fade_tail(true); 435 render_text->set_fade_tail(true);
431 render_text->set_fade_head(true); 436 render_text->set_fade_head(true);
432 break; 437 break;
433 } 438 }
434 439
435 // Default to left alignment unless right alignment was chosen above. 440 // Default to left alignment unless right alignment was chosen above.
436 if (!(flags & TEXT_ALIGN_RIGHT)) 441 if (!(flags & TEXT_ALIGN_RIGHT))
437 flags |= TEXT_ALIGN_LEFT; 442 flags |= TEXT_ALIGN_LEFT;
438 443
439 Rect rect = display_rect; 444 Rect rect = display_rect;
440 UpdateRenderText(rect, clipped_text, font, flags, color, render_text.get()); 445 UpdateRenderText(rect, clipped_text, font_list, flags, color,
446 render_text.get());
441 447
442 const int line_height = render_text->GetStringSize().height(); 448 const int line_height = render_text->GetStringSize().height();
443 // Center the text vertically. 449 // Center the text vertically.
444 rect += Vector2d(0, (display_rect.height() - line_height) / 2); 450 rect += Vector2d(0, (display_rect.height() - line_height) / 2);
445 rect.set_height(line_height); 451 rect.set_height(line_height);
446 render_text->SetDisplayRect(rect); 452 render_text->SetDisplayRect(rect);
447 453
448 canvas_->save(SkCanvas::kClip_SaveFlag); 454 canvas_->save(SkCanvas::kClip_SaveFlag);
449 ClipRect(display_rect); 455 ClipRect(display_rect);
450 render_text->Draw(this); 456 render_text->Draw(this);
451 canvas_->restore(); 457 canvas_->restore();
452 } 458 }
453 459
460 void Canvas::DrawFadeTruncatingString(
461 const base::string16& text,
462 TruncateFadeMode truncate_mode,
463 size_t desired_characters_to_truncate_from_head,
464 const Font& font,
465 SkColor color,
466 const Rect& display_rect) {
467 DrawFadeTruncatingStringRect(text, truncate_mode,
468 desired_characters_to_truncate_from_head,
469 FontList(font), color, display_rect);
470 }
471
454 } // namespace gfx 472 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698