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

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

Issue 11535014: Replace StyleRange with BreakList; update RenderText, etc. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments. Created 7 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 | Annotate | Revision Log
« no previous file with comments | « ui/gfx/break_list_unittest.cc ('k') | ui/gfx/font.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 "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" 12 #include "ui/gfx/font.h"
13 #include "ui/gfx/font_list.h" 13 #include "ui/gfx/font_list.h"
14 #include "ui/gfx/insets.h" 14 #include "ui/gfx/insets.h"
15 #include "ui/gfx/rect.h" 15 #include "ui/gfx/rect.h"
16 #include "ui/gfx/render_text.h" 16 #include "ui/gfx/render_text.h"
17 #include "ui/gfx/shadow_value.h" 17 #include "ui/gfx/shadow_value.h"
18 #include "ui/gfx/text_utils.h" 18 #include "ui/gfx/text_utils.h"
19 19
20 namespace gfx {
21
20 namespace { 22 namespace {
21 23
22 // If necessary, wraps |text| with RTL/LTR directionality characters based on 24 // If necessary, wraps |text| with RTL/LTR directionality characters based on
23 // |flags| and |text| content. 25 // |flags| and |text| content.
24 // Returns true if the text will be rendered right-to-left. 26 // Returns true if the text will be rendered right-to-left.
25 // TODO(msw): Nix this, now that RenderTextWin supports directionality directly. 27 // TODO(msw): Nix this, now that RenderTextWin supports directionality directly.
26 bool AdjustStringDirection(int flags, string16* text) { 28 bool AdjustStringDirection(int flags, string16* text) {
27 // TODO(msw): FORCE_LTR_DIRECTIONALITY does not work for RTL text now. 29 // TODO(msw): FORCE_LTR_DIRECTIONALITY does not work for RTL text now.
28 30
29 // If the string is empty or LTR was forced, simply return false since the 31 // If the string is empty or LTR was forced, simply return false since the
30 // default RenderText directionality is already LTR. 32 // default RenderText directionality is already LTR.
31 if (text->empty() || (flags & gfx::Canvas::FORCE_LTR_DIRECTIONALITY)) 33 if (text->empty() || (flags & Canvas::FORCE_LTR_DIRECTIONALITY))
32 return false; 34 return false;
33 35
34 // If RTL is forced, apply it to the string. 36 // If RTL is forced, apply it to the string.
35 if (flags & gfx::Canvas::FORCE_RTL_DIRECTIONALITY) { 37 if (flags & Canvas::FORCE_RTL_DIRECTIONALITY) {
36 base::i18n::WrapStringWithRTLFormatting(text); 38 base::i18n::WrapStringWithRTLFormatting(text);
37 return true; 39 return true;
38 } 40 }
39 41
40 // If a direction wasn't forced but the UI language is RTL and there were 42 // If a direction wasn't forced but the UI language is RTL and there were
41 // strong RTL characters, ensure RTL is applied. 43 // strong RTL characters, ensure RTL is applied.
42 if (base::i18n::IsRTL() && base::i18n::StringContainsStrongRTLChars(*text)) { 44 if (base::i18n::IsRTL() && base::i18n::StringContainsStrongRTLChars(*text)) {
43 base::i18n::WrapStringWithRTLFormatting(text); 45 base::i18n::WrapStringWithRTLFormatting(text);
44 return true; 46 return true;
45 } 47 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 *bitmap.getAddr32(x, y + 1) != halo_color && 79 *bitmap.getAddr32(x, y + 1) != halo_color &&
78 *bitmap.getAddr32(x, y + 1) != 0) 80 *bitmap.getAddr32(x, y + 1) != 0)
79 return true; // Touched pixel below. 81 return true; // Touched pixel below.
80 return false; 82 return false;
81 } 83 }
82 84
83 // Strips accelerator character prefixes in |text| if needed, based on |flags|. 85 // Strips accelerator character prefixes in |text| if needed, based on |flags|.
84 // Returns a range in |text| to underline or ui::Range::InvalidRange() if 86 // Returns a range in |text| to underline or ui::Range::InvalidRange() if
85 // underlining is not needed. 87 // underlining is not needed.
86 ui::Range StripAcceleratorChars(int flags, string16* text) { 88 ui::Range StripAcceleratorChars(int flags, string16* text) {
87 if (flags & (gfx::Canvas::SHOW_PREFIX | gfx::Canvas::HIDE_PREFIX)) { 89 if (flags & (Canvas::SHOW_PREFIX | Canvas::HIDE_PREFIX)) {
88 int char_pos = -1; 90 int char_pos = -1;
89 int char_span = 0; 91 int char_span = 0;
90 *text = gfx::RemoveAcceleratorChar(*text, '&', &char_pos, &char_span); 92 *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span);
91 if ((flags & gfx::Canvas::SHOW_PREFIX) && char_pos != -1) 93 if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1)
92 return ui::Range(char_pos, char_pos + char_span); 94 return ui::Range(char_pos, char_pos + char_span);
93 } 95 }
94 return ui::Range::InvalidRange(); 96 return ui::Range::InvalidRange();
95 } 97 }
96 98
97 // Elides |text| and adjusts |range| appropriately. If eliding causes |range| 99 // Elides |text| and adjusts |range| appropriately. If eliding causes |range|
98 // to no longer point to the same character in |text|, |range| is made invalid. 100 // to no longer point to the same character in |text|, |range| is made invalid.
99 void ElideTextAndAdjustRange(const gfx::Font& font, 101 void ElideTextAndAdjustRange(const Font& font,
100 int width, 102 int width,
101 string16* text, 103 string16* text,
102 ui::Range* range) { 104 ui::Range* range) {
103 const char16 start_char = (range->IsValid() ? text->at(range->start()) : 0); 105 const char16 start_char = (range->IsValid() ? text->at(range->start()) : 0);
104 *text = ui::ElideText(*text, font, width, ui::ELIDE_AT_END); 106 *text = ui::ElideText(*text, font, width, ui::ELIDE_AT_END);
105 if (!range->IsValid()) 107 if (!range->IsValid())
106 return; 108 return;
107 if (range->start() >= text->length() || 109 if (range->start() >= text->length() ||
108 text->at(range->start()) != start_char) { 110 text->at(range->start()) != start_char) {
109 *range = ui::Range::InvalidRange(); 111 *range = ui::Range::InvalidRange();
110 } 112 }
111 } 113 }
112 114
113 // Updates |render_text| from the specified parameters. 115 // Updates |render_text| from the specified parameters.
114 void UpdateRenderText(const gfx::Rect& rect, 116 void UpdateRenderText(const Rect& rect,
115 const string16& text, 117 const string16& text,
116 const gfx::Font& font, 118 const Font& font,
117 int flags, 119 int flags,
118 SkColor color, 120 SkColor color,
119 gfx::RenderText* render_text) { 121 RenderText* render_text) {
120 render_text->SetFont(font); 122 render_text->SetFont(font);
121 render_text->SetText(text); 123 render_text->SetText(text);
122 render_text->SetCursorEnabled(false); 124 render_text->SetCursorEnabled(false);
123 125
124 gfx::Rect display_rect = rect; 126 Rect display_rect = rect;
125 display_rect.set_height(font.GetHeight()); 127 display_rect.set_height(font.GetHeight());
126 render_text->SetDisplayRect(display_rect); 128 render_text->SetDisplayRect(display_rect);
127 129
128 // 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,
129 // if not specified. 131 // if not specified.
130 if (!(flags & (gfx::Canvas::TEXT_ALIGN_CENTER | 132 if (!(flags & (Canvas::TEXT_ALIGN_CENTER |
131 gfx::Canvas::TEXT_ALIGN_RIGHT | 133 Canvas::TEXT_ALIGN_RIGHT |
132 gfx::Canvas::TEXT_ALIGN_LEFT))) { 134 Canvas::TEXT_ALIGN_LEFT))) {
133 flags |= gfx::Canvas::DefaultCanvasTextAlignment(); 135 flags |= Canvas::DefaultCanvasTextAlignment();
134 } 136 }
135 137
136 if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) 138 if (flags & Canvas::TEXT_ALIGN_RIGHT)
137 render_text->SetHorizontalAlignment(gfx::ALIGN_RIGHT); 139 render_text->SetHorizontalAlignment(ALIGN_RIGHT);
138 else if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) 140 else if (flags & Canvas::TEXT_ALIGN_CENTER)
139 render_text->SetHorizontalAlignment(gfx::ALIGN_CENTER); 141 render_text->SetHorizontalAlignment(ALIGN_CENTER);
140 else 142 else
141 render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT); 143 render_text->SetHorizontalAlignment(ALIGN_LEFT);
142 144
143 if (flags & gfx::Canvas::NO_SUBPIXEL_RENDERING) 145 if (flags & Canvas::NO_SUBPIXEL_RENDERING)
144 render_text->set_background_is_transparent(true); 146 render_text->set_background_is_transparent(true);
145 147
146 gfx::StyleRange style; 148 render_text->SetColor(color);
147 style.foreground = color; 149 render_text->SetStyle(BOLD, (font.GetStyle() & Font::BOLD) != 0);
148 style.font_style = font.GetStyle(); 150 render_text->SetStyle(ITALIC, (font.GetStyle() & Font::ITALIC) != 0);
149 if (font.GetStyle() & gfx::Font::UNDERLINED) 151 render_text->SetStyle(UNDERLINE, (font.GetStyle() & Font::UNDERLINE) != 0);
150 style.underline = true;
151 render_text->set_default_style(style);
152 render_text->ApplyDefaultStyle();
153 }
154
155 // Adds an underline style to |render_text| over |range|.
156 void ApplyUnderlineStyle(const ui::Range& range, gfx::RenderText* render_text) {
157 gfx::StyleRange style = render_text->default_style();
158 if (range.IsValid() && !style.underline) {
159 style.range = range;
160 style.underline = true;
161 render_text->ApplyStyleRange(style);
162 }
163 } 152 }
164 153
165 // Returns updated |flags| to match platform-specific expected behavior. 154 // Returns updated |flags| to match platform-specific expected behavior.
166 int AdjustPlatformSpecificFlags(const string16& text, int flags) { 155 int AdjustPlatformSpecificFlags(const string16& text, int flags) {
167 #if defined(OS_LINUX) 156 #if defined(OS_LINUX)
168 // TODO(asvitkine): ash/tooltips/tooltip_controller.cc adds \n's to the string 157 // TODO(asvitkine): ash/tooltips/tooltip_controller.cc adds \n's to the string
169 // without passing MULTI_LINE. 158 // without passing MULTI_LINE.
170 if (text.find('\n') != string16::npos) 159 if (text.find('\n') != string16::npos)
171 flags |= gfx::Canvas::MULTI_LINE; 160 flags |= Canvas::MULTI_LINE;
172 #endif 161 #endif
173 162
174 return flags; 163 return flags;
175 } 164 }
176 165
177 } // namespace 166 } // namespace
178 167
179 namespace gfx {
180
181 // static 168 // static
182 void Canvas::SizeStringInt(const string16& text, 169 void Canvas::SizeStringInt(const string16& text,
183 const gfx::Font& font, 170 const Font& font,
184 int* width, int* height, 171 int* width, int* height,
185 int flags) { 172 int flags) {
186 DCHECK_GE(*width, 0); 173 DCHECK_GE(*width, 0);
187 DCHECK_GE(*height, 0); 174 DCHECK_GE(*height, 0);
188 175
189 flags = AdjustPlatformSpecificFlags(text, flags); 176 flags = AdjustPlatformSpecificFlags(text, flags);
190 177
191 string16 adjusted_text = text; 178 string16 adjusted_text = text;
192 #if defined(OS_WIN) 179 #if defined(OS_WIN)
193 AdjustStringDirection(flags, &adjusted_text); 180 AdjustStringDirection(flags, &adjusted_text);
194 #endif 181 #endif
195 182
196 if ((flags & MULTI_LINE) && *width != 0) { 183 if ((flags & MULTI_LINE) && *width != 0) {
197 ui::WordWrapBehavior wrap_behavior = ui::TRUNCATE_LONG_WORDS; 184 ui::WordWrapBehavior wrap_behavior = ui::TRUNCATE_LONG_WORDS;
198 if (flags & CHARACTER_BREAK) 185 if (flags & CHARACTER_BREAK)
199 wrap_behavior = ui::WRAP_LONG_WORDS; 186 wrap_behavior = ui::WRAP_LONG_WORDS;
200 else if (!(flags & NO_ELLIPSIS)) 187 else if (!(flags & NO_ELLIPSIS))
201 wrap_behavior = ui::ELIDE_LONG_WORDS; 188 wrap_behavior = ui::ELIDE_LONG_WORDS;
202 189
203 gfx::Rect rect(*width, INT_MAX); 190 Rect rect(*width, INT_MAX);
204 std::vector<string16> strings; 191 std::vector<string16> strings;
205 ui::ElideRectangleText(adjusted_text, font, rect.width(), rect.height(), 192 ui::ElideRectangleText(adjusted_text, font, rect.width(), rect.height(),
206 wrap_behavior, &strings); 193 wrap_behavior, &strings);
207 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 194 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
208 UpdateRenderText(rect, string16(), font, flags, 0, render_text.get()); 195 UpdateRenderText(rect, string16(), font, flags, 0, render_text.get());
209 196
210 int h = 0; 197 int h = 0;
211 int w = 0; 198 int w = 0;
212 for (size_t i = 0; i < strings.size(); ++i) { 199 for (size_t i = 0; i < strings.size(); ++i) {
213 StripAcceleratorChars(flags, &strings[i]); 200 StripAcceleratorChars(flags, &strings[i]);
214 render_text->SetText(strings[i]); 201 render_text->SetText(strings[i]);
215 const Size string_size = render_text->GetStringSize(); 202 const Size string_size = render_text->GetStringSize();
216 w = std::max(w, string_size.width()); 203 w = std::max(w, string_size.width());
217 h += string_size.height(); 204 h += string_size.height();
218 } 205 }
219 *width = w; 206 *width = w;
220 *height = h; 207 *height = h;
221 } else { 208 } else {
222 // If the string is too long, the call by |RenderTextWin| to |ScriptShape()| 209 // If the string is too long, the call by |RenderTextWin| to |ScriptShape()|
223 // will inexplicably fail with result E_INVALIDARG. Guard against this. 210 // will inexplicably fail with result E_INVALIDARG. Guard against this.
224 const size_t kMaxRenderTextLength = 5000; 211 const size_t kMaxRenderTextLength = 5000;
225 if (adjusted_text.length() >= kMaxRenderTextLength) { 212 if (adjusted_text.length() >= kMaxRenderTextLength) {
226 *width = adjusted_text.length() * font.GetAverageCharacterWidth(); 213 *width = adjusted_text.length() * font.GetAverageCharacterWidth();
227 *height = font.GetHeight(); 214 *height = font.GetHeight();
228 } else { 215 } else {
229 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 216 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
230 gfx::Rect rect(*width, *height); 217 Rect rect(*width, *height);
231 StripAcceleratorChars(flags, &adjusted_text); 218 StripAcceleratorChars(flags, &adjusted_text);
232 UpdateRenderText(rect, adjusted_text, font, flags, 0, render_text.get()); 219 UpdateRenderText(rect, adjusted_text, font, flags, 0, render_text.get());
233 const Size string_size = render_text->GetStringSize(); 220 const Size string_size = render_text->GetStringSize();
234 *width = string_size.width(); 221 *width = string_size.width();
235 *height = string_size.height(); 222 *height = string_size.height();
236 } 223 }
237 } 224 }
238 } 225 }
239 226
240 void Canvas::DrawStringWithShadows(const string16& text, 227 void Canvas::DrawStringWithShadows(const string16& text,
241 const gfx::Font& font, 228 const Font& font,
242 SkColor color, 229 SkColor color,
243 const gfx::Rect& text_bounds, 230 const Rect& text_bounds,
244 int flags, 231 int flags,
245 const ShadowValues& shadows) { 232 const ShadowValues& shadows) {
246 if (!IntersectsClipRect(text_bounds)) 233 if (!IntersectsClipRect(text_bounds))
247 return; 234 return;
248 235
249 flags = AdjustPlatformSpecificFlags(text, flags); 236 flags = AdjustPlatformSpecificFlags(text, flags);
250 237
251 gfx::Rect clip_rect(text_bounds); 238 Rect clip_rect(text_bounds);
252 clip_rect.Inset(ShadowValue::GetMargin(shadows)); 239 clip_rect.Inset(ShadowValue::GetMargin(shadows));
253 240
254 canvas_->save(SkCanvas::kClip_SaveFlag); 241 canvas_->save(SkCanvas::kClip_SaveFlag);
255 ClipRect(clip_rect); 242 ClipRect(clip_rect);
256 243
257 gfx::Rect rect(text_bounds); 244 Rect rect(text_bounds);
258 string16 adjusted_text = text; 245 string16 adjusted_text = text;
259 246
260 #if defined(OS_WIN) 247 #if defined(OS_WIN)
261 AdjustStringDirection(flags, &adjusted_text); 248 AdjustStringDirection(flags, &adjusted_text);
262 #endif 249 #endif
263 250
264 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 251 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
265 render_text->SetTextShadows(shadows); 252 render_text->SetTextShadows(shadows);
266 253
267 if (flags & MULTI_LINE) { 254 if (flags & MULTI_LINE) {
(...skipping 13 matching lines...) Expand all
281 for (size_t i = 0; i < strings.size(); i++) { 268 for (size_t i = 0; i < strings.size(); i++) {
282 ui::Range range = StripAcceleratorChars(flags, &strings[i]); 269 ui::Range range = StripAcceleratorChars(flags, &strings[i]);
283 UpdateRenderText(rect, strings[i], font, flags, color, render_text.get()); 270 UpdateRenderText(rect, strings[i], font, flags, color, render_text.get());
284 const int line_height = render_text->GetStringSize().height(); 271 const int line_height = render_text->GetStringSize().height();
285 272
286 // TODO(msw|asvitkine): Center Windows multi-line text: crbug.com/107357 273 // TODO(msw|asvitkine): Center Windows multi-line text: crbug.com/107357
287 #if !defined(OS_WIN) 274 #if !defined(OS_WIN)
288 if (i == 0) { 275 if (i == 0) {
289 // TODO(msw|asvitkine): Support multi-line text with varied heights. 276 // TODO(msw|asvitkine): Support multi-line text with varied heights.
290 const int aggregate_height = strings.size() * line_height; 277 const int aggregate_height = strings.size() * line_height;
291 rect += gfx::Vector2d(0, (text_bounds.height() - aggregate_height) / 2); 278 rect += Vector2d(0, (text_bounds.height() - aggregate_height) / 2);
292 } 279 }
293 #endif 280 #endif
294 281
295 rect.set_height(line_height); 282 rect.set_height(line_height);
296 283
297 ApplyUnderlineStyle(range, render_text.get()); 284 if (range.IsValid())
285 render_text->ApplyStyle(UNDERLINE, true, range);
298 render_text->SetDisplayRect(rect); 286 render_text->SetDisplayRect(rect);
299 render_text->Draw(this); 287 render_text->Draw(this);
300 rect += gfx::Vector2d(0, line_height); 288 rect += Vector2d(0, line_height);
301 } 289 }
302 } else { 290 } else {
303 ui::Range range = StripAcceleratorChars(flags, &adjusted_text); 291 ui::Range range = StripAcceleratorChars(flags, &adjusted_text);
304 bool elide_text = ((flags & NO_ELLIPSIS) == 0); 292 bool elide_text = ((flags & NO_ELLIPSIS) == 0);
305 293
306 #if defined(OS_LINUX) 294 #if defined(OS_LINUX)
307 // On Linux, eliding really means fading the end of the string. But only 295 // On Linux, eliding really means fading the end of the string. But only
308 // for LTR text. RTL text is still elided (on the left) with "...". 296 // for LTR text. RTL text is still elided (on the left) with "...".
309 if (elide_text) { 297 if (elide_text) {
310 render_text->SetText(adjusted_text); 298 render_text->SetText(adjusted_text);
311 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) { 299 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) {
312 render_text->set_fade_tail(true); 300 render_text->set_fade_tail(true);
313 elide_text = false; 301 elide_text = false;
314 } 302 }
315 } 303 }
316 #endif 304 #endif
317 305
318 if (elide_text) { 306 if (elide_text) {
319 ElideTextAndAdjustRange(font, 307 ElideTextAndAdjustRange(font,
320 text_bounds.width(), 308 text_bounds.width(),
321 &adjusted_text, 309 &adjusted_text,
322 &range); 310 &range);
323 } 311 }
324 312
325 UpdateRenderText(rect, adjusted_text, font, flags, color, 313 UpdateRenderText(rect, adjusted_text, font, flags, color,
326 render_text.get()); 314 render_text.get());
327 315
328 const int line_height = render_text->GetStringSize().height(); 316 const int line_height = render_text->GetStringSize().height();
329 // Center the text vertically. 317 // Center the text vertically.
330 rect += gfx::Vector2d(0, (text_bounds.height() - line_height) / 2); 318 rect += Vector2d(0, (text_bounds.height() - line_height) / 2);
331 rect.set_height(line_height); 319 rect.set_height(line_height);
332 render_text->SetDisplayRect(rect); 320 render_text->SetDisplayRect(rect);
333 321 if (range.IsValid())
334 ApplyUnderlineStyle(range, render_text.get()); 322 render_text->ApplyStyle(UNDERLINE, true, range);
335 render_text->Draw(this); 323 render_text->Draw(this);
336 } 324 }
337 325
338 canvas_->restore(); 326 canvas_->restore();
339 } 327 }
340 328
341 void Canvas::DrawStringWithHalo(const string16& text, 329 void Canvas::DrawStringWithHalo(const string16& text,
342 const gfx::Font& font, 330 const Font& font,
343 SkColor text_color, 331 SkColor text_color,
344 SkColor halo_color_in, 332 SkColor halo_color_in,
345 int x, int y, int w, int h, 333 int x, int y, int w, int h,
346 int flags) { 334 int flags) {
347 // Some callers will have semitransparent halo colors, which we don't handle 335 // Some callers will have semitransparent halo colors, which we don't handle
348 // (since the resulting image can have 1-bit transparency only). 336 // (since the resulting image can have 1-bit transparency only).
349 SkColor halo_color = SkColorSetA(halo_color_in, 0xFF); 337 SkColor halo_color = SkColorSetA(halo_color_in, 0xFF);
350 338
351 // Create a temporary buffer filled with the halo color. It must leave room 339 // Create a temporary buffer filled with the halo color. It must leave room
352 // for the 1-pixel border around the text. 340 // for the 1-pixel border around the text.
353 Size size(w + 2, h + 2); 341 Size size(w + 2, h + 2);
354 Canvas text_canvas(size, scale_factor(), true); 342 Canvas text_canvas(size, scale_factor(), true);
355 SkPaint bkgnd_paint; 343 SkPaint bkgnd_paint;
356 bkgnd_paint.setColor(halo_color); 344 bkgnd_paint.setColor(halo_color);
357 text_canvas.DrawRect(gfx::Rect(size), bkgnd_paint); 345 text_canvas.DrawRect(Rect(size), bkgnd_paint);
358 346
359 // Draw the text into the temporary buffer. This will have correct 347 // Draw the text into the temporary buffer. This will have correct
360 // ClearType since the background color is the same as the halo color. 348 // ClearType since the background color is the same as the halo color.
361 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); 349 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags);
362 350
363 uint32_t halo_premul = SkPreMultiplyColor(halo_color); 351 uint32_t halo_premul = SkPreMultiplyColor(halo_color);
364 SkBitmap& text_bitmap = const_cast<SkBitmap&>( 352 SkBitmap& text_bitmap = const_cast<SkBitmap&>(
365 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(true)); 353 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(true));
366 354
367 for (int cur_y = 0; cur_y < text_bitmap.height(); cur_y++) { 355 for (int cur_y = 0; cur_y < text_bitmap.height(); cur_y++) {
368 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); 356 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y);
369 for (int cur_x = 0; cur_x < text_bitmap.width(); cur_x++) { 357 for (int cur_x = 0; cur_x < text_bitmap.width(); cur_x++) {
370 if (text_row[cur_x] == halo_premul) { 358 if (text_row[cur_x] == halo_premul) {
371 // This pixel was not touched by the text routines. See if it borders 359 // This pixel was not touched by the text routines. See if it borders
372 // a touched pixel in any of the 4 directions (not diagonally). 360 // a touched pixel in any of the 4 directions (not diagonally).
373 if (!PixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) 361 if (!PixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul))
374 text_row[cur_x] = 0; // Make transparent. 362 text_row[cur_x] = 0; // Make transparent.
375 } else { 363 } else {
376 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. 364 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque.
377 } 365 }
378 } 366 }
379 } 367 }
380 368
381 // Draw the halo bitmap with blur. 369 // Draw the halo bitmap with blur.
382 gfx::ImageSkia text_image = gfx::ImageSkia(gfx::ImageSkiaRep(text_bitmap, 370 ImageSkia text_image = ImageSkia(ImageSkiaRep(text_bitmap,
383 text_canvas.scale_factor())); 371 text_canvas.scale_factor()));
384 DrawImageInt(text_image, x - 1, y - 1); 372 DrawImageInt(text_image, x - 1, y - 1);
385 } 373 }
386 374
387 void Canvas::DrawFadeTruncatingString( 375 void Canvas::DrawFadeTruncatingString(
388 const string16& text, 376 const string16& text,
389 TruncateFadeMode truncate_mode, 377 TruncateFadeMode truncate_mode,
390 size_t desired_characters_to_truncate_from_head, 378 size_t desired_characters_to_truncate_from_head,
391 const gfx::Font& font, 379 const Font& font,
392 SkColor color, 380 SkColor color,
393 const gfx::Rect& display_rect) { 381 const Rect& display_rect) {
394 int flags = NO_ELLIPSIS; 382 int flags = NO_ELLIPSIS;
395 383
396 // If the whole string fits in the destination then just draw it directly. 384 // If the whole string fits in the destination then just draw it directly.
397 if (GetStringWidth(text, font) <= display_rect.width()) { 385 if (GetStringWidth(text, font) <= display_rect.width()) {
398 DrawStringInt(text, font, color, display_rect.x(), display_rect.y(), 386 DrawStringInt(text, font, color, display_rect.x(), display_rect.y(),
399 display_rect.width(), display_rect.height(), flags); 387 display_rect.width(), display_rect.height(), flags);
400 return; 388 return;
401 } 389 }
402 390
403 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 391 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
(...skipping 30 matching lines...) Expand all
434 422
435 render_text->set_fade_tail(true); 423 render_text->set_fade_tail(true);
436 render_text->set_fade_head(true); 424 render_text->set_fade_head(true);
437 break; 425 break;
438 } 426 }
439 427
440 // Default to left alignment unless right alignment was chosen above. 428 // Default to left alignment unless right alignment was chosen above.
441 if (!(flags & TEXT_ALIGN_RIGHT)) 429 if (!(flags & TEXT_ALIGN_RIGHT))
442 flags |= TEXT_ALIGN_LEFT; 430 flags |= TEXT_ALIGN_LEFT;
443 431
444 gfx::Rect rect = display_rect; 432 Rect rect = display_rect;
445 UpdateRenderText(rect, clipped_text, font, flags, color, render_text.get()); 433 UpdateRenderText(rect, clipped_text, font, flags, color, render_text.get());
446 434
447 const int line_height = render_text->GetStringSize().height(); 435 const int line_height = render_text->GetStringSize().height();
448 // Center the text vertically. 436 // Center the text vertically.
449 rect += gfx::Vector2d(0, (display_rect.height() - line_height) / 2); 437 rect += Vector2d(0, (display_rect.height() - line_height) / 2);
450 rect.set_height(line_height); 438 rect.set_height(line_height);
451 render_text->SetDisplayRect(rect); 439 render_text->SetDisplayRect(rect);
452 440
453 canvas_->save(SkCanvas::kClip_SaveFlag); 441 canvas_->save(SkCanvas::kClip_SaveFlag);
454 ClipRect(display_rect); 442 ClipRect(display_rect);
455 render_text->Draw(this); 443 render_text->Draw(this);
456 canvas_->restore(); 444 canvas_->restore();
457 } 445 }
458 446
459 } // namespace gfx 447 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/break_list_unittest.cc ('k') | ui/gfx/font.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698