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 "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 Loading... | |
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 // |DrawStringWithHaloRect| 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 Loading... | |
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 // static |
230 const Font& font, | 233 void Canvas::SizeStringInt(const base::string16& text, |
msw
2013/08/19 19:05:43
Why not define this SizeStringInt and the two GetS
Yuki
2013/08/20 15:05:47
I was struggling to remove dependency-breakage on
| |
231 SkColor color, | 234 const gfx::Font& font, |
Alexei Svitkine (slow)
2013/08/19 14:17:28
Nit: No gfx:: prefix - fix throughout all the canv
Yuki
2013/08/20 15:05:47
Done.
| |
232 const Rect& text_bounds, | 235 int* width, |
233 int line_height, | 236 int* height, |
234 int flags, | 237 int line_height, |
235 const ShadowValues& shadows) { | 238 int flags) { |
239 SizeStringInt(text, gfx::FontList(font), width, height, line_height, flags); | |
240 } | |
241 | |
242 // static | |
243 int Canvas::GetStringWidth(const base::string16& text, | |
244 const gfx::FontList& font_list) { | |
245 int width = 0, height = 0; | |
246 SizeStringInt(text, font_list, &width, &height, 0, NO_ELLIPSIS); | |
247 return width; | |
248 } | |
249 | |
250 // static | |
251 int Canvas::GetStringWidth(const base::string16& text, const gfx::Font& font) { | |
252 int width = 0, height = 0; | |
253 SizeStringInt(text, gfx::FontList(font), &width, &height, 0, NO_ELLIPSIS); | |
254 return width; | |
255 } | |
256 | |
257 void Canvas::DrawStringWithShadowsRect(const base::string16& text, | |
258 const FontList& font_list, | |
259 SkColor color, | |
260 const Rect& text_bounds, | |
261 int line_height, | |
262 int flags, | |
263 const ShadowValues& shadows) { | |
236 if (!IntersectsClipRect(text_bounds)) | 264 if (!IntersectsClipRect(text_bounds)) |
237 return; | 265 return; |
238 | 266 |
239 flags = AdjustPlatformSpecificFlags(text, flags); | 267 flags = AdjustPlatformSpecificFlags(text, flags); |
240 | 268 |
241 Rect clip_rect(text_bounds); | 269 Rect clip_rect(text_bounds); |
242 clip_rect.Inset(ShadowValue::GetMargin(shadows)); | 270 clip_rect.Inset(ShadowValue::GetMargin(shadows)); |
243 | 271 |
244 canvas_->save(SkCanvas::kClip_SaveFlag); | 272 canvas_->save(SkCanvas::kClip_SaveFlag); |
245 ClipRect(clip_rect); | 273 ClipRect(clip_rect); |
(...skipping 10 matching lines...) Expand all Loading... | |
256 | 284 |
257 if (flags & MULTI_LINE) { | 285 if (flags & MULTI_LINE) { |
258 ui::WordWrapBehavior wrap_behavior = ui::IGNORE_LONG_WORDS; | 286 ui::WordWrapBehavior wrap_behavior = ui::IGNORE_LONG_WORDS; |
259 if (flags & CHARACTER_BREAK) | 287 if (flags & CHARACTER_BREAK) |
260 wrap_behavior = ui::WRAP_LONG_WORDS; | 288 wrap_behavior = ui::WRAP_LONG_WORDS; |
261 else if (!(flags & NO_ELLIPSIS)) | 289 else if (!(flags & NO_ELLIPSIS)) |
262 wrap_behavior = ui::ELIDE_LONG_WORDS; | 290 wrap_behavior = ui::ELIDE_LONG_WORDS; |
263 | 291 |
264 std::vector<base::string16> strings; | 292 std::vector<base::string16> strings; |
265 ui::ElideRectangleText(adjusted_text, | 293 ui::ElideRectangleText(adjusted_text, |
266 font, | 294 font_list, |
267 text_bounds.width(), text_bounds.height(), | 295 text_bounds.width(), text_bounds.height(), |
268 wrap_behavior, | 296 wrap_behavior, |
269 &strings); | 297 &strings); |
270 | 298 |
271 for (size_t i = 0; i < strings.size(); i++) { | 299 for (size_t i = 0; i < strings.size(); i++) { |
272 ui::Range range = StripAcceleratorChars(flags, &strings[i]); | 300 ui::Range range = StripAcceleratorChars(flags, &strings[i]); |
273 UpdateRenderText(rect, strings[i], font, flags, color, render_text.get()); | 301 UpdateRenderText(rect, strings[i], font_list, flags, color, |
302 render_text.get()); | |
274 int line_padding = 0; | 303 int line_padding = 0; |
275 if (line_height > 0) | 304 if (line_height > 0) |
276 line_padding = line_height - render_text->GetStringSize().height(); | 305 line_padding = line_height - render_text->GetStringSize().height(); |
277 else | 306 else |
278 line_height = render_text->GetStringSize().height(); | 307 line_height = render_text->GetStringSize().height(); |
279 | 308 |
280 // TODO(msw|asvitkine): Center Windows multi-line text: crbug.com/107357 | 309 // TODO(msw|asvitkine): Center Windows multi-line text: crbug.com/107357 |
281 #if !defined(OS_WIN) | 310 #if !defined(OS_WIN) |
282 if (i == 0) { | 311 if (i == 0) { |
283 // TODO(msw|asvitkine): Support multi-line text with varied heights. | 312 // TODO(msw|asvitkine): Support multi-line text with varied heights. |
(...skipping 20 matching lines...) Expand all Loading... | |
304 if (elide_text) { | 333 if (elide_text) { |
305 render_text->SetText(adjusted_text); | 334 render_text->SetText(adjusted_text); |
306 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) { | 335 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) { |
307 render_text->set_fade_tail(true); | 336 render_text->set_fade_tail(true); |
308 elide_text = false; | 337 elide_text = false; |
309 } | 338 } |
310 } | 339 } |
311 #endif | 340 #endif |
312 | 341 |
313 if (elide_text) { | 342 if (elide_text) { |
314 ElideTextAndAdjustRange(font, | 343 ElideTextAndAdjustRange(font_list, |
315 text_bounds.width(), | 344 text_bounds.width(), |
316 &adjusted_text, | 345 &adjusted_text, |
317 &range); | 346 &range); |
318 } | 347 } |
319 | 348 |
320 UpdateRenderText(rect, adjusted_text, font, flags, color, | 349 UpdateRenderText(rect, adjusted_text, font_list, flags, color, |
321 render_text.get()); | 350 render_text.get()); |
322 | 351 |
323 const int text_height = render_text->GetStringSize().height(); | 352 const int text_height = render_text->GetStringSize().height(); |
324 // Center the text vertically. | 353 // Center the text vertically. |
325 rect += Vector2d(0, (text_bounds.height() - text_height) / 2); | 354 rect += Vector2d(0, (text_bounds.height() - text_height) / 2); |
326 rect.set_height(text_height); | 355 rect.set_height(text_height); |
327 render_text->SetDisplayRect(rect); | 356 render_text->SetDisplayRect(rect); |
328 if (range.IsValid()) | 357 if (range.IsValid()) |
329 render_text->ApplyStyle(UNDERLINE, true, range); | 358 render_text->ApplyStyle(UNDERLINE, true, range); |
330 render_text->Draw(this); | 359 render_text->Draw(this); |
331 } | 360 } |
332 | 361 |
333 canvas_->restore(); | 362 canvas_->restore(); |
334 } | 363 } |
335 | 364 |
336 void Canvas::DrawStringWithHalo(const base::string16& text, | 365 void Canvas::DrawStringWithHaloRect(const base::string16& text, |
337 const Font& font, | 366 const FontList& font_list, |
338 SkColor text_color, | 367 SkColor text_color, |
339 SkColor halo_color_in, | 368 SkColor halo_color_in, |
340 int x, int y, int w, int h, | 369 const Rect& display_rect, |
341 int flags) { | 370 int flags) { |
342 // Some callers will have semitransparent halo colors, which we don't handle | 371 // Some callers will have semitransparent halo colors, which we don't handle |
343 // (since the resulting image can have 1-bit transparency only). | 372 // (since the resulting image can have 1-bit transparency only). |
344 SkColor halo_color = SkColorSetA(halo_color_in, 0xFF); | 373 SkColor halo_color = SkColorSetA(halo_color_in, 0xFF); |
345 | 374 |
346 // Create a temporary buffer filled with the halo color. It must leave room | 375 // Create a temporary buffer filled with the halo color. It must leave room |
347 // for the 1-pixel border around the text. | 376 // for the 1-pixel border around the text. |
348 Size size(w + 2, h + 2); | 377 Size size(display_rect.width() + 2, display_rect.height() + 2); |
349 Canvas text_canvas(size, scale_factor(), true); | 378 Canvas text_canvas(size, scale_factor(), true); |
350 SkPaint bkgnd_paint; | 379 SkPaint bkgnd_paint; |
351 bkgnd_paint.setColor(halo_color); | 380 bkgnd_paint.setColor(halo_color); |
352 text_canvas.DrawRect(Rect(size), bkgnd_paint); | 381 text_canvas.DrawRect(Rect(size), bkgnd_paint); |
353 | 382 |
354 // Draw the text into the temporary buffer. This will have correct | 383 // Draw the text into the temporary buffer. This will have correct |
355 // ClearType since the background color is the same as the halo color. | 384 // 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); | 385 text_canvas.DrawStringWithFlagsRect( |
386 text, font_list, text_color, | |
387 Rect(1, 1, display_rect.width(), display_rect.height()), flags); | |
357 | 388 |
358 uint32_t halo_premul = SkPreMultiplyColor(halo_color); | 389 uint32_t halo_premul = SkPreMultiplyColor(halo_color); |
359 SkBitmap& text_bitmap = const_cast<SkBitmap&>( | 390 SkBitmap& text_bitmap = const_cast<SkBitmap&>( |
360 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(true)); | 391 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(true)); |
361 | 392 |
362 for (int cur_y = 0; cur_y < text_bitmap.height(); cur_y++) { | 393 for (int cur_y = 0; cur_y < text_bitmap.height(); cur_y++) { |
363 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); | 394 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); |
364 for (int cur_x = 0; cur_x < text_bitmap.width(); cur_x++) { | 395 for (int cur_x = 0; cur_x < text_bitmap.width(); cur_x++) { |
365 if (text_row[cur_x] == halo_premul) { | 396 if (text_row[cur_x] == halo_premul) { |
366 // This pixel was not touched by the text routines. See if it borders | 397 // 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). | 398 // a touched pixel in any of the 4 directions (not diagonally). |
368 if (!PixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) | 399 if (!PixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) |
369 text_row[cur_x] = 0; // Make transparent. | 400 text_row[cur_x] = 0; // Make transparent. |
370 } else { | 401 } else { |
371 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. | 402 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. |
372 } | 403 } |
373 } | 404 } |
374 } | 405 } |
375 | 406 |
376 // Draw the halo bitmap with blur. | 407 // Draw the halo bitmap with blur. |
377 ImageSkia text_image = ImageSkia(ImageSkiaRep(text_bitmap, | 408 ImageSkia text_image = ImageSkia(ImageSkiaRep(text_bitmap, |
378 text_canvas.scale_factor())); | 409 text_canvas.scale_factor())); |
379 DrawImageInt(text_image, x - 1, y - 1); | 410 DrawImageInt(text_image, display_rect.x() - 1, display_rect.y() - 1); |
380 } | 411 } |
381 | 412 |
382 void Canvas::DrawFadeTruncatingString( | 413 void Canvas::DrawFadeTruncatingStringRect( |
383 const base::string16& text, | 414 const base::string16& text, |
384 TruncateFadeMode truncate_mode, | 415 TruncateFadeMode truncate_mode, |
385 size_t desired_characters_to_truncate_from_head, | 416 size_t desired_characters_to_truncate_from_head, |
386 const Font& font, | 417 const FontList& font_list, |
387 SkColor color, | 418 SkColor color, |
388 const Rect& display_rect) { | 419 const Rect& display_rect) { |
389 int flags = NO_ELLIPSIS; | 420 int flags = NO_ELLIPSIS; |
390 | 421 |
391 // If the whole string fits in the destination then just draw it directly. | 422 // If the whole string fits in the destination then just draw it directly. |
392 if (GetStringWidth(text, font) <= display_rect.width()) { | 423 if (GetStringWidth(text, font_list) <= display_rect.width()) { |
393 DrawStringInt(text, font, color, display_rect.x(), display_rect.y(), | 424 DrawStringWithFlagsRect(text, font_list, color, display_rect, flags); |
394 display_rect.width(), display_rect.height(), flags); | |
395 return; | 425 return; |
396 } | 426 } |
397 | 427 |
398 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 428 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
399 base::string16 clipped_text = text; | 429 base::string16 clipped_text = text; |
400 const bool is_rtl = AdjustStringDirection(flags, &clipped_text); | 430 const bool is_rtl = AdjustStringDirection(flags, &clipped_text); |
401 | 431 |
402 switch (truncate_mode) { | 432 switch (truncate_mode) { |
403 case TruncateFadeTail: | 433 case TruncateFadeTail: |
404 render_text->set_fade_tail(true); | 434 render_text->set_fade_tail(true); |
(...skipping 25 matching lines...) Expand all Loading... | |
430 render_text->set_fade_tail(true); | 460 render_text->set_fade_tail(true); |
431 render_text->set_fade_head(true); | 461 render_text->set_fade_head(true); |
432 break; | 462 break; |
433 } | 463 } |
434 | 464 |
435 // Default to left alignment unless right alignment was chosen above. | 465 // Default to left alignment unless right alignment was chosen above. |
436 if (!(flags & TEXT_ALIGN_RIGHT)) | 466 if (!(flags & TEXT_ALIGN_RIGHT)) |
437 flags |= TEXT_ALIGN_LEFT; | 467 flags |= TEXT_ALIGN_LEFT; |
438 | 468 |
439 Rect rect = display_rect; | 469 Rect rect = display_rect; |
440 UpdateRenderText(rect, clipped_text, font, flags, color, render_text.get()); | 470 UpdateRenderText(rect, clipped_text, font_list, flags, color, |
471 render_text.get()); | |
441 | 472 |
442 const int line_height = render_text->GetStringSize().height(); | 473 const int line_height = render_text->GetStringSize().height(); |
443 // Center the text vertically. | 474 // Center the text vertically. |
444 rect += Vector2d(0, (display_rect.height() - line_height) / 2); | 475 rect += Vector2d(0, (display_rect.height() - line_height) / 2); |
445 rect.set_height(line_height); | 476 rect.set_height(line_height); |
446 render_text->SetDisplayRect(rect); | 477 render_text->SetDisplayRect(rect); |
447 | 478 |
448 canvas_->save(SkCanvas::kClip_SaveFlag); | 479 canvas_->save(SkCanvas::kClip_SaveFlag); |
449 ClipRect(display_rect); | 480 ClipRect(display_rect); |
450 render_text->Draw(this); | 481 render_text->Draw(this); |
451 canvas_->restore(); | 482 canvas_->restore(); |
452 } | 483 } |
453 | 484 |
485 void Canvas::DrawFadeTruncatingString( | |
486 const base::string16& text, | |
487 TruncateFadeMode truncate_mode, | |
488 size_t desired_characters_to_truncate_from_head, | |
489 const gfx::Font& font, | |
490 SkColor color, | |
491 const gfx::Rect& display_rect) { | |
492 DrawFadeTruncatingStringRect(text, truncate_mode, | |
493 desired_characters_to_truncate_from_head, | |
494 gfx::FontList(font), color, display_rect); | |
495 } | |
496 | |
454 } // namespace gfx | 497 } // namespace gfx |
OLD | NEW |