| 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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 primary->Inset(remainder, 0, 0, 0); | 268 primary->Inset(remainder, 0, 0, 0); |
| 269 secondary->Inset(0, 0, primary_width, 0); | 269 secondary->Inset(0, 0, primary_width, 0); |
| 270 break; | 270 break; |
| 271 } | 271 } |
| 272 } | 272 } |
| 273 | 273 |
| 274 } // anonymous namespace | 274 } // anonymous namespace |
| 275 | 275 |
| 276 namespace gfx { | 276 namespace gfx { |
| 277 | 277 |
| 278 CanvasSkia::CanvasSkia(int width, int height, bool is_opaque) | |
| 279 : skia::PlatformCanvas(width, height, is_opaque) { | |
| 280 } | |
| 281 | |
| 282 CanvasSkia::CanvasSkia() : skia::PlatformCanvas() { | |
| 283 } | |
| 284 | |
| 285 CanvasSkia::~CanvasSkia() { | |
| 286 } | |
| 287 | |
| 288 // static | 278 // static |
| 289 void CanvasSkia::SizeStringInt(const string16& text, | 279 void CanvasSkia::SizeStringInt(const string16& text, |
| 290 const gfx::Font& font, | 280 const gfx::Font& font, |
| 291 int* width, int* height, | 281 int* width, int* height, |
| 292 int flags) { | 282 int flags) { |
| 293 // Clamp the max amount of text we'll measure to 2K. When the string is | 283 // Clamp the max amount of text we'll measure to 2K. When the string is |
| 294 // actually drawn, it will be clipped to whatever size box is provided, and | 284 // actually drawn, it will be clipped to whatever size box is provided, and |
| 295 // the time to do that doesn't depend on the length being clipped off. | 285 // the time to do that doesn't depend on the length being clipped off. |
| 296 const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K. | 286 const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K. |
| 297 string16 clamped_string(text.substr(0, kMaxStringLength)); | 287 string16 clamped_string(text.substr(0, kMaxStringLength)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 323 *width = r.right; | 313 *width = r.right; |
| 324 *height = r.bottom; | 314 *height = r.bottom; |
| 325 } | 315 } |
| 326 | 316 |
| 327 void CanvasSkia::DrawStringInt(const string16& text, | 317 void CanvasSkia::DrawStringInt(const string16& text, |
| 328 HFONT font, | 318 HFONT font, |
| 329 const SkColor& color, | 319 const SkColor& color, |
| 330 int x, int y, int w, int h, | 320 int x, int y, int w, int h, |
| 331 int flags) { | 321 int flags) { |
| 332 SkRect fclip; | 322 SkRect fclip; |
| 333 if (!getClipBounds(&fclip)) | 323 if (!skia_canvas_->getClipBounds(&fclip)) |
| 334 return; | 324 return; |
| 335 RECT text_bounds = { x, y, x + w, y + h }; | 325 RECT text_bounds = { x, y, x + w, y + h }; |
| 336 SkIRect clip; | 326 SkIRect clip; |
| 337 fclip.round(&clip); | 327 fclip.round(&clip); |
| 338 if (!clip.intersect(skia::RECTToSkIRect(text_bounds))) | 328 if (!clip.intersect(skia::RECTToSkIRect(text_bounds))) |
| 339 return; | 329 return; |
| 340 | 330 |
| 341 // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in | 331 // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in |
| 342 // DrawText() if you e.g. ask it to character-break a no-whitespace string of | 332 // DrawText() if you e.g. ask it to character-break a no-whitespace string of |
| 343 // length > 43680 (for which it draws nothing), and since we clamped to 2K in | 333 // length > 43680 (for which it draws nothing), and since we clamped to 2K in |
| 344 // SizeStringInt() we're unlikely to be able to display this much anyway. | 334 // SizeStringInt() we're unlikely to be able to display this much anyway. |
| 345 const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K. | 335 const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K. |
| 346 string16 clamped_string(text.substr(0, kMaxStringLength)); | 336 string16 clamped_string(text.substr(0, kMaxStringLength)); |
| 347 | 337 |
| 348 HDC dc = beginPlatformPaint(); | 338 HDC dc = BeginPlatformPaint(); |
| 349 SetBkMode(dc, TRANSPARENT); | 339 SetBkMode(dc, TRANSPARENT); |
| 350 HFONT old_font = (HFONT)SelectObject(dc, font); | 340 HFONT old_font = (HFONT)SelectObject(dc, font); |
| 351 COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), | 341 COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), |
| 352 SkColorGetB(color)); | 342 SkColorGetB(color)); |
| 353 SetTextColor(dc, brush_color); | 343 SetTextColor(dc, brush_color); |
| 354 | 344 |
| 355 int f = ComputeFormatFlags(flags, clamped_string); | 345 int f = ComputeFormatFlags(flags, clamped_string); |
| 356 DoDrawText(dc, clamped_string, &text_bounds, f); | 346 DoDrawText(dc, clamped_string, &text_bounds, f); |
| 357 endPlatformPaint(); | 347 EndPlatformPaint(); |
| 358 | 348 |
| 359 // Restore the old font. This way we don't have to worry if the caller | 349 // Restore the old font. This way we don't have to worry if the caller |
| 360 // deletes the font and the DC lives longer. | 350 // deletes the font and the DC lives longer. |
| 361 SelectObject(dc, old_font); | 351 SelectObject(dc, old_font); |
| 362 | 352 |
| 363 // Windows will have cleared the alpha channel of the text we drew. Assume | 353 // Windows will have cleared the alpha channel of the text we drew. Assume |
| 364 // we're drawing to an opaque surface, or at least the text rect area is | 354 // we're drawing to an opaque surface, or at least the text rect area is |
| 365 // opaque. | 355 // opaque. |
| 366 getTopPlatformDevice().makeOpaque(clip.fLeft, clip.fTop, | 356 skia::MakeOpaque(clip, skia_canvas_.get()); |
| 367 clip.width(), clip.height()); | |
| 368 } | 357 } |
| 369 | 358 |
| 370 void CanvasSkia::DrawStringInt(const string16& text, | 359 void CanvasSkia::DrawStringInt(const string16& text, |
| 371 const gfx::Font& font, | 360 const gfx::Font& font, |
| 372 const SkColor& color, | 361 const SkColor& color, |
| 373 int x, int y, int w, int h, | 362 int x, int y, int w, int h, |
| 374 int flags) { | 363 int flags) { |
| 375 DrawStringInt(text, font.GetNativeFont(), color, x, y, w, h, flags); | 364 DrawStringInt(text, font.GetNativeFont(), color, x, y, w, h, flags); |
| 376 } | 365 } |
| 377 | 366 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 408 const SkColor& text_color, | 397 const SkColor& text_color, |
| 409 const SkColor& halo_color_in, | 398 const SkColor& halo_color_in, |
| 410 int x, int y, int w, int h, | 399 int x, int y, int w, int h, |
| 411 int flags) { | 400 int flags) { |
| 412 // Some callers will have semitransparent halo colors, which we don't handle | 401 // Some callers will have semitransparent halo colors, which we don't handle |
| 413 // (since the resulting image can have 1-bit transparency only). | 402 // (since the resulting image can have 1-bit transparency only). |
| 414 SkColor halo_color = halo_color_in | 0xFF000000; | 403 SkColor halo_color = halo_color_in | 0xFF000000; |
| 415 | 404 |
| 416 // Create a temporary buffer filled with the halo color. It must leave room | 405 // Create a temporary buffer filled with the halo color. It must leave room |
| 417 // for the 1-pixel border around the text. | 406 // for the 1-pixel border around the text. |
| 418 CanvasSkia text_canvas(w + 2, h + 2, true); | 407 CanvasSkia text_canvas; |
| 408 if (!text_canvas.Init(w + 2, h + 2, true)) |
| 409 return; |
| 410 |
| 419 SkPaint bkgnd_paint; | 411 SkPaint bkgnd_paint; |
| 420 bkgnd_paint.setColor(halo_color); | 412 bkgnd_paint.setColor(halo_color); |
| 421 text_canvas.DrawRectInt(0, 0, w + 2, h + 2, bkgnd_paint); | 413 text_canvas.DrawRectInt(0, 0, w + 2, h + 2, bkgnd_paint); |
| 422 | 414 |
| 423 // Draw the text into the temporary buffer. This will have correct | 415 // Draw the text into the temporary buffer. This will have correct |
| 424 // ClearType since the background color is the same as the halo color. | 416 // ClearType since the background color is the same as the halo color. |
| 425 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); | 417 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); |
| 426 | 418 |
| 427 // Windows will have cleared the alpha channel for the pixels it drew. Make it | 419 // Windows will have cleared the alpha channel for the pixels it drew. Make it |
| 428 // opaque. We have to do this first since pixelShouldGetHalo will check for | 420 // opaque. We have to do this first since pixelShouldGetHalo will check for |
| 429 // 0 to see if a pixel has been modified to transparent, and black text that | 421 // 0 to see if a pixel has been modified to transparent, and black text that |
| 430 // Windows draw will look transparent to it! | 422 // Windows draw will look transparent to it! |
| 431 text_canvas.getTopPlatformDevice().makeOpaque(0, 0, w + 2, h + 2); | 423 skia::MakeOpaque(SkIRect::MakeWH(w + 2, h + 2), text_canvas.skia_canvas()); |
| 432 | 424 |
| 433 uint32_t halo_premul = SkPreMultiplyColor(halo_color); | 425 uint32_t halo_premul = SkPreMultiplyColor(halo_color); |
| 434 SkBitmap& text_bitmap = const_cast<SkBitmap&>( | 426 SkBitmap& text_bitmap = const_cast<SkBitmap&>( |
| 435 text_canvas.getTopPlatformDevice().accessBitmap(true)); | 427 text_canvas.skia_canvas()->getTopDevice()->accessBitmap(true)); |
| 436 for (int cur_y = 0; cur_y < h + 2; cur_y++) { | 428 for (int cur_y = 0; cur_y < h + 2; cur_y++) { |
| 437 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); | 429 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); |
| 438 for (int cur_x = 0; cur_x < w + 2; cur_x++) { | 430 for (int cur_x = 0; cur_x < w + 2; cur_x++) { |
| 439 if (text_row[cur_x] == halo_premul) { | 431 if (text_row[cur_x] == halo_premul) { |
| 440 // This pixel was not touched by the text routines. See if it borders | 432 // This pixel was not touched by the text routines. See if it borders |
| 441 // a touched pixel in any of the 4 directions (not diagonally). | 433 // a touched pixel in any of the 4 directions (not diagonally). |
| 442 if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) | 434 if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) |
| 443 text_row[cur_x] = 0; // Make transparent. | 435 text_row[cur_x] = 0; // Make transparent. |
| 444 } else { | 436 } else { |
| 445 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. | 437 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 flags |= TEXT_ALIGN_LEFT; | 516 flags |= TEXT_ALIGN_LEFT; |
| 525 | 517 |
| 526 // Fade in/out about 2.5 characters of the beginning/end of the string. | 518 // Fade in/out about 2.5 characters of the beginning/end of the string. |
| 527 // The .5 here is helpful if one of the characters is a space. | 519 // The .5 here is helpful if one of the characters is a space. |
| 528 // Use a quarter of the display width if the string is very short. | 520 // Use a quarter of the display width if the string is very short. |
| 529 int gradient_width = Round(std::min(average_character_width * 2.5, | 521 int gradient_width = Round(std::min(average_character_width * 2.5, |
| 530 display_rect.width() / 4.0)); | 522 display_rect.width() / 4.0)); |
| 531 | 523 |
| 532 // Move the origin to |display_rect.origin()|. This simplifies all the | 524 // Move the origin to |display_rect.origin()|. This simplifies all the |
| 533 // drawing so that both the source and destination can be (0,0). | 525 // drawing so that both the source and destination can be (0,0). |
| 534 save(kMatrix_SaveFlag); | 526 skia_canvas_->save(SkCanvas::kMatrix_SaveFlag); |
| 535 TranslateInt(display_rect.x(), display_rect.y()); | 527 TranslateInt(display_rect.x(), display_rect.y()); |
| 536 | 528 |
| 537 gfx::Rect solid_part(gfx::Point(), display_rect.size()); | 529 gfx::Rect solid_part(gfx::Point(), display_rect.size()); |
| 538 gfx::Rect head_part; | 530 gfx::Rect head_part; |
| 539 gfx::Rect tail_part; | 531 gfx::Rect tail_part; |
| 540 if (is_truncating_head) | 532 if (is_truncating_head) |
| 541 DivideRect(solid_part, is_rtl ? PrimaryOnRight : PrimaryOnLeft, | 533 DivideRect(solid_part, is_rtl ? PrimaryOnRight : PrimaryOnLeft, |
| 542 gradient_width, &head_part, &solid_part); | 534 gradient_width, &head_part, &solid_part); |
| 543 if (is_truncating_tail) | 535 if (is_truncating_tail) |
| 544 DivideRect(solid_part, is_rtl ? PrimaryOnLeft : PrimaryOnRight, | 536 DivideRect(solid_part, is_rtl ? PrimaryOnLeft : PrimaryOnRight, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 556 GetObject(font.GetNativeFont(), sizeof(font_info), &font_info); | 548 GetObject(font.GetNativeFont(), sizeof(font_info), &font_info); |
| 557 font_info.lfQuality = ANTIALIASED_QUALITY; | 549 font_info.lfQuality = ANTIALIASED_QUALITY; |
| 558 base::win::ScopedHFONT gray_scale_font(CreateFontIndirect(&font_info)); | 550 base::win::ScopedHFONT gray_scale_font(CreateFontIndirect(&font_info)); |
| 559 | 551 |
| 560 // Create a temporary bitmap to draw the gradient to. | 552 // Create a temporary bitmap to draw the gradient to. |
| 561 scoped_ptr<skia::BitmapPlatformDevice> gradient_bitmap( | 553 scoped_ptr<skia::BitmapPlatformDevice> gradient_bitmap( |
| 562 skia::BitmapPlatformDevice::create( | 554 skia::BitmapPlatformDevice::create( |
| 563 display_rect.width(), display_rect.height(), false, NULL)); | 555 display_rect.width(), display_rect.height(), false, NULL)); |
| 564 DCHECK(gradient_bitmap.get()); | 556 DCHECK(gradient_bitmap.get()); |
| 565 | 557 |
| 566 HDC hdc = beginPlatformPaint(); | 558 HDC hdc = BeginPlatformPaint(); |
| 567 if (is_truncating_head) | 559 if (is_truncating_head) |
| 568 DrawTextGradientPart(hdc, *gradient_bitmap, text, color, gray_scale_font, | 560 DrawTextGradientPart(hdc, *gradient_bitmap, text, color, gray_scale_font, |
| 569 text_rect, head_part, is_rtl, flags); | 561 text_rect, head_part, is_rtl, flags); |
| 570 if (is_truncating_tail) | 562 if (is_truncating_tail) |
| 571 DrawTextGradientPart(hdc, *gradient_bitmap, text, color, gray_scale_font, | 563 DrawTextGradientPart(hdc, *gradient_bitmap, text, color, gray_scale_font, |
| 572 text_rect, tail_part, !is_rtl, flags); | 564 text_rect, tail_part, !is_rtl, flags); |
| 573 endPlatformPaint(); | 565 EndPlatformPaint(); |
| 574 | 566 |
| 575 // Draw the solid part. | 567 // Draw the solid part. |
| 576 save(kClip_SaveFlag); | 568 skia_canvas_->save(SkCanvas::kClip_SaveFlag); |
| 577 ClipRectInt(solid_part.x(), solid_part.y(), | 569 ClipRectInt(solid_part.x(), solid_part.y(), |
| 578 solid_part.width(), solid_part.height()); | 570 solid_part.width(), solid_part.height()); |
| 579 DrawStringInt(text, font, color, | 571 DrawStringInt(text, font, color, |
| 580 text_rect.x(), text_rect.y(), | 572 text_rect.x(), text_rect.y(), |
| 581 text_rect.width(), text_rect.height(), | 573 text_rect.width(), text_rect.height(), |
| 582 flags); | 574 flags); |
| 583 restore(); | 575 skia_canvas_->restore(); |
| 584 restore(); | 576 skia_canvas_->restore(); |
| 577 } |
| 578 |
| 579 void CanvasSkia::BlitToNativeContext(const Rect& src_rect, |
| 580 const Point& dst_origin, |
| 581 NativeDrawingContext dst_context) { |
| 582 skia::BitmapPlatformDevice* device = |
| 583 static_cast<skia::BitmapPlatformDevice*>(skia_canvas_->getTopDevice()); |
| 584 device->drawToHDC(dst_context, dst_origin.x(), dst_origin.y(), |
| 585 &src_rect.ToRECT()); |
| 585 } | 586 } |
| 586 | 587 |
| 587 } // namespace gfx | 588 } // namespace gfx |
| 589 |
| OLD | NEW |