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 |