| 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 <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" |
| 11 #include "third_party/skia/include/core/SkBitmap.h" | 11 #include "third_party/skia/include/core/SkBitmap.h" |
| 12 #include "third_party/skia/include/effects/SkGradientShader.h" | 12 #include "third_party/skia/include/effects/SkGradientShader.h" |
| 13 #include "ui/gfx/canvas.h" | 13 #include "ui/gfx/canvas.h" |
| 14 #include "ui/gfx/font.h" | 14 #include "ui/gfx/font.h" |
| 15 #include "ui/gfx/rect.h" | 15 #include "ui/gfx/rect.h" |
| 16 #include "ui/gfx/skia_util.h" | 16 #include "ui/gfx/skia_util.h" |
| 17 #include "ui/gfx/transform.h" | 17 #include "ui/gfx/transform.h" |
| 18 | 18 |
| 19 #if defined(OS_WIN) | 19 #if defined(OS_WIN) |
| 20 #include "ui/gfx/canvas_skia_paint.h" | 20 #include "ui/gfx/canvas_skia_paint.h" |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 namespace gfx { | 23 namespace gfx { |
| 24 | 24 |
| 25 Canvas::Canvas(const gfx::Size& size, bool is_opaque) | |
| 26 : owned_canvas_(new skia::PlatformCanvas(size.width(), size.height(), | |
| 27 is_opaque)), | |
| 28 canvas_(owned_canvas_.get()) { | |
| 29 #if defined(OS_WIN) || defined(OS_MACOSX) | |
| 30 // skia::PlatformCanvas instances are initialized to 0 by Cairo on Linux, but | |
| 31 // uninitialized on Win and Mac. | |
| 32 if (!is_opaque) | |
| 33 owned_canvas_->clear(SkColorSetARGB(0, 0, 0, 0)); | |
| 34 #endif | |
| 35 | |
| 36 ApplyScaleFactor(ui::SCALE_FACTOR_100P, false); | |
| 37 } | |
| 38 | |
| 39 Canvas::Canvas(const gfx::Size& size, | 25 Canvas::Canvas(const gfx::Size& size, |
| 40 ui::ScaleFactor scale_factor, | 26 ui::ScaleFactor scale_factor, |
| 41 bool is_opaque) { | 27 bool is_opaque) |
| 28 : scale_factor_(scale_factor), |
| 29 owned_canvas_(NULL), |
| 30 canvas_(NULL) { |
| 42 gfx::Size pixel_size = size.Scale(ui::GetScaleFactorScale(scale_factor)); | 31 gfx::Size pixel_size = size.Scale(ui::GetScaleFactorScale(scale_factor)); |
| 43 owned_canvas_.reset(new skia::PlatformCanvas(pixel_size.width(), | 32 owned_canvas_.reset(new skia::PlatformCanvas(pixel_size.width(), |
| 44 pixel_size.height(), | 33 pixel_size.height(), |
| 45 is_opaque)); | 34 is_opaque)); |
| 46 canvas_ = owned_canvas_.get(); | 35 canvas_ = owned_canvas_.get(); |
| 47 #if defined(OS_WIN) || defined(OS_MACOSX) | 36 #if defined(OS_WIN) || defined(OS_MACOSX) |
| 48 // skia::PlatformCanvas instances are initialized to 0 by Cairo on Linux, but | 37 // skia::PlatformCanvas instances are initialized to 0 by Cairo on Linux, but |
| 49 // uninitialized on Win and Mac. | 38 // uninitialized on Win and Mac. |
| 50 if (!is_opaque) | 39 if (!is_opaque) |
| 51 owned_canvas_->clear(SkColorSetARGB(0, 0, 0, 0)); | 40 owned_canvas_->clear(SkColorSetARGB(0, 0, 0, 0)); |
| 52 #endif | 41 #endif |
| 53 | 42 |
| 54 ApplyScaleFactor(scale_factor, true); | 43 SkScalar scale = SkFloatToScalar(ui::GetScaleFactorScale(scale_factor)); |
| 44 canvas_->scale(scale, scale); |
| 55 } | 45 } |
| 56 | 46 |
| 57 Canvas::Canvas(const gfx::ImageSkiaRep& image_rep, bool is_opaque) | 47 Canvas::Canvas(const gfx::ImageSkiaRep& image_rep, bool is_opaque) |
| 58 : owned_canvas_(new skia::PlatformCanvas(image_rep.pixel_width(), | 48 : scale_factor_(image_rep.scale_factor()), |
| 49 owned_canvas_(new skia::PlatformCanvas(image_rep.pixel_width(), |
| 59 image_rep.pixel_height(), | 50 image_rep.pixel_height(), |
| 60 is_opaque)), | 51 is_opaque)), |
| 61 canvas_(owned_canvas_.get()) { | 52 canvas_(owned_canvas_.get()) { |
| 62 ApplyScaleFactor(image_rep.scale_factor(), true); | 53 SkScalar scale = SkFloatToScalar(ui::GetScaleFactorScale(scale_factor_)); |
| 54 canvas_->scale(scale, scale); |
| 63 DrawImageInt(gfx::ImageSkia(image_rep), 0, 0); | 55 DrawImageInt(gfx::ImageSkia(image_rep), 0, 0); |
| 64 } | 56 } |
| 65 | 57 |
| 66 Canvas::Canvas() | 58 Canvas::Canvas() |
| 67 : owned_canvas_(new skia::PlatformCanvas()), | 59 : scale_factor_(ui::SCALE_FACTOR_100P), |
| 60 owned_canvas_(new skia::PlatformCanvas()), |
| 68 canvas_(owned_canvas_.get()) { | 61 canvas_(owned_canvas_.get()) { |
| 69 ApplyScaleFactor(ui::SCALE_FACTOR_100P, false); | |
| 70 } | |
| 71 | |
| 72 Canvas::Canvas(SkCanvas* canvas, | |
| 73 ui::ScaleFactor scale_factor, | |
| 74 bool scale_canvas) | |
| 75 : owned_canvas_(), | |
| 76 canvas_(canvas) { | |
| 77 DCHECK(canvas); | |
| 78 ApplyScaleFactor(scale_factor, scale_canvas); | |
| 79 } | 62 } |
| 80 | 63 |
| 81 Canvas::~Canvas() { | 64 Canvas::~Canvas() { |
| 82 if (scale_factor_scales_canvas_) { | 65 } |
| 83 SkScalar scale = 1.0f / ui::GetScaleFactorScale(scale_factor_); | 66 |
| 84 canvas_->scale(scale, scale); | 67 // static |
| 85 } | 68 Canvas* Canvas::CreateCanvasWithoutScaling(SkCanvas* canvas, |
| 69 ui::ScaleFactor scale_factor) { |
| 70 return new Canvas(canvas, scale_factor); |
| 86 } | 71 } |
| 87 | 72 |
| 88 void Canvas::RecreateBackingCanvas(const gfx::Size& size, | 73 void Canvas::RecreateBackingCanvas(const gfx::Size& size, |
| 89 ui::ScaleFactor scale_factor, | 74 ui::ScaleFactor scale_factor, |
| 90 bool is_opaque) { | 75 bool is_opaque) { |
| 76 scale_factor_ = scale_factor; |
| 91 gfx::Size pixel_size = size.Scale(ui::GetScaleFactorScale(scale_factor)); | 77 gfx::Size pixel_size = size.Scale(ui::GetScaleFactorScale(scale_factor)); |
| 92 owned_canvas_.reset(new skia::PlatformCanvas(pixel_size.width(), | 78 owned_canvas_.reset(new skia::PlatformCanvas(pixel_size.width(), |
| 93 pixel_size.height(), | 79 pixel_size.height(), |
| 94 is_opaque)); | 80 is_opaque)); |
| 95 canvas_ = owned_canvas_.get(); | 81 canvas_ = owned_canvas_.get(); |
| 96 | 82 SkScalar scale = SkFloatToScalar(ui::GetScaleFactorScale(scale_factor_)); |
| 97 ApplyScaleFactor(scale_factor, true); | 83 canvas_->scale(scale, scale); |
| 98 } | 84 } |
| 99 | 85 |
| 100 // static | 86 // static |
| 101 int Canvas::GetStringWidth(const string16& text, const gfx::Font& font) { | 87 int Canvas::GetStringWidth(const string16& text, const gfx::Font& font) { |
| 102 int width = 0, height = 0; | 88 int width = 0, height = 0; |
| 103 Canvas::SizeStringInt(text, font, &width, &height, NO_ELLIPSIS); | 89 Canvas::SizeStringInt(text, font, &width, &height, NO_ELLIPSIS); |
| 104 return width; | 90 return width; |
| 105 } | 91 } |
| 106 | 92 |
| 107 // static | 93 // static |
| 108 int Canvas::DefaultCanvasTextAlignment() { | 94 int Canvas::DefaultCanvasTextAlignment() { |
| 109 return base::i18n::IsRTL() ? TEXT_ALIGN_RIGHT : TEXT_ALIGN_LEFT; | 95 return base::i18n::IsRTL() ? TEXT_ALIGN_RIGHT : TEXT_ALIGN_LEFT; |
| 110 } | 96 } |
| 111 | 97 |
| 112 SkBitmap Canvas::ExtractBitmap() const { | 98 gfx::ImageSkiaRep Canvas::ExtractImageRep() const { |
| 113 const SkBitmap& device_bitmap = canvas_->getDevice()->accessBitmap(false); | 99 const SkBitmap& device_bitmap = canvas_->getDevice()->accessBitmap(false); |
| 114 | 100 |
| 115 // Make a bitmap to return, and a canvas to draw into it. We don't just want | 101 // Make a bitmap to return, and a canvas to draw into it. We don't just want |
| 116 // to call extractSubset or the copy constructor, since we want an actual copy | 102 // to call extractSubset or the copy constructor, since we want an actual copy |
| 117 // of the bitmap. | 103 // of the bitmap. |
| 118 SkBitmap result; | 104 SkBitmap result; |
| 119 device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config); | 105 device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config); |
| 120 return result; | |
| 121 } | |
| 122 | 106 |
| 123 gfx::ImageSkiaRep Canvas::ExtractImageSkiaRep() const { | 107 return gfx::ImageSkiaRep(result, scale_factor_); |
| 124 return gfx::ImageSkiaRep(ExtractBitmap(), scale_factor_); | |
| 125 } | 108 } |
| 126 | 109 |
| 127 void Canvas::DrawDashedRect(const gfx::Rect& rect, SkColor color) { | 110 void Canvas::DrawDashedRect(const gfx::Rect& rect, SkColor color) { |
| 128 // Create a 2D bitmap containing alternating on/off pixels - we do this | 111 // Create a 2D bitmap containing alternating on/off pixels - we do this |
| 129 // so that you never get two pixels of the same color around the edges | 112 // so that you never get two pixels of the same color around the edges |
| 130 // of the focus rect (this may mean that opposing edges of the rect may | 113 // of the focus rect (this may mean that opposing edges of the rect may |
| 131 // have a dot pattern out of phase to each other). | 114 // have a dot pattern out of phase to each other). |
| 132 static SkColor last_color; | 115 static SkColor last_color; |
| 133 static SkBitmap* dots = NULL; | 116 static SkBitmap* dots = NULL; |
| 134 if (!dots || last_color != color) { | 117 if (!dots || last_color != color) { |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 } | 477 } |
| 495 | 478 |
| 496 void Canvas::EndPlatformPaint() { | 479 void Canvas::EndPlatformPaint() { |
| 497 skia::EndPlatformPaint(canvas_); | 480 skia::EndPlatformPaint(canvas_); |
| 498 } | 481 } |
| 499 | 482 |
| 500 void Canvas::Transform(const ui::Transform& transform) { | 483 void Canvas::Transform(const ui::Transform& transform) { |
| 501 canvas_->concat(transform.matrix()); | 484 canvas_->concat(transform.matrix()); |
| 502 } | 485 } |
| 503 | 486 |
| 487 Canvas::Canvas(SkCanvas* canvas, ui::ScaleFactor scale_factor) |
| 488 : scale_factor_(scale_factor), |
| 489 owned_canvas_(), |
| 490 canvas_(canvas) { |
| 491 DCHECK(canvas); |
| 492 } |
| 493 |
| 504 bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) { | 494 bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) { |
| 505 SkRect clip; | 495 SkRect clip; |
| 506 return canvas_->getClipBounds(&clip) && | 496 return canvas_->getClipBounds(&clip) && |
| 507 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), | 497 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), |
| 508 SkIntToScalar(y + h)); | 498 SkIntToScalar(y + h)); |
| 509 } | 499 } |
| 510 | 500 |
| 511 bool Canvas::IntersectsClipRect(const gfx::Rect& rect) { | 501 bool Canvas::IntersectsClipRect(const gfx::Rect& rect) { |
| 512 return IntersectsClipRectInt(rect.x(), rect.y(), | 502 return IntersectsClipRectInt(rect.x(), rect.y(), |
| 513 rect.width(), rect.height()); | 503 rect.width(), rect.height()); |
| 514 } | 504 } |
| 515 | 505 |
| 516 void Canvas::ApplyScaleFactor(ui::ScaleFactor scale_factor, | |
| 517 bool scale_canvas) { | |
| 518 scale_factor_scales_canvas_ = scale_canvas; | |
| 519 scale_factor_ = scale_factor; | |
| 520 if (scale_canvas) { | |
| 521 SkScalar scale = SkFloatToScalar(ui::GetScaleFactorScale(scale_factor)); | |
| 522 canvas_->scale(scale, scale); | |
| 523 } | |
| 524 } | |
| 525 | |
| 526 const gfx::ImageSkiaRep& Canvas::GetImageRepToPaint( | 506 const gfx::ImageSkiaRep& Canvas::GetImageRepToPaint( |
| 527 const gfx::ImageSkia& image) const { | 507 const gfx::ImageSkia& image) const { |
| 528 return GetImageRepToPaint(image, 1.0f, 1.0f); | 508 return GetImageRepToPaint(image, 1.0f, 1.0f); |
| 529 } | 509 } |
| 530 | 510 |
| 531 const gfx::ImageSkiaRep& Canvas::GetImageRepToPaint( | 511 const gfx::ImageSkiaRep& Canvas::GetImageRepToPaint( |
| 532 const gfx::ImageSkia& image, | 512 const gfx::ImageSkia& image, |
| 533 float user_additional_scale_x, | 513 float user_additional_scale_x, |
| 534 float user_additional_scale_y) const { | 514 float user_additional_scale_y) const { |
| 535 const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(scale_factor_); | 515 const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(scale_factor_); |
| 536 | 516 |
| 537 if (!image_rep.is_null()) { | 517 if (!image_rep.is_null()) { |
| 538 SkMatrix m = canvas_->getTotalMatrix(); | 518 SkMatrix m = canvas_->getTotalMatrix(); |
| 539 float scale_x = SkScalarToFloat(SkScalarAbs(m.getScaleX())) * | 519 float scale_x = SkScalarToFloat(SkScalarAbs(m.getScaleX())) * |
| 540 user_additional_scale_x; | 520 user_additional_scale_x; |
| 541 float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())) * | 521 float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())) * |
| 542 user_additional_scale_y; | 522 user_additional_scale_y; |
| 543 | 523 |
| 544 float bitmap_scale = image_rep.GetScale(); | 524 float bitmap_scale = image_rep.GetScale(); |
| 545 if (scale_x < bitmap_scale || scale_y < bitmap_scale) | 525 if (scale_x < bitmap_scale || scale_y < bitmap_scale) |
| 546 const_cast<SkBitmap&>(image_rep.sk_bitmap()).buildMipMap(); | 526 const_cast<SkBitmap&>(image_rep.sk_bitmap()).buildMipMap(); |
| 547 } | 527 } |
| 548 | 528 |
| 549 return image_rep; | 529 return image_rep; |
| 550 } | 530 } |
| 551 | 531 |
| 552 } // namespace gfx | 532 } // namespace gfx |
| OLD | NEW |