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