| 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/gfx/font_list.h" | 10 #include "ui/gfx/font_list.h" |
| 11 #include "ui/gfx/geometry/safe_integer_conversions.h" |
| 11 #include "ui/gfx/insets.h" | 12 #include "ui/gfx/insets.h" |
| 12 #include "ui/gfx/range/range.h" | 13 #include "ui/gfx/range/range.h" |
| 13 #include "ui/gfx/rect.h" | 14 #include "ui/gfx/rect.h" |
| 14 #include "ui/gfx/render_text.h" | 15 #include "ui/gfx/render_text.h" |
| 15 #include "ui/gfx/shadow_value.h" | 16 #include "ui/gfx/shadow_value.h" |
| 16 #include "ui/gfx/text_elider.h" | 17 #include "ui/gfx/text_elider.h" |
| 17 #include "ui/gfx/text_utils.h" | 18 #include "ui/gfx/text_utils.h" |
| 18 | 19 |
| 19 namespace gfx { | 20 namespace gfx { |
| 20 | 21 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span); | 94 *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span); |
| 94 if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1) | 95 if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1) |
| 95 return Range(char_pos, char_pos + char_span); | 96 return Range(char_pos, char_pos + char_span); |
| 96 } | 97 } |
| 97 return Range::InvalidRange(); | 98 return Range::InvalidRange(); |
| 98 } | 99 } |
| 99 | 100 |
| 100 // Elides |text| and adjusts |range| appropriately. If eliding causes |range| | 101 // Elides |text| and adjusts |range| appropriately. If eliding causes |range| |
| 101 // to no longer point to the same character in |text|, |range| is made invalid. | 102 // to no longer point to the same character in |text|, |range| is made invalid. |
| 102 void ElideTextAndAdjustRange(const FontList& font_list, | 103 void ElideTextAndAdjustRange(const FontList& font_list, |
| 103 int width, | 104 float width, |
| 104 base::string16* text, | 105 base::string16* text, |
| 105 Range* range) { | 106 Range* range) { |
| 106 const base::char16 start_char = | 107 const base::char16 start_char = |
| 107 (range->IsValid() ? text->at(range->start()) : 0); | 108 (range->IsValid() ? text->at(range->start()) : 0); |
| 108 *text = ElideText(*text, font_list, width, ELIDE_TAIL); | 109 *text = ElideText(*text, font_list, width, ELIDE_TAIL); |
| 109 if (!range->IsValid()) | 110 if (!range->IsValid()) |
| 110 return; | 111 return; |
| 111 if (range->start() >= text->length() || | 112 if (range->start() >= text->length() || |
| 112 text->at(range->start()) != start_char) { | 113 text->at(range->start()) != start_char) { |
| 113 *range = Range::InvalidRange(); | 114 *range = Range::InvalidRange(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 AdjustStringDirection(flags, &adjusted_text); | 168 AdjustStringDirection(flags, &adjusted_text); |
| 168 #endif | 169 #endif |
| 169 | 170 |
| 170 if ((flags & MULTI_LINE) && *width != 0) { | 171 if ((flags & MULTI_LINE) && *width != 0) { |
| 171 WordWrapBehavior wrap_behavior = TRUNCATE_LONG_WORDS; | 172 WordWrapBehavior wrap_behavior = TRUNCATE_LONG_WORDS; |
| 172 if (flags & CHARACTER_BREAK) | 173 if (flags & CHARACTER_BREAK) |
| 173 wrap_behavior = WRAP_LONG_WORDS; | 174 wrap_behavior = WRAP_LONG_WORDS; |
| 174 else if (!(flags & NO_ELLIPSIS)) | 175 else if (!(flags & NO_ELLIPSIS)) |
| 175 wrap_behavior = ELIDE_LONG_WORDS; | 176 wrap_behavior = ELIDE_LONG_WORDS; |
| 176 | 177 |
| 177 Rect rect(*width, INT_MAX); | |
| 178 std::vector<base::string16> strings; | 178 std::vector<base::string16> strings; |
| 179 ElideRectangleText(adjusted_text, font_list, rect.width(), rect.height(), | 179 ElideRectangleText(adjusted_text, font_list, |
| 180 *width, INT_MAX, |
| 180 wrap_behavior, &strings); | 181 wrap_behavior, &strings); |
| 182 Rect rect(ClampToInt(*width), INT_MAX); |
| 181 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 183 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 182 UpdateRenderText(rect, base::string16(), font_list, flags, 0, | 184 UpdateRenderText(rect, base::string16(), font_list, flags, 0, |
| 183 render_text.get()); | 185 render_text.get()); |
| 184 | 186 |
| 185 float h = 0; | 187 float h = 0; |
| 186 float w = 0; | 188 float w = 0; |
| 187 for (size_t i = 0; i < strings.size(); ++i) { | 189 for (size_t i = 0; i < strings.size(); ++i) { |
| 188 StripAcceleratorChars(flags, &strings[i]); | 190 StripAcceleratorChars(flags, &strings[i]); |
| 189 render_text->SetText(strings[i]); | 191 render_text->SetText(strings[i]); |
| 190 const SizeF& string_size = render_text->GetStringSizeF(); | 192 const SizeF& string_size = render_text->GetStringSizeF(); |
| 191 w = std::max(w, string_size.width()); | 193 w = std::max(w, string_size.width()); |
| 192 h += (i > 0 && line_height > 0) ? line_height : string_size.height(); | 194 h += (i > 0 && line_height > 0) ? line_height : string_size.height(); |
| 193 } | 195 } |
| 194 *width = w; | 196 *width = w; |
| 195 *height = h; | 197 *height = h; |
| 196 } else { | 198 } else { |
| 197 // If the string is too long, the call by |RenderTextWin| to |ScriptShape()| | 199 // If the string is too long, the call by |RenderTextWin| to |ScriptShape()| |
| 198 // will inexplicably fail with result E_INVALIDARG. Guard against this. | 200 // will inexplicably fail with result E_INVALIDARG. Guard against this. |
| 199 const size_t kMaxRenderTextLength = 5000; | 201 const size_t kMaxRenderTextLength = 5000; |
| 200 if (adjusted_text.length() >= kMaxRenderTextLength) { | 202 if (adjusted_text.length() >= kMaxRenderTextLength) { |
| 201 *width = font_list.GetExpectedTextWidth(adjusted_text.length()); | 203 *width = static_cast<float>( |
| 202 *height = font_list.GetHeight(); | 204 font_list.GetExpectedTextWidth(adjusted_text.length())); |
| 205 *height = static_cast<float>(font_list.GetHeight()); |
| 203 } else { | 206 } else { |
| 204 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 207 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 205 Rect rect(*width, *height); | 208 Rect rect(ClampToInt(*width), ClampToInt(*height)); |
| 206 StripAcceleratorChars(flags, &adjusted_text); | 209 StripAcceleratorChars(flags, &adjusted_text); |
| 207 UpdateRenderText(rect, adjusted_text, font_list, flags, 0, | 210 UpdateRenderText(rect, adjusted_text, font_list, flags, 0, |
| 208 render_text.get()); | 211 render_text.get()); |
| 209 const SizeF& string_size = render_text->GetStringSizeF(); | 212 const SizeF& string_size = render_text->GetStringSizeF(); |
| 210 *width = string_size.width(); | 213 *width = string_size.width(); |
| 211 *height = string_size.height(); | 214 *height = string_size.height(); |
| 212 } | 215 } |
| 213 } | 216 } |
| 214 } | 217 } |
| 215 | 218 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 240 render_text->set_shadows(shadows); | 243 render_text->set_shadows(shadows); |
| 241 | 244 |
| 242 if (flags & MULTI_LINE) { | 245 if (flags & MULTI_LINE) { |
| 243 WordWrapBehavior wrap_behavior = IGNORE_LONG_WORDS; | 246 WordWrapBehavior wrap_behavior = IGNORE_LONG_WORDS; |
| 244 if (flags & CHARACTER_BREAK) | 247 if (flags & CHARACTER_BREAK) |
| 245 wrap_behavior = WRAP_LONG_WORDS; | 248 wrap_behavior = WRAP_LONG_WORDS; |
| 246 else if (!(flags & NO_ELLIPSIS)) | 249 else if (!(flags & NO_ELLIPSIS)) |
| 247 wrap_behavior = ELIDE_LONG_WORDS; | 250 wrap_behavior = ELIDE_LONG_WORDS; |
| 248 | 251 |
| 249 std::vector<base::string16> strings; | 252 std::vector<base::string16> strings; |
| 250 ElideRectangleText(adjusted_text, font_list, text_bounds.width(), | 253 ElideRectangleText(adjusted_text, font_list, |
| 254 static_cast<float>(text_bounds.width()), |
| 251 text_bounds.height(), wrap_behavior, &strings); | 255 text_bounds.height(), wrap_behavior, &strings); |
| 252 | 256 |
| 253 for (size_t i = 0; i < strings.size(); i++) { | 257 for (size_t i = 0; i < strings.size(); i++) { |
| 254 Range range = StripAcceleratorChars(flags, &strings[i]); | 258 Range range = StripAcceleratorChars(flags, &strings[i]); |
| 255 UpdateRenderText(rect, strings[i], font_list, flags, color, | 259 UpdateRenderText(rect, strings[i], font_list, flags, color, |
| 256 render_text.get()); | 260 render_text.get()); |
| 257 int line_padding = 0; | 261 int line_padding = 0; |
| 258 if (line_height > 0) | 262 if (line_height > 0) |
| 259 line_padding = line_height - render_text->GetStringSize().height(); | 263 line_padding = line_height - render_text->GetStringSize().height(); |
| 260 else | 264 else |
| (...skipping 26 matching lines...) Expand all Loading... |
| 287 if (elide_text) { | 291 if (elide_text) { |
| 288 render_text->SetText(adjusted_text); | 292 render_text->SetText(adjusted_text); |
| 289 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) { | 293 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) { |
| 290 render_text->SetElideBehavior(FADE_TAIL); | 294 render_text->SetElideBehavior(FADE_TAIL); |
| 291 elide_text = false; | 295 elide_text = false; |
| 292 } | 296 } |
| 293 } | 297 } |
| 294 #endif | 298 #endif |
| 295 | 299 |
| 296 if (elide_text) { | 300 if (elide_text) { |
| 297 ElideTextAndAdjustRange(font_list, text_bounds.width(), &adjusted_text, | 301 ElideTextAndAdjustRange(font_list, |
| 298 &range); | 302 static_cast<float>(text_bounds.width()), |
| 303 &adjusted_text, &range); |
| 299 } | 304 } |
| 300 | 305 |
| 301 UpdateRenderText(rect, adjusted_text, font_list, flags, color, | 306 UpdateRenderText(rect, adjusted_text, font_list, flags, color, |
| 302 render_text.get()); | 307 render_text.get()); |
| 303 if (range.IsValid()) | 308 if (range.IsValid()) |
| 304 render_text->ApplyStyle(UNDERLINE, true, range); | 309 render_text->ApplyStyle(UNDERLINE, true, range); |
| 305 render_text->Draw(this); | 310 render_text->Draw(this); |
| 306 } | 311 } |
| 307 | 312 |
| 308 canvas_->restore(); | 313 canvas_->restore(); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 UpdateRenderText(rect, text, font_list, flags, color, render_text.get()); | 393 UpdateRenderText(rect, text, font_list, flags, color, render_text.get()); |
| 389 render_text->SetElideBehavior(FADE_TAIL); | 394 render_text->SetElideBehavior(FADE_TAIL); |
| 390 | 395 |
| 391 canvas_->save(); | 396 canvas_->save(); |
| 392 ClipRect(display_rect); | 397 ClipRect(display_rect); |
| 393 render_text->Draw(this); | 398 render_text->Draw(this); |
| 394 canvas_->restore(); | 399 canvas_->restore(); |
| 395 } | 400 } |
| 396 | 401 |
| 397 } // namespace gfx | 402 } // namespace gfx |
| OLD | NEW |