Home | History | Annotate | Download | only in gfx
      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
      3 // found in the LICENSE file.
      4 
      5 #include "ui/gfx/canvas.h"
      6 
      7 #include <cmath>
      8 #include <limits>
      9 
     10 #include "base/i18n/rtl.h"
     11 #include "base/logging.h"
     12 #include "third_party/skia/include/core/SkBitmap.h"
     13 #include "third_party/skia/include/effects/SkGradientShader.h"
     14 #include "ui/gfx/canvas.h"
     15 #include "ui/gfx/font_list.h"
     16 #include "ui/gfx/rect.h"
     17 #include "ui/gfx/size_conversions.h"
     18 #include "ui/gfx/skia_util.h"
     19 #include "ui/gfx/transform.h"
     20 
     21 #if defined(OS_WIN)
     22 #include "ui/gfx/canvas_skia_paint.h"
     23 #endif
     24 
     25 namespace gfx {
     26 
     27 Canvas::Canvas(const Size& size, float image_scale, bool is_opaque)
     28     : image_scale_(image_scale),
     29       canvas_(NULL) {
     30   Size pixel_size = ToCeiledSize(ScaleSize(size, image_scale));
     31   owned_canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(),
     32                                                             pixel_size.height(),
     33                                                             is_opaque));
     34   canvas_ = owned_canvas_.get();
     35 #if defined(OS_WIN) || defined(OS_MACOSX)
     36   // skia::PlatformCanvas instances are initialized to 0 by Cairo on Linux, but
     37   // uninitialized on Win and Mac.
     38   if (!is_opaque)
     39     owned_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
     40 #endif
     41 
     42   SkScalar scale_scalar = SkFloatToScalar(image_scale);
     43   canvas_->scale(scale_scalar, scale_scalar);
     44 }
     45 
     46 Canvas::Canvas(const ImageSkiaRep& image_rep, bool is_opaque)
     47     : image_scale_(image_rep.scale()),
     48       owned_canvas_(skia::AdoptRef(
     49           skia::CreatePlatformCanvas(image_rep.pixel_width(),
     50                                      image_rep.pixel_height(),
     51                                      is_opaque))),
     52       canvas_(owned_canvas_.get()) {
     53   SkScalar scale_scalar = SkFloatToScalar(image_scale_);
     54   canvas_->scale(scale_scalar, scale_scalar);
     55   DrawImageInt(ImageSkia(image_rep), 0, 0);
     56 }
     57 
     58 Canvas::Canvas()
     59     : image_scale_(1.0),
     60       owned_canvas_(skia::AdoptRef(skia::CreatePlatformCanvas(0, 0, false))),
     61       canvas_(owned_canvas_.get()) {
     62 }
     63 
     64 Canvas::~Canvas() {
     65 }
     66 
     67 // static
     68 Canvas* Canvas::CreateCanvasWithoutScaling(SkCanvas* canvas,
     69                                            float image_scale) {
     70   return new Canvas(canvas, image_scale);
     71 }
     72 
     73 void Canvas::RecreateBackingCanvas(const Size& size,
     74                                    float image_scale,
     75                                    bool is_opaque) {
     76   image_scale_ = image_scale;
     77   Size pixel_size = ToFlooredSize(ScaleSize(size, image_scale));
     78   owned_canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(),
     79                                                             pixel_size.height(),
     80                                                             is_opaque));
     81   canvas_ = owned_canvas_.get();
     82   SkScalar scale_scalar = SkFloatToScalar(image_scale);
     83   canvas_->scale(scale_scalar, scale_scalar);
     84 }
     85 
     86 // static
     87 void Canvas::SizeStringInt(const base::string16& text,
     88                            const FontList& font_list,
     89                            int* width,
     90                            int* height,
     91                            int line_height,
     92                            int flags) {
     93   float fractional_width = *width;
     94   float factional_height = *height;
     95   SizeStringFloat(text, font_list, &fractional_width,
     96                   &factional_height, line_height, flags);
     97   *width = std::ceil(fractional_width);
     98   *height = std::ceil(factional_height);
     99 }
    100 
    101 // static
    102 void Canvas::SizeStringInt(const base::string16& text,
    103                            const Font& font,
    104                            int* width,
    105                            int* height,
    106                            int line_height,
    107                            int flags) {
    108   SizeStringInt(text, FontList(font), width, height, line_height, flags);
    109 }
    110 
    111 // static
    112 int Canvas::GetStringWidth(const base::string16& text,
    113                            const FontList& font_list) {
    114   int width = 0, height = 0;
    115   SizeStringInt(text, font_list, &width, &height, 0, NO_ELLIPSIS);
    116   return width;
    117 }
    118 
    119 // static
    120 float Canvas::GetStringWidthF(const base::string16& text,
    121                               const FontList& font_list) {
    122   float width = 0, height = 0;
    123   SizeStringFloat(text, font_list, &width, &height, 0, NO_ELLIPSIS);
    124   return width;
    125 }
    126 
    127 // static
    128 int Canvas::GetStringWidth(const base::string16& text, const Font& font) {
    129   int width = 0, height = 0;
    130   SizeStringInt(text, FontList(font), &width, &height, 0, NO_ELLIPSIS);
    131   return width;
    132 }
    133 
    134 // static
    135 int Canvas::DefaultCanvasTextAlignment() {
    136   return base::i18n::IsRTL() ? TEXT_ALIGN_RIGHT : TEXT_ALIGN_LEFT;
    137 }
    138 
    139 void Canvas::DrawStringWithHalo(const base::string16& text,
    140                                 const Font& font,
    141                                 SkColor text_color,
    142                                 SkColor halo_color_in,
    143                                 int x,
    144                                 int y,
    145                                 int w,
    146                                 int h,
    147                                 int flags) {
    148   DrawStringRectWithHalo(text, FontList(font), text_color, halo_color_in,
    149                          Rect(x, y, w, h), flags);
    150 }
    151 
    152 ImageSkiaRep Canvas::ExtractImageRep() const {
    153   const SkBitmap& device_bitmap = canvas_->getDevice()->accessBitmap(false);
    154 
    155   // Make a bitmap to return, and a canvas to draw into it. We don't just want
    156   // to call extractSubset or the copy constructor, since we want an actual copy
    157   // of the bitmap.
    158   SkBitmap result;
    159   device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config);
    160 
    161   return ImageSkiaRep(result, image_scale_);
    162 }
    163 
    164 void Canvas::DrawDashedRect(const Rect& rect, SkColor color) {
    165   // Create a 2D bitmap containing alternating on/off pixels - we do this
    166   // so that you never get two pixels of the same color around the edges
    167   // of the focus rect (this may mean that opposing edges of the rect may
    168   // have a dot pattern out of phase to each other).
    169   static SkColor last_color;
    170   static SkBitmap* dots = NULL;
    171   if (!dots || last_color != color) {
    172     int col_pixels = 32;
    173     int row_pixels = 32;
    174 
    175     delete dots;
    176     last_color = color;
    177     dots = new SkBitmap;
    178     dots->setConfig(SkBitmap::kARGB_8888_Config, col_pixels, row_pixels);
    179     dots->allocPixels();
    180     dots->eraseARGB(0, 0, 0, 0);
    181 
    182     uint32_t* dot = dots->getAddr32(0, 0);
    183     for (int i = 0; i < row_pixels; i++) {
    184       for (int u = 0; u < col_pixels; u++) {
    185         if ((u % 2 + i % 2) % 2 != 0) {
    186           dot[i * row_pixels + u] = color;
    187         }
    188       }
    189     }
    190   }
    191 
    192   // Make a shader for the bitmap with an origin of the box we'll draw. This
    193   // shader is refcounted and will have an initial refcount of 1.
    194   skia::RefPtr<SkShader> shader = skia::AdoptRef(
    195       SkShader::CreateBitmapShader(
    196           *dots, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
    197   // Assign the shader to the paint & release our reference. The paint will
    198   // now own the shader and the shader will be destroyed when the paint goes
    199   // out of scope.
    200   SkPaint paint;
    201   paint.setShader(shader.get());
    202 
    203   DrawRect(Rect(rect.x(), rect.y(), rect.width(), 1), paint);
    204   DrawRect(Rect(rect.x(), rect.y() + rect.height() - 1, rect.width(), 1),
    205            paint);
    206   DrawRect(Rect(rect.x(), rect.y(), 1, rect.height()), paint);
    207   DrawRect(Rect(rect.x() + rect.width() - 1, rect.y(), 1, rect.height()),
    208            paint);
    209 }
    210 
    211 void Canvas::Save() {
    212   canvas_->save();
    213 }
    214 
    215 void Canvas::SaveLayerAlpha(uint8 alpha) {
    216   canvas_->saveLayerAlpha(NULL, alpha);
    217 }
    218 
    219 
    220 void Canvas::SaveLayerAlpha(uint8 alpha, const Rect& layer_bounds) {
    221   SkRect bounds(RectToSkRect(layer_bounds));
    222   canvas_->saveLayerAlpha(&bounds, alpha);
    223 }
    224 
    225 void Canvas::Restore() {
    226   canvas_->restore();
    227 }
    228 
    229 bool Canvas::ClipRect(const Rect& rect) {
    230   return canvas_->clipRect(RectToSkRect(rect));
    231 }
    232 
    233 bool Canvas::ClipPath(const SkPath& path) {
    234   return canvas_->clipPath(path);
    235 }
    236 
    237 bool Canvas::GetClipBounds(Rect* bounds) {
    238   SkRect out;
    239   bool has_non_empty_clip = canvas_->getClipBounds(&out);
    240   bounds->SetRect(out.left(), out.top(), out.width(), out.height());
    241   return has_non_empty_clip;
    242 }
    243 
    244 void Canvas::Translate(const Vector2d& offset) {
    245   canvas_->translate(SkIntToScalar(offset.x()), SkIntToScalar(offset.y()));
    246 }
    247 
    248 void Canvas::Scale(int x_scale, int y_scale) {
    249   canvas_->scale(SkIntToScalar(x_scale), SkIntToScalar(y_scale));
    250 }
    251 
    252 void Canvas::DrawColor(SkColor color) {
    253   DrawColor(color, SkXfermode::kSrcOver_Mode);
    254 }
    255 
    256 void Canvas::DrawColor(SkColor color, SkXfermode::Mode mode) {
    257   canvas_->drawColor(color, mode);
    258 }
    259 
    260 void Canvas::FillRect(const Rect& rect, SkColor color) {
    261   FillRect(rect, color, SkXfermode::kSrcOver_Mode);
    262 }
    263 
    264 void Canvas::FillRect(const Rect& rect,
    265                       SkColor color,
    266                       SkXfermode::Mode mode) {
    267   SkPaint paint;
    268   paint.setColor(color);
    269   paint.setStyle(SkPaint::kFill_Style);
    270   paint.setXfermodeMode(mode);
    271   DrawRect(rect, paint);
    272 }
    273 
    274 void Canvas::DrawRect(const Rect& rect, SkColor color) {
    275   DrawRect(rect, color, SkXfermode::kSrcOver_Mode);
    276 }
    277 
    278 void Canvas::DrawRect(const Rect& rect,
    279                       SkColor color,
    280                       SkXfermode::Mode mode) {
    281   SkPaint paint;
    282   paint.setColor(color);
    283   paint.setStyle(SkPaint::kStroke_Style);
    284   // Set a stroke width of 0, which will put us down the stroke rect path.  If
    285   // we set a stroke width of 1, for example, this will internally create a
    286   // path and fill it, which causes problems near the edge of the canvas.
    287   paint.setStrokeWidth(SkIntToScalar(0));
    288   paint.setXfermodeMode(mode);
    289 
    290   DrawRect(rect, paint);
    291 }
    292 
    293 void Canvas::DrawRect(const Rect& rect, const SkPaint& paint) {
    294   canvas_->drawIRect(RectToSkIRect(rect), paint);
    295 }
    296 
    297 void Canvas::DrawPoint(const Point& p1, const SkPaint& paint) {
    298   canvas_->drawPoint(SkIntToScalar(p1.x()), SkIntToScalar(p1.y()), paint);
    299 }
    300 
    301 void Canvas::DrawLine(const Point& p1, const Point& p2, SkColor color) {
    302   SkPaint paint;
    303   paint.setColor(color);
    304   paint.setStrokeWidth(SkIntToScalar(1));
    305   DrawLine(p1, p2, paint);
    306 }
    307 
    308 void Canvas::DrawLine(const Point& p1, const Point& p2, const SkPaint& paint) {
    309   canvas_->drawLine(SkIntToScalar(p1.x()), SkIntToScalar(p1.y()),
    310                     SkIntToScalar(p2.x()), SkIntToScalar(p2.y()), paint);
    311 }
    312 
    313 void Canvas::DrawCircle(const Point& center_point,
    314                         int radius,
    315                         const SkPaint& paint) {
    316   canvas_->drawCircle(SkIntToScalar(center_point.x()),
    317       SkIntToScalar(center_point.y()), SkIntToScalar(radius), paint);
    318 }
    319 
    320 void Canvas::DrawRoundRect(const Rect& rect,
    321                            int radius,
    322                            const SkPaint& paint) {
    323   canvas_->drawRoundRect(RectToSkRect(rect), SkIntToScalar(radius),
    324                          SkIntToScalar(radius), paint);
    325 }
    326 
    327 void Canvas::DrawPath(const SkPath& path, const SkPaint& paint) {
    328   canvas_->drawPath(path, paint);
    329 }
    330 
    331 void Canvas::DrawFocusRect(const Rect& rect) {
    332   DrawDashedRect(rect, SK_ColorGRAY);
    333 }
    334 
    335 void Canvas::DrawSolidFocusRect(const Rect& rect, SkColor color) {
    336   SkPaint paint;
    337   paint.setColor(color);
    338   paint.setStrokeWidth(SkIntToScalar(1));
    339   // Note: We cannot use DrawRect since it would create a path and fill it which
    340   // would cause problems near the edge of the canvas.
    341   int x1 = std::min(rect.x(), rect.right());
    342   int x2 = std::max(rect.x(), rect.right());
    343   int y1 = std::min(rect.y(), rect.bottom());
    344   int y2 = std::max(rect.y(), rect.bottom());
    345   DrawLine(Point(x1, y1), Point(x2, y1), paint);
    346   DrawLine(Point(x1, y2), Point(x2, y2), paint);
    347   DrawLine(Point(x1, y1), Point(x1, y2), paint);
    348   DrawLine(Point(x2, y1), Point(x2, y2 + 1), paint);
    349 }
    350 
    351 void Canvas::DrawImageInt(const ImageSkia& image, int x, int y) {
    352   SkPaint paint;
    353   DrawImageInt(image, x, y, paint);
    354 }
    355 
    356 void Canvas::DrawImageInt(const ImageSkia& image, int x, int y, uint8 a) {
    357   SkPaint paint;
    358   paint.setAlpha(a);
    359   DrawImageInt(image, x, y, paint);
    360 }
    361 
    362 void Canvas::DrawImageInt(const ImageSkia& image,
    363                           int x,
    364                           int y,
    365                           const SkPaint& paint) {
    366   const ImageSkiaRep& image_rep = GetImageRepToPaint(image);
    367   if (image_rep.is_null())
    368     return;
    369   const SkBitmap& bitmap = image_rep.sk_bitmap();
    370   float bitmap_scale = image_rep.scale();
    371 
    372   canvas_->save();
    373   canvas_->scale(SkFloatToScalar(1.0f / bitmap_scale),
    374                  SkFloatToScalar(1.0f / bitmap_scale));
    375   canvas_->drawBitmap(bitmap,
    376                       SkFloatToScalar(x * bitmap_scale),
    377                       SkFloatToScalar(y * bitmap_scale),
    378                       &paint);
    379   canvas_->restore();
    380 }
    381 
    382 void Canvas::DrawImageInt(const ImageSkia& image,
    383                           int src_x,
    384                           int src_y,
    385                           int src_w,
    386                           int src_h,
    387                           int dest_x,
    388                           int dest_y,
    389                           int dest_w,
    390                           int dest_h,
    391                           bool filter) {
    392   SkPaint p;
    393   DrawImageInt(image, src_x, src_y, src_w, src_h, dest_x, dest_y,
    394                dest_w, dest_h, filter, p);
    395 }
    396 
    397 void Canvas::DrawImageInt(const ImageSkia& image,
    398                           int src_x,
    399                           int src_y,
    400                           int src_w,
    401                           int src_h,
    402                           int dest_x,
    403                           int dest_y,
    404                           int dest_w,
    405                           int dest_h,
    406                           bool filter,
    407                           const SkPaint& paint) {
    408   DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() &&
    409               src_y + src_h < std::numeric_limits<int16_t>::max());
    410   if (src_w <= 0 || src_h <= 0) {
    411     NOTREACHED() << "Attempting to draw bitmap from an empty rect!";
    412     return;
    413   }
    414 
    415   if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h))
    416     return;
    417 
    418   float user_scale_x = static_cast<float>(dest_w) / src_w;
    419   float user_scale_y = static_cast<float>(dest_h) / src_h;
    420 
    421   const ImageSkiaRep& image_rep = GetImageRepToPaint(image,
    422       user_scale_x, user_scale_y);
    423   if (image_rep.is_null())
    424     return;
    425 
    426   SkRect dest_rect = { SkIntToScalar(dest_x),
    427                        SkIntToScalar(dest_y),
    428                        SkIntToScalar(dest_x + dest_w),
    429                        SkIntToScalar(dest_y + dest_h) };
    430 
    431   if (src_w == dest_w && src_h == dest_h &&
    432       user_scale_x == 1.0f && user_scale_y == 1.0f &&
    433       image_rep.scale() == 1.0f) {
    434     // Workaround for apparent bug in Skia that causes image to occasionally
    435     // shift.
    436     SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h };
    437     const SkBitmap& bitmap = image_rep.sk_bitmap();
    438     canvas_->drawBitmapRect(bitmap, &src_rect, dest_rect, &paint);
    439     return;
    440   }
    441 
    442   // Make a bitmap shader that contains the bitmap we want to draw. This is
    443   // basically what SkCanvas.drawBitmap does internally, but it gives us
    444   // more control over quality and will use the mipmap in the source image if
    445   // it has one, whereas drawBitmap won't.
    446   SkMatrix shader_scale;
    447   shader_scale.setScale(SkFloatToScalar(user_scale_x),
    448                         SkFloatToScalar(user_scale_y));
    449   shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
    450   shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
    451 
    452   skia::RefPtr<SkShader> shader = CreateImageRepShader(
    453       image_rep,
    454       SkShader::kRepeat_TileMode,
    455       shader_scale);
    456 
    457   // Set up our paint to use the shader & release our reference (now just owned
    458   // by the paint).
    459   SkPaint p(paint);
    460   p.setFilterBitmap(filter);
    461   p.setShader(shader.get());
    462 
    463   // The rect will be filled by the bitmap.
    464   canvas_->drawRect(dest_rect, p);
    465 }
    466 
    467 void Canvas::DrawImageInPath(const ImageSkia& image,
    468                              int x,
    469                              int y,
    470                              const SkPath& path,
    471                              const SkPaint& paint) {
    472   const ImageSkiaRep& image_rep = GetImageRepToPaint(image);
    473   if (image_rep.is_null())
    474     return;
    475 
    476   SkMatrix matrix;
    477   matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
    478   skia::RefPtr<SkShader> shader = CreateImageRepShader(
    479       image_rep,
    480       SkShader::kRepeat_TileMode,
    481       matrix);
    482 
    483   SkPaint p(paint);
    484   p.setShader(shader.get());
    485   canvas_->drawPath(path, p);
    486 }
    487 
    488 void Canvas::DrawStringRect(const base::string16& text,
    489                             const FontList& font_list,
    490                             SkColor color,
    491                             const Rect& display_rect) {
    492   DrawStringRectWithFlags(text, font_list, color, display_rect,
    493                           DefaultCanvasTextAlignment());
    494 }
    495 
    496 void Canvas::DrawStringRectWithFlags(const base::string16& text,
    497                                      const FontList& font_list,
    498                                      SkColor color,
    499                                      const Rect& display_rect,
    500                                      int flags) {
    501   DrawStringRectWithShadows(text, font_list, color, display_rect, 0, flags,
    502                             ShadowValues());
    503 }
    504 
    505 void Canvas::DrawStringInt(const base::string16& text,
    506                            const Font& font,
    507                            SkColor color,
    508                            int x,
    509                            int y,
    510                            int w,
    511                            int h) {
    512   DrawStringInt(text, font, color, x, y, w, h, DefaultCanvasTextAlignment());
    513 }
    514 
    515 void Canvas::DrawStringInt(const base::string16& text,
    516                            const Font& font,
    517                            SkColor color,
    518                            const Rect& display_rect) {
    519   DrawStringInt(text, font, color, display_rect.x(), display_rect.y(),
    520                 display_rect.width(), display_rect.height());
    521 }
    522 
    523 void Canvas::DrawStringInt(const base::string16& text,
    524                            const Font& font,
    525                            SkColor color,
    526                            int x,
    527                            int y,
    528                            int w,
    529                            int h,
    530                            int flags) {
    531   DrawStringWithShadows(text, font, color, Rect(x, y, w, h), 0, flags,
    532                         ShadowValues());
    533 }
    534 
    535 void Canvas::DrawStringWithShadows(const base::string16& text,
    536                                    const Font& font,
    537                                    SkColor color,
    538                                    const Rect& text_bounds,
    539                                    int line_height,
    540                                    int flags,
    541                                    const ShadowValues& shadows) {
    542   DrawStringRectWithShadows(text, FontList(font), color, text_bounds,
    543                             line_height, flags, shadows);
    544 }
    545 
    546 void Canvas::TileImageInt(const ImageSkia& image,
    547                           int x,
    548                           int y,
    549                           int w,
    550                           int h) {
    551   TileImageInt(image, 0, 0, x, y, w, h);
    552 }
    553 
    554 void Canvas::TileImageInt(const ImageSkia& image,
    555                           int src_x,
    556                           int src_y,
    557                           int dest_x,
    558                           int dest_y,
    559                           int w,
    560                           int h) {
    561   TileImageInt(image, src_x, src_y, 1.0f, 1.0f, dest_x, dest_y, w, h);
    562 }
    563 
    564 void Canvas::TileImageInt(const ImageSkia& image,
    565                           int src_x,
    566                           int src_y,
    567                           float tile_scale_x,
    568                           float tile_scale_y,
    569                           int dest_x,
    570                           int dest_y,
    571                           int w,
    572                           int h) {
    573   if (!IntersectsClipRectInt(dest_x, dest_y, w, h))
    574     return;
    575 
    576   const ImageSkiaRep& image_rep = GetImageRepToPaint(
    577       image, tile_scale_x, tile_scale_y);
    578   if (image_rep.is_null())
    579     return;
    580 
    581   SkMatrix shader_scale;
    582   shader_scale.setScale(SkFloatToScalar(tile_scale_x),
    583                         SkFloatToScalar(tile_scale_y));
    584   shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
    585   shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
    586 
    587   skia::RefPtr<SkShader> shader = CreateImageRepShader(
    588       image_rep,
    589       SkShader::kRepeat_TileMode,
    590       shader_scale);
    591 
    592   SkPaint paint;
    593   paint.setShader(shader.get());
    594   paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
    595 
    596   SkRect dest_rect = { SkIntToScalar(dest_x),
    597                        SkIntToScalar(dest_y),
    598                        SkIntToScalar(dest_x + w),
    599                        SkIntToScalar(dest_y + h) };
    600   canvas_->drawRect(dest_rect, paint);
    601 }
    602 
    603 NativeDrawingContext Canvas::BeginPlatformPaint() {
    604   return skia::BeginPlatformPaint(canvas_);
    605 }
    606 
    607 void Canvas::EndPlatformPaint() {
    608   skia::EndPlatformPaint(canvas_);
    609 }
    610 
    611 void Canvas::Transform(const gfx::Transform& transform) {
    612   canvas_->concat(transform.matrix());
    613 }
    614 
    615 Canvas::Canvas(SkCanvas* canvas, float image_scale)
    616     : image_scale_(image_scale),
    617       owned_canvas_(),
    618       canvas_(canvas) {
    619   DCHECK(canvas);
    620 }
    621 
    622 bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) {
    623   SkRect clip;
    624   return canvas_->getClipBounds(&clip) &&
    625       clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w),
    626                      SkIntToScalar(y + h));
    627 }
    628 
    629 bool Canvas::IntersectsClipRect(const Rect& rect) {
    630   return IntersectsClipRectInt(rect.x(), rect.y(),
    631                                rect.width(), rect.height());
    632 }
    633 
    634 const ImageSkiaRep& Canvas::GetImageRepToPaint(const ImageSkia& image) const {
    635   return GetImageRepToPaint(image, 1.0f, 1.0f);
    636 }
    637 
    638 const ImageSkiaRep& Canvas::GetImageRepToPaint(
    639     const ImageSkia& image,
    640     float user_additional_scale_x,
    641     float user_additional_scale_y) const {
    642   const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_);
    643 
    644   if (!image_rep.is_null()) {
    645     SkMatrix m = canvas_->getTotalMatrix();
    646     float scale_x = SkScalarToFloat(SkScalarAbs(m.getScaleX())) *
    647         user_additional_scale_x;
    648     float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())) *
    649         user_additional_scale_y;
    650 
    651     float bitmap_scale = image_rep.scale();
    652     if (scale_x < bitmap_scale || scale_y < bitmap_scale)
    653       const_cast<SkBitmap&>(image_rep.sk_bitmap()).buildMipMap();
    654   }
    655 
    656   return image_rep;
    657 }
    658 
    659 }  // namespace gfx
    660