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

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

Issue 10807082: Add RenderText DirectionalityMode enum and support; etc. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update and expand on unit tests. Created 8 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
« no previous file with comments | « no previous file | ui/gfx/render_text.h » ('j') | ui/gfx/render_text_linux.cc » ('J')
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/skia_util.h" 18 #include "ui/gfx/skia_util.h"
19 19
20 namespace { 20 namespace {
21 21
22 // If necessary, wraps |text| with RTL/LTR directionality characters based on 22 // If necessary, force RTL/LTR base directionality.
23 // |flags| and |text| content. 23 // Returns true if the text will be rendered with an RTL base direction.
24 // Returns true if the text will be rendered right-to-left. 24 bool AdjustStringDirection(int flags,
25 // TODO(msw): Nix this, now that RenderTextWin supports directionality directly. 25 const string16& text,
26 bool AdjustStringDirection(int flags, string16* text) { 26 gfx::RenderText* render_text) {
27 // TODO(msw): FORCE_LTR_DIRECTIONALITY does not work for RTL text now. 27 if (flags & gfx::Canvas::FORCE_LTR_DIRECTIONALITY)
28 28 render_text->SetDirectionalityMode(gfx::DIRECTIONALITY_FORCE_LTR);
29 // If the string is empty or LTR was forced, simply return false since the 29 else if (flags & gfx::Canvas::FORCE_RTL_DIRECTIONALITY)
30 // default RenderText directionality is already LTR. 30 render_text->SetDirectionalityMode(gfx::DIRECTIONALITY_FORCE_RTL);
31 if (text->empty() || (flags & gfx::Canvas::FORCE_LTR_DIRECTIONALITY))
32 return false;
33
34 // If RTL is forced, apply it to the string.
35 if (flags & gfx::Canvas::FORCE_RTL_DIRECTIONALITY) {
36 base::i18n::WrapStringWithRTLFormatting(text);
37 return true;
38 }
39 31
40 // If a direction wasn't forced but the UI language is RTL and there were 32 // If a direction wasn't forced but the UI language is RTL and there were
41 // strong RTL characters, ensure RTL is applied. 33 // strong RTL characters, ensure RTL is applied.
42 if (base::i18n::IsRTL() && base::i18n::StringContainsStrongRTLChars(*text)) { 34 if (base::i18n::IsRTL() && base::i18n::StringContainsStrongRTLChars(text))
43 base::i18n::WrapStringWithRTLFormatting(text); 35 render_text->SetDirectionalityMode(gfx::DIRECTIONALITY_FORCE_RTL);
xji 2012/07/30 18:32:16 this is DIRECTIONALITY_FROM_UI. we probably shoul
msw 2012/07/31 03:03:06 Changed to DIRECTIONALITY_FROM_UI for now (to avoi
xji 2012/07/31 23:03:25 are we already introducing behavior changes in win
msw 2012/08/01 17:30:10 Done. I made the recommended change (which amounts
44 return true;
45 }
46 36
47 // In the default case, the string should be rendered as LTR. RenderText's 37 return render_text->GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
48 // default directionality is LTR, so the text doesn't need to be wrapped.
49 // Note that individual runs within the string may still be rendered RTL
50 // (which will be the case for RTL text under non-RTL locales, since under RTL
51 // locales it will be handled by the if statement above).
52 return false;
53 } 38 }
54 39
55 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If 40 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If
56 // any of them are not the halo color, returns true. This defines the halo of 41 // any of them are not the halo color, returns true. This defines the halo of
57 // pixels that will appear around the text. Note that we have to check each 42 // pixels that will appear around the text. Note that we have to check each
58 // pixel against both the halo color and transparent since |DrawStringWithHalo| 43 // pixel against both the halo color and transparent since |DrawStringWithHalo|
59 // will modify the bitmap as it goes, and cleared pixels shouldn't count as 44 // will modify the bitmap as it goes, and cleared pixels shouldn't count as
60 // changed. 45 // changed.
61 bool PixelShouldGetHalo(const SkBitmap& bitmap, 46 bool PixelShouldGetHalo(const SkBitmap& bitmap,
62 int x, int y, 47 int x, int y,
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 void Canvas::SizeStringInt(const string16& text, 181 void Canvas::SizeStringInt(const string16& text,
197 const gfx::Font& font, 182 const gfx::Font& font,
198 int* width, int* height, 183 int* width, int* height,
199 int flags) { 184 int flags) {
200 DCHECK_GE(*width, 0); 185 DCHECK_GE(*width, 0);
201 DCHECK_GE(*height, 0); 186 DCHECK_GE(*height, 0);
202 187
203 flags = AdjustPlatformSpecificFlags(text, flags); 188 flags = AdjustPlatformSpecificFlags(text, flags);
204 189
205 string16 adjusted_text = text; 190 string16 adjusted_text = text;
191 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
192
206 #if defined(OS_WIN) 193 #if defined(OS_WIN)
207 AdjustStringDirection(flags, &adjusted_text); 194 AdjustStringDirection(flags, adjusted_text, render_text.get());
208 #endif 195 #endif
209 196
210 if ((flags & MULTI_LINE) && *width != 0) { 197 if ((flags & MULTI_LINE) && *width != 0) {
211 ui::WordWrapBehavior wrap_behavior = ui::TRUNCATE_LONG_WORDS; 198 ui::WordWrapBehavior wrap_behavior = ui::TRUNCATE_LONG_WORDS;
212 if (flags & CHARACTER_BREAK) 199 if (flags & CHARACTER_BREAK)
213 wrap_behavior = ui::WRAP_LONG_WORDS; 200 wrap_behavior = ui::WRAP_LONG_WORDS;
214 else if (!(flags & NO_ELLIPSIS)) 201 else if (!(flags & NO_ELLIPSIS))
215 wrap_behavior = ui::ELIDE_LONG_WORDS; 202 wrap_behavior = ui::ELIDE_LONG_WORDS;
216 203
217 gfx::Rect rect(*width, INT_MAX); 204 gfx::Rect rect(*width, INT_MAX);
218 std::vector<string16> strings; 205 std::vector<string16> strings;
219 ui::ElideRectangleText(adjusted_text, font, rect.width(), rect.height(), 206 ui::ElideRectangleText(adjusted_text, font, rect.width(), rect.height(),
220 wrap_behavior, &strings); 207 wrap_behavior, &strings);
221 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
222 UpdateRenderText(rect, string16(), font, flags, 0, render_text.get()); 208 UpdateRenderText(rect, string16(), font, flags, 0, render_text.get());
223 209
224 int h = 0; 210 int h = 0;
225 int w = 0; 211 int w = 0;
226 for (size_t i = 0; i < strings.size(); ++i) { 212 for (size_t i = 0; i < strings.size(); ++i) {
227 StripAcceleratorChars(flags, &strings[i]); 213 StripAcceleratorChars(flags, &strings[i]);
228 render_text->SetText(strings[i]); 214 render_text->SetText(strings[i]);
229 const Size string_size = render_text->GetStringSize(); 215 const Size string_size = render_text->GetStringSize();
230 w = std::max(w, string_size.width()); 216 w = std::max(w, string_size.width());
231 h += string_size.height(); 217 h += string_size.height();
232 } 218 }
233 *width = w; 219 *width = w;
234 *height = h; 220 *height = h;
235 } else { 221 } else {
236 // If the string is too long, the call by |RenderTextWin| to |ScriptShape()| 222 // If the string is too long, the call by |RenderTextWin| to |ScriptShape()|
237 // will inexplicably fail with result E_INVALIDARG. Guard against this. 223 // will inexplicably fail with result E_INVALIDARG. Guard against this.
238 const size_t kMaxRenderTextLength = 5000; 224 const size_t kMaxRenderTextLength = 5000;
239 if (adjusted_text.length() >= kMaxRenderTextLength) { 225 if (adjusted_text.length() >= kMaxRenderTextLength) {
240 *width = adjusted_text.length() * font.GetAverageCharacterWidth(); 226 *width = adjusted_text.length() * font.GetAverageCharacterWidth();
241 *height = font.GetHeight(); 227 *height = font.GetHeight();
242 } else { 228 } else {
243 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
244 gfx::Rect rect(*width, *height); 229 gfx::Rect rect(*width, *height);
245 StripAcceleratorChars(flags, &adjusted_text); 230 StripAcceleratorChars(flags, &adjusted_text);
246 UpdateRenderText(rect, adjusted_text, font, flags, 0, render_text.get()); 231 UpdateRenderText(rect, adjusted_text, font, flags, 0, render_text.get());
247 const Size string_size = render_text->GetStringSize(); 232 const Size string_size = render_text->GetStringSize();
248 *width = string_size.width(); 233 *width = string_size.width();
249 *height = string_size.height(); 234 *height = string_size.height();
250 } 235 }
251 } 236 }
252 } 237 }
253 238
(...skipping 19 matching lines...) Expand all
273 258
274 gfx::Rect clip_rect(text_bounds); 259 gfx::Rect clip_rect(text_bounds);
275 clip_rect.Inset(ShadowValue::GetMargin(shadows)); 260 clip_rect.Inset(ShadowValue::GetMargin(shadows));
276 261
277 canvas_->save(SkCanvas::kClip_SaveFlag); 262 canvas_->save(SkCanvas::kClip_SaveFlag);
278 ClipRect(clip_rect); 263 ClipRect(clip_rect);
279 264
280 gfx::Rect rect(text_bounds); 265 gfx::Rect rect(text_bounds);
281 string16 adjusted_text = text; 266 string16 adjusted_text = text;
282 267
283 #if defined(OS_WIN)
284 AdjustStringDirection(flags, &adjusted_text);
285 #endif
286
287 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 268 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
288 render_text->SetTextShadows(shadows); 269 render_text->SetTextShadows(shadows);
289 270
271 #if defined(OS_WIN)
272 AdjustStringDirection(flags, adjusted_text, render_text.get());
273 #endif
274
290 if (flags & MULTI_LINE) { 275 if (flags & MULTI_LINE) {
291 ui::WordWrapBehavior wrap_behavior = ui::IGNORE_LONG_WORDS; 276 ui::WordWrapBehavior wrap_behavior = ui::IGNORE_LONG_WORDS;
292 if (flags & CHARACTER_BREAK) 277 if (flags & CHARACTER_BREAK)
293 wrap_behavior = ui::WRAP_LONG_WORDS; 278 wrap_behavior = ui::WRAP_LONG_WORDS;
294 else if (!(flags & NO_ELLIPSIS)) 279 else if (!(flags & NO_ELLIPSIS))
295 wrap_behavior = ui::ELIDE_LONG_WORDS; 280 wrap_behavior = ui::ELIDE_LONG_WORDS;
296 281
297 std::vector<string16> strings; 282 std::vector<string16> strings;
298 ui::ElideRectangleText(adjusted_text, 283 ui::ElideRectangleText(adjusted_text,
299 font, 284 font,
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 401
417 // If the whole string fits in the destination then just draw it directly. 402 // If the whole string fits in the destination then just draw it directly.
418 if (GetStringWidth(text, font) <= display_rect.width()) { 403 if (GetStringWidth(text, font) <= display_rect.width()) {
419 DrawStringInt(text, font, color, display_rect.x(), display_rect.y(), 404 DrawStringInt(text, font, color, display_rect.x(), display_rect.y(),
420 display_rect.width(), display_rect.height(), flags); 405 display_rect.width(), display_rect.height(), flags);
421 return; 406 return;
422 } 407 }
423 408
424 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 409 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
425 string16 clipped_text = text; 410 string16 clipped_text = text;
426 const bool is_rtl = AdjustStringDirection(flags, &clipped_text); 411 const bool is_rtl =
412 AdjustStringDirection(flags, clipped_text, render_text.get());
427 413
428 switch (truncate_mode) { 414 switch (truncate_mode) {
429 case TruncateFadeTail: 415 case TruncateFadeTail:
430 render_text->set_fade_tail(true); 416 render_text->set_fade_tail(true);
431 if (is_rtl) 417 if (is_rtl)
432 flags |= TEXT_ALIGN_RIGHT; 418 flags |= TEXT_ALIGN_RIGHT;
433 break; 419 break;
434 case TruncateFadeHead: 420 case TruncateFadeHead:
435 render_text->set_fade_head(true); 421 render_text->set_fade_head(true);
436 if (!is_rtl) 422 if (!is_rtl)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 rect.set_height(line_height); 456 rect.set_height(line_height);
471 render_text->SetDisplayRect(rect); 457 render_text->SetDisplayRect(rect);
472 458
473 canvas_->save(SkCanvas::kClip_SaveFlag); 459 canvas_->save(SkCanvas::kClip_SaveFlag);
474 ClipRect(display_rect); 460 ClipRect(display_rect);
475 render_text->Draw(this); 461 render_text->Draw(this);
476 canvas_->restore(); 462 canvas_->restore();
477 } 463 }
478 464
479 } // namespace gfx 465 } // namespace gfx
OLDNEW
« no previous file with comments | « no previous file | ui/gfx/render_text.h » ('j') | ui/gfx/render_text_linux.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698