| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_skia.h" | 5 #include "ui/gfx/canvas_skia.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/i18n/rtl.h" | 9 #include "base/i18n/rtl.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 primary->Inset(remainder, 0, 0, 0); | 274 primary->Inset(remainder, 0, 0, 0); |
| 275 secondary->Inset(0, 0, primary_width, 0); | 275 secondary->Inset(0, 0, primary_width, 0); |
| 276 break; | 276 break; |
| 277 } | 277 } |
| 278 } | 278 } |
| 279 | 279 |
| 280 } // anonymous namespace | 280 } // anonymous namespace |
| 281 | 281 |
| 282 namespace gfx { | 282 namespace gfx { |
| 283 | 283 |
| 284 CanvasSkia::CanvasSkia(int width, int height, bool is_opaque) | |
| 285 : skia::PlatformCanvas(width, height, is_opaque) { | |
| 286 } | |
| 287 | |
| 288 CanvasSkia::CanvasSkia() : skia::PlatformCanvas() { | |
| 289 } | |
| 290 | |
| 291 CanvasSkia::~CanvasSkia() { | |
| 292 } | |
| 293 | |
| 294 // static | 284 // static |
| 295 void CanvasSkia::SizeStringInt(const string16& text, | 285 void CanvasSkia::SizeStringInt(const string16& text, |
| 296 const gfx::Font& font, | 286 const gfx::Font& font, |
| 297 int* width, int* height, | 287 int* width, int* height, |
| 298 int flags) { | 288 int flags) { |
| 299 // Clamp the max amount of text we'll measure to 2K. When the string is | 289 // Clamp the max amount of text we'll measure to 2K. When the string is |
| 300 // actually drawn, it will be clipped to whatever size box is provided, and | 290 // actually drawn, it will be clipped to whatever size box is provided, and |
| 301 // the time to do that doesn't depend on the length being clipped off. | 291 // the time to do that doesn't depend on the length being clipped off. |
| 302 const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K. | 292 const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K. |
| 303 string16 clamped_string(text.substr(0, kMaxStringLength)); | 293 string16 clamped_string(text.substr(0, kMaxStringLength)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 329 *width = r.right; | 319 *width = r.right; |
| 330 *height = r.bottom; | 320 *height = r.bottom; |
| 331 } | 321 } |
| 332 | 322 |
| 333 void CanvasSkia::DrawStringInt(const string16& text, | 323 void CanvasSkia::DrawStringInt(const string16& text, |
| 334 HFONT font, | 324 HFONT font, |
| 335 const SkColor& color, | 325 const SkColor& color, |
| 336 int x, int y, int w, int h, | 326 int x, int y, int w, int h, |
| 337 int flags) { | 327 int flags) { |
| 338 SkRect fclip; | 328 SkRect fclip; |
| 339 if (!getClipBounds(&fclip)) | 329 if (!canvas_->getClipBounds(&fclip)) |
| 340 return; | 330 return; |
| 341 RECT text_bounds = { x, y, x + w, y + h }; | 331 RECT text_bounds = { x, y, x + w, y + h }; |
| 342 SkIRect clip; | 332 SkIRect clip; |
| 343 fclip.round(&clip); | 333 fclip.round(&clip); |
| 344 if (!clip.intersect(skia::RECTToSkIRect(text_bounds))) | 334 if (!clip.intersect(skia::RECTToSkIRect(text_bounds))) |
| 345 return; | 335 return; |
| 346 | 336 |
| 347 // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in | 337 // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in |
| 348 // DrawText() if you e.g. ask it to character-break a no-whitespace string of | 338 // DrawText() if you e.g. ask it to character-break a no-whitespace string of |
| 349 // length > 43680 (for which it draws nothing), and since we clamped to 2K in | 339 // length > 43680 (for which it draws nothing), and since we clamped to 2K in |
| 350 // SizeStringInt() we're unlikely to be able to display this much anyway. | 340 // SizeStringInt() we're unlikely to be able to display this much anyway. |
| 351 const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K. | 341 const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K. |
| 352 string16 clamped_string(text.substr(0, kMaxStringLength)); | 342 string16 clamped_string(text.substr(0, kMaxStringLength)); |
| 353 | 343 |
| 354 HDC dc; | 344 HDC dc; |
| 355 HFONT old_font; | 345 HFONT old_font; |
| 356 { | 346 { |
| 357 skia::ScopedPlatformPaint scoped_platform_paint(this); | 347 skia::ScopedPlatformPaint scoped_platform_paint(canvas_); |
| 358 dc = scoped_platform_paint.GetPlatformSurface(); | 348 dc = scoped_platform_paint.GetPlatformSurface(); |
| 359 SetBkMode(dc, TRANSPARENT); | 349 SetBkMode(dc, TRANSPARENT); |
| 360 old_font = (HFONT)SelectObject(dc, font); | 350 old_font = (HFONT)SelectObject(dc, font); |
| 361 COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), | 351 COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), |
| 362 SkColorGetB(color)); | 352 SkColorGetB(color)); |
| 363 SetTextColor(dc, brush_color); | 353 SetTextColor(dc, brush_color); |
| 364 | 354 |
| 365 int f = ComputeFormatFlags(flags, clamped_string); | 355 int f = ComputeFormatFlags(flags, clamped_string); |
| 366 DoDrawText(dc, clamped_string, &text_bounds, f); | 356 DoDrawText(dc, clamped_string, &text_bounds, f); |
| 367 } | 357 } |
| 368 | 358 |
| 369 // Restore the old font. This way we don't have to worry if the caller | 359 // Restore the old font. This way we don't have to worry if the caller |
| 370 // deletes the font and the DC lives longer. | 360 // deletes the font and the DC lives longer. |
| 371 SelectObject(dc, old_font); | 361 SelectObject(dc, old_font); |
| 372 | 362 |
| 373 // Windows will have cleared the alpha channel of the text we drew. Assume | 363 // Windows will have cleared the alpha channel of the text we drew. Assume |
| 374 // we're drawing to an opaque surface, or at least the text rect area is | 364 // we're drawing to an opaque surface, or at least the text rect area is |
| 375 // opaque. | 365 // opaque. |
| 376 skia::MakeOpaque(this, clip.fLeft, clip.fTop, clip.width(), | 366 skia::MakeOpaque(canvas_, clip.fLeft, clip.fTop, clip.width(), |
| 377 clip.height()); | 367 clip.height()); |
| 378 } | 368 } |
| 379 | 369 |
| 380 void CanvasSkia::DrawStringInt(const string16& text, | 370 void CanvasSkia::DrawStringInt(const string16& text, |
| 381 const gfx::Font& font, | 371 const gfx::Font& font, |
| 382 const SkColor& color, | 372 const SkColor& color, |
| 383 int x, int y, int w, int h, | 373 int x, int y, int w, int h, |
| 384 int flags) { | 374 int flags) { |
| 385 DrawStringInt(text, font.GetNativeFont(), color, x, y, w, h, flags); | 375 DrawStringInt(text, font.GetNativeFont(), color, x, y, w, h, flags); |
| 386 } | 376 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 text_canvas.DrawRectInt(0, 0, w + 2, h + 2, bkgnd_paint); | 421 text_canvas.DrawRectInt(0, 0, w + 2, h + 2, bkgnd_paint); |
| 432 | 422 |
| 433 // Draw the text into the temporary buffer. This will have correct | 423 // Draw the text into the temporary buffer. This will have correct |
| 434 // ClearType since the background color is the same as the halo color. | 424 // ClearType since the background color is the same as the halo color. |
| 435 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); | 425 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); |
| 436 | 426 |
| 437 // Windows will have cleared the alpha channel for the pixels it drew. Make it | 427 // Windows will have cleared the alpha channel for the pixels it drew. Make it |
| 438 // opaque. We have to do this first since pixelShouldGetHalo will check for | 428 // opaque. We have to do this first since pixelShouldGetHalo will check for |
| 439 // 0 to see if a pixel has been modified to transparent, and black text that | 429 // 0 to see if a pixel has been modified to transparent, and black text that |
| 440 // Windows draw will look transparent to it! | 430 // Windows draw will look transparent to it! |
| 441 skia::MakeOpaque(&text_canvas, 0, 0, w + 2, h + 2); | 431 skia::MakeOpaque(text_canvas.sk_canvas(), 0, 0, w + 2, h + 2); |
| 442 | 432 |
| 443 uint32_t halo_premul = SkPreMultiplyColor(halo_color); | 433 uint32_t halo_premul = SkPreMultiplyColor(halo_color); |
| 444 SkBitmap& text_bitmap = const_cast<SkBitmap&>( | 434 SkBitmap& text_bitmap = const_cast<SkBitmap&>( |
| 445 skia::GetTopDevice(text_canvas)->accessBitmap(true)); | 435 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(true)); |
| 446 for (int cur_y = 0; cur_y < h + 2; cur_y++) { | 436 for (int cur_y = 0; cur_y < h + 2; cur_y++) { |
| 447 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); | 437 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); |
| 448 for (int cur_x = 0; cur_x < w + 2; cur_x++) { | 438 for (int cur_x = 0; cur_x < w + 2; cur_x++) { |
| 449 if (text_row[cur_x] == halo_premul) { | 439 if (text_row[cur_x] == halo_premul) { |
| 450 // This pixel was not touched by the text routines. See if it borders | 440 // This pixel was not touched by the text routines. See if it borders |
| 451 // a touched pixel in any of the 4 directions (not diagonally). | 441 // a touched pixel in any of the 4 directions (not diagonally). |
| 452 if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) | 442 if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) |
| 453 text_row[cur_x] = 0; // Make transparent. | 443 text_row[cur_x] = 0; // Make transparent. |
| 454 } else { | 444 } else { |
| 455 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. | 445 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 flags |= TEXT_ALIGN_LEFT; | 524 flags |= TEXT_ALIGN_LEFT; |
| 535 | 525 |
| 536 // Fade in/out about 2.5 characters of the beginning/end of the string. | 526 // Fade in/out about 2.5 characters of the beginning/end of the string. |
| 537 // The .5 here is helpful if one of the characters is a space. | 527 // The .5 here is helpful if one of the characters is a space. |
| 538 // Use a quarter of the display width if the string is very short. | 528 // Use a quarter of the display width if the string is very short. |
| 539 int gradient_width = Round(std::min(average_character_width * 2.5, | 529 int gradient_width = Round(std::min(average_character_width * 2.5, |
| 540 display_rect.width() / 4.0)); | 530 display_rect.width() / 4.0)); |
| 541 | 531 |
| 542 // Move the origin to |display_rect.origin()|. This simplifies all the | 532 // Move the origin to |display_rect.origin()|. This simplifies all the |
| 543 // drawing so that both the source and destination can be (0,0). | 533 // drawing so that both the source and destination can be (0,0). |
| 544 save(kMatrix_SaveFlag); | 534 canvas_->save(SkCanvas::kMatrix_SaveFlag); |
| 545 TranslateInt(display_rect.x(), display_rect.y()); | 535 TranslateInt(display_rect.x(), display_rect.y()); |
| 546 | 536 |
| 547 gfx::Rect solid_part(gfx::Point(), display_rect.size()); | 537 gfx::Rect solid_part(gfx::Point(), display_rect.size()); |
| 548 gfx::Rect head_part; | 538 gfx::Rect head_part; |
| 549 gfx::Rect tail_part; | 539 gfx::Rect tail_part; |
| 550 if (is_truncating_head) | 540 if (is_truncating_head) |
| 551 DivideRect(solid_part, is_rtl ? PrimaryOnRight : PrimaryOnLeft, | 541 DivideRect(solid_part, is_rtl ? PrimaryOnRight : PrimaryOnLeft, |
| 552 gradient_width, &head_part, &solid_part); | 542 gradient_width, &head_part, &solid_part); |
| 553 if (is_truncating_tail) | 543 if (is_truncating_tail) |
| 554 DivideRect(solid_part, is_rtl ? PrimaryOnLeft : PrimaryOnRight, | 544 DivideRect(solid_part, is_rtl ? PrimaryOnLeft : PrimaryOnRight, |
| 555 gradient_width, &tail_part, &solid_part); | 545 gradient_width, &tail_part, &solid_part); |
| 556 | 546 |
| 557 // Grow |display_rect| by |offset_x|. | 547 // Grow |display_rect| by |offset_x|. |
| 558 gfx::Rect text_rect(gfx::Point(), display_rect.size()); | 548 gfx::Rect text_rect(gfx::Point(), display_rect.size()); |
| 559 if (!is_rtl) | 549 if (!is_rtl) |
| 560 text_rect.set_x(text_rect.x() - offset_x); | 550 text_rect.set_x(text_rect.x() - offset_x); |
| 561 text_rect.set_width(text_rect.width() + offset_x); | 551 text_rect.set_width(text_rect.width() + offset_x); |
| 562 | 552 |
| 563 // Create a temporary bitmap to draw the gradient to. | 553 // Create a temporary bitmap to draw the gradient to. |
| 564 scoped_ptr<SkCanvas> gradient_canvas(skia::CreateBitmapCanvas( | 554 scoped_ptr<SkCanvas> gradient_canvas(skia::CreateBitmapCanvas( |
| 565 display_rect.width(), display_rect.height(), false)); | 555 display_rect.width(), display_rect.height(), false)); |
| 566 | 556 |
| 567 { | 557 { |
| 568 skia::ScopedPlatformPaint scoped_platform_paint(this); | 558 skia::ScopedPlatformPaint scoped_platform_paint(canvas_); |
| 569 HDC hdc = scoped_platform_paint.GetPlatformSurface(); | 559 HDC hdc = scoped_platform_paint.GetPlatformSurface(); |
| 570 if (is_truncating_head) | 560 if (is_truncating_head) |
| 571 DrawTextGradientPart(hdc, gradient_canvas.get(), text, color, | 561 DrawTextGradientPart(hdc, gradient_canvas.get(), text, color, |
| 572 font.GetNativeFont(), text_rect, head_part, is_rtl, | 562 font.GetNativeFont(), text_rect, head_part, is_rtl, |
| 573 flags); | 563 flags); |
| 574 if (is_truncating_tail) | 564 if (is_truncating_tail) |
| 575 DrawTextGradientPart(hdc, gradient_canvas.get(), text, color, | 565 DrawTextGradientPart(hdc, gradient_canvas.get(), text, color, |
| 576 font.GetNativeFont(), text_rect, tail_part, !is_rtl, | 566 font.GetNativeFont(), text_rect, tail_part, !is_rtl, |
| 577 flags); | 567 flags); |
| 578 } | 568 } |
| 579 | 569 |
| 580 // Draw the solid part. | 570 // Draw the solid part. |
| 581 save(kClip_SaveFlag); | 571 canvas_->save(SkCanvas::kClip_SaveFlag); |
| 582 ClipRectInt(solid_part.x(), solid_part.y(), | 572 ClipRectInt(solid_part.x(), solid_part.y(), |
| 583 solid_part.width(), solid_part.height()); | 573 solid_part.width(), solid_part.height()); |
| 584 DrawStringInt(text, font, color, | 574 DrawStringInt(text, font, color, |
| 585 text_rect.x(), text_rect.y(), | 575 text_rect.x(), text_rect.y(), |
| 586 text_rect.width(), text_rect.height(), | 576 text_rect.width(), text_rect.height(), |
| 587 flags); | 577 flags); |
| 588 restore(); | 578 canvas_->restore(); |
| 589 restore(); | 579 canvas_->restore(); |
| 590 } | 580 } |
| 591 | 581 |
| 592 } // namespace gfx | 582 } // namespace gfx |
| OLD | NEW |