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