Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright 2014 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkGatherPixelRefsAndRects_DEFINED
      9 #define SkGatherPixelRefsAndRects_DEFINED
     10 
     11 #include "SkBitmap.h"
     12 #include "SkDevice.h"
     13 #include "SkDraw.h"
     14 #include "SkPictureUtils.h"
     15 #include "SkRasterClip.h"
     16 #include "SkRefCnt.h"
     17 #include "SkRRect.h"
     18 #include "SkTypes.h"
     19 
     20 // This GatherPixelRefs device passes all discovered pixel refs and their
     21 // device bounds to the user provided SkPixelRefContainer-derived object
     22 class SkGatherPixelRefsAndRectsDevice : public SkBaseDevice {
     23 public:
     24     SK_DECLARE_INST_COUNT(SkGatherPixelRefsAndRectsDevice)
     25 
     26     SkGatherPixelRefsAndRectsDevice(int width, int height,
     27                                     SkPictureUtils::SkPixelRefContainer* prCont) {
     28         fSize.set(width, height);
     29         fPRCont = prCont;
     30         SkSafeRef(fPRCont);
     31         fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
     32     }
     33 
     34     virtual ~SkGatherPixelRefsAndRectsDevice() {
     35         SkSafeUnref(fPRCont);
     36     }
     37 
     38     virtual SkImageInfo imageInfo() const SK_OVERRIDE {
     39         return fEmptyBitmap.info();
     40     }
     41 
     42 protected:
     43     virtual void clear(SkColor color) SK_OVERRIDE {
     44         NothingToDo();
     45     }
     46     virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
     47         SkBitmap bm;
     48 
     49         if (GetBitmapFromPaint(paint, &bm)) {
     50             SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
     51             fPRCont->add(bm.pixelRef(), clipRect);
     52         }
     53     }
     54     virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
     55                             const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
     56         SkBitmap bm;
     57         if (!GetBitmapFromPaint(paint, &bm)) {
     58             return;
     59         }
     60 
     61         if (0 == count) {
     62             return;
     63         }
     64 
     65         SkPoint min = points[0];
     66         SkPoint max = points[0];
     67         for (size_t i = 1; i < count; ++i) {
     68             const SkPoint& point = points[i];
     69 
     70             min.set(SkMinScalar(min.x(), point.x()), SkMinScalar(min.y(), point.y()));
     71             max.set(SkMaxScalar(max.x(), point.x()), SkMaxScalar(max.y(), point.y()));
     72         }
     73 
     74         SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x()+1, max.y()+1);
     75 
     76         this->drawRect(draw, bounds, paint);
     77     }
     78     virtual void drawRect(const SkDraw& draw, const SkRect& rect,
     79                           const SkPaint& paint) SK_OVERRIDE {
     80         SkBitmap bm;
     81         if (GetBitmapFromPaint(paint, &bm)) {
     82             SkRect mappedRect;
     83             draw.fMatrix->mapRect(&mappedRect, rect);
     84             SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
     85             mappedRect.intersect(clipRect);
     86             fPRCont->add(bm.pixelRef(), mappedRect);
     87         }
     88     }
     89     virtual void drawOval(const SkDraw& draw, const SkRect& rect,
     90                           const SkPaint& paint) SK_OVERRIDE {
     91         this->drawRect(draw, rect, paint);
     92     }
     93     virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
     94                            const SkPaint& paint) SK_OVERRIDE {
     95         this->drawRect(draw, rrect.rect(), paint);
     96     }
     97     virtual void drawPath(const SkDraw& draw, const SkPath& path,
     98                           const SkPaint& paint, const SkMatrix* prePathMatrix,
     99                           bool pathIsMutable) SK_OVERRIDE {
    100         SkBitmap bm;
    101         if (!GetBitmapFromPaint(paint, &bm)) {
    102             return;
    103         }
    104 
    105         SkRect pathBounds = path.getBounds();
    106         if (prePathMatrix) {
    107             prePathMatrix->mapRect(&pathBounds);
    108         }
    109 
    110         this->drawRect(draw, pathBounds, paint);
    111     }
    112     virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
    113                             const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
    114         SkMatrix totMatrix;
    115         totMatrix.setConcat(*draw.fMatrix, matrix);
    116 
    117         SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
    118                                            SkIntToScalar(bitmap.height()));
    119         SkRect mappedRect;
    120         totMatrix.mapRect(&mappedRect, bitmapRect);
    121         fPRCont->add(bitmap.pixelRef(), mappedRect);
    122 
    123         SkBitmap paintBitmap;
    124         if (GetBitmapFromPaint(paint, &paintBitmap)) {
    125             fPRCont->add(paintBitmap.pixelRef(), mappedRect);
    126         }
    127     }
    128     virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
    129                             int x, int y, const SkPaint& paint) SK_OVERRIDE {
    130         // Sprites aren't affected by current matrix, so we can't reuse drawRect.
    131         SkMatrix matrix;
    132         matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
    133 
    134         SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
    135                                            SkIntToScalar(bitmap.height()));
    136         SkRect mappedRect;
    137         matrix.mapRect(&mappedRect, bitmapRect);
    138         fPRCont->add(bitmap.pixelRef(), mappedRect);
    139 
    140         SkBitmap paintBitmap;
    141         if (GetBitmapFromPaint(paint, &paintBitmap)) {
    142             fPRCont->add(paintBitmap.pixelRef(), mappedRect);
    143         }
    144     }
    145     virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
    146                                 const SkRect* srcOrNull, const SkRect& dst,
    147                                 const SkPaint& paint,
    148                                 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
    149         SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
    150                                            SkIntToScalar(bitmap.height()));
    151         SkMatrix matrix;
    152         matrix.setRectToRect(bitmapRect, dst, SkMatrix::kFill_ScaleToFit);
    153         this->drawBitmap(draw, bitmap, matrix, paint);
    154     }
    155     virtual void drawText(const SkDraw& draw, const void* text, size_t len,
    156                           SkScalar x, SkScalar y,
    157                           const SkPaint& paint) SK_OVERRIDE {
    158         SkBitmap bitmap;
    159         if (!GetBitmapFromPaint(paint, &bitmap)) {
    160             return;
    161         }
    162 
    163         // Math is borrowed from SkBBoxRecord
    164         SkRect bounds;
    165         paint.measureText(text, len, &bounds);
    166         SkPaint::FontMetrics metrics;
    167         paint.getFontMetrics(&metrics);
    168 
    169         if (paint.isVerticalText()) {
    170             SkScalar h = bounds.fBottom - bounds.fTop;
    171             if (paint.getTextAlign() == SkPaint::kCenter_Align) {
    172                 bounds.fTop -= h / 2;
    173                 bounds.fBottom -= h / 2;
    174             }
    175             bounds.fBottom += metrics.fBottom;
    176             bounds.fTop += metrics.fTop;
    177         } else {
    178             SkScalar w = bounds.fRight - bounds.fLeft;
    179             if (paint.getTextAlign() == SkPaint::kCenter_Align) {
    180                 bounds.fLeft -= w / 2;
    181                 bounds.fRight -= w / 2;
    182             } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
    183                 bounds.fLeft -= w;
    184                 bounds.fRight -= w;
    185             }
    186             bounds.fTop = metrics.fTop;
    187             bounds.fBottom = metrics.fBottom;
    188         }
    189 
    190         SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
    191         bounds.fLeft -= pad;
    192         bounds.fRight += pad;
    193         bounds.offset(x, y);
    194 
    195         this->drawRect(draw, bounds, paint);
    196     }
    197     virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
    198                              const SkScalar pos[], SkScalar constY,
    199                              int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
    200         SkBitmap bitmap;
    201         if (!GetBitmapFromPaint(paint, &bitmap)) {
    202             return;
    203         }
    204 
    205         if (0 == len) {
    206             return;
    207         }
    208 
    209         // Similar to SkDraw asserts.
    210         SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2);
    211 
    212         SkScalar y = scalarsPerPos == 1 ? constY : constY + pos[1];
    213 
    214         SkPoint min, max;
    215         min.set(pos[0], y);
    216         max.set(pos[0], y);
    217 
    218         for (size_t i = 1; i < len; ++i) {
    219             SkScalar x = pos[i * scalarsPerPos];
    220             SkScalar y = constY;
    221             if (2 == scalarsPerPos) {
    222                 y += pos[i * scalarsPerPos + 1];
    223             }
    224 
    225             min.set(SkMinScalar(x, min.x()), SkMinScalar(y, min.y()));
    226             max.set(SkMaxScalar(x, max.x()), SkMaxScalar(y, max.y()));
    227         }
    228 
    229         SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x(), max.y());
    230 
    231         // Math is borrowed from SkBBoxRecord
    232         SkPaint::FontMetrics metrics;
    233         paint.getFontMetrics(&metrics);
    234 
    235         bounds.fTop += metrics.fTop;
    236         bounds.fBottom += metrics.fBottom;
    237 
    238         SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
    239         bounds.fLeft -= pad;
    240         bounds.fRight += pad;
    241 
    242         this->drawRect(draw, bounds, paint);
    243     }
    244     virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
    245                                 const SkPath& path, const SkMatrix* matrix,
    246                                 const SkPaint& paint) SK_OVERRIDE {
    247         SkBitmap bitmap;
    248         if (!GetBitmapFromPaint(paint, &bitmap)) {
    249             return;
    250         }
    251 
    252         // Math is borrowed from SkBBoxRecord
    253         SkRect bounds = path.getBounds();
    254         SkPaint::FontMetrics metrics;
    255         paint.getFontMetrics(&metrics);
    256 
    257         SkScalar pad = metrics.fTop;
    258         // TODO: inset?!
    259         bounds.fLeft += pad;
    260         bounds.fRight -= pad;
    261         bounds.fTop += pad;
    262         bounds.fBottom -= pad;
    263 
    264         this->drawRect(draw, bounds, paint);
    265     }
    266     virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
    267                               const SkPoint verts[], const SkPoint texs[],
    268                               const SkColor colors[], SkXfermode* xmode,
    269                               const uint16_t indices[], int indexCount,
    270                               const SkPaint& paint) SK_OVERRIDE {
    271         this->drawPoints(draw, SkCanvas::kPolygon_PointMode, vertexCount, verts, paint);
    272     }
    273     virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
    274                             const SkPaint&) SK_OVERRIDE {
    275         NothingToDo();
    276     }
    277     // TODO: allow this call to return failure, or move to SkBitmapDevice only.
    278     virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
    279         return fEmptyBitmap;
    280     }
    281     virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
    282     virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
    283     virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
    284     virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
    285     virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
    286                              SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
    287         return false;
    288     }
    289 
    290 private:
    291     SkPictureUtils::SkPixelRefContainer* fPRCont;
    292     SkISize                              fSize;
    293 
    294     SkBitmap                             fEmptyBitmap; // legacy -- need to remove
    295 
    296     static bool GetBitmapFromPaint(const SkPaint &paint, SkBitmap* bitmap) {
    297         SkShader* shader = paint.getShader();
    298         if (shader) {
    299             if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) {
    300                 return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, NULL, NULL);
    301             }
    302         }
    303         return false;
    304     }
    305 
    306     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
    307         NotSupported();
    308     }
    309 
    310     virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
    311         // we expect to only get called via savelayer, in which case it is fine.
    312         SkASSERT(kSaveLayer_Usage == usage);
    313         return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice,
    314                           (info.width(), info.height(), fPRCont));
    315     }
    316 
    317     static void NotSupported() {
    318         SkDEBUGFAIL("this method should never be called");
    319     }
    320 
    321     static void NothingToDo() {}
    322 
    323     typedef SkBaseDevice INHERITED;
    324 };
    325 
    326 #endif // SkGatherPixelRefsAndRects_DEFINED
    327