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 |