156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com/*
256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com * Copyright 2014 Google Inc.
356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com *
456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com * found in the LICENSE file.
656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com */
756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#ifndef SkGatherPixelRefsAndRects_DEFINED
956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#define SkGatherPixelRefsAndRects_DEFINED
1056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
1156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#include "SkBitmap.h"
1256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#include "SkDevice.h"
1356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#include "SkDraw.h"
1456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#include "SkPictureUtils.h"
1556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#include "SkRasterClip.h"
1656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#include "SkRefCnt.h"
1756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#include "SkRRect.h"
1856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#include "SkTypes.h"
1956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
2056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com// This GatherPixelRefs device passes all discovered pixel refs and their
2156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com// device bounds to the user provided SkPixelRefContainer-derived object
2256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.comclass SkGatherPixelRefsAndRectsDevice : public SkBaseDevice {
2356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.compublic:
2456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    SK_DECLARE_INST_COUNT(SkGatherPixelRefsAndRectsDevice)
2556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
262e9a7157ee8ce47dae6e692162440c4f94a05574skia.committer@gmail.com    SkGatherPixelRefsAndRectsDevice(int width, int height,
2756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                    SkPictureUtils::SkPixelRefContainer* prCont) {
2856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        fSize.set(width, height);
2956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        fPRCont = prCont;
3056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkSafeRef(fPRCont);
31a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
3256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
3356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
3456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual ~SkGatherPixelRefsAndRectsDevice() {
3556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkSafeUnref(fPRCont);
3656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
3756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
3815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    virtual SkImageInfo imageInfo() const SK_OVERRIDE {
3915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        return fEmptyBitmap.info();
4015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    }
4115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org
4256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
4356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
4456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.comprotected:
4556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
4656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return false;
4756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
4856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void clear(SkColor color) SK_OVERRIDE {
4956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        NothingToDo();
5056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
5156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
5256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bm;
5356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
5456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (GetBitmapFromPaint(paint, &bm)) {
5556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
5656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            fPRCont->add(bm.pixelRef(), clipRect);
5756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
5856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
5956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
6056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                            const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
6156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bm;
6256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bm)) {
6356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
6456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
6556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
6656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (0 == count) {
6756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
6856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
6956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
7056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPoint min = points[0];
7156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPoint max = points[0];
7256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        for (size_t i = 1; i < count; ++i) {
7356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            const SkPoint& point = points[i];
7456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
7556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            min.set(SkMinScalar(min.x(), point.x()), SkMinScalar(min.y(), point.y()));
7656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            max.set(SkMaxScalar(max.x(), point.x()), SkMaxScalar(max.y(), point.y()));
7756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
7856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
7956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x()+1, max.y()+1);
8056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
8156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, bounds, paint);
8256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
8356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawRect(const SkDraw& draw, const SkRect& rect,
8456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          const SkPaint& paint) SK_OVERRIDE {
8556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bm;
8656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (GetBitmapFromPaint(paint, &bm)) {
8756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkRect mappedRect;
8856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            draw.fMatrix->mapRect(&mappedRect, rect);
8956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
9056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            mappedRect.intersect(clipRect);
9156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            fPRCont->add(bm.pixelRef(), mappedRect);
9256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
9356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
9456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawOval(const SkDraw& draw, const SkRect& rect,
9556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          const SkPaint& paint) SK_OVERRIDE {
9656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, rect, paint);
9756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
9856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
9956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                           const SkPaint& paint) SK_OVERRIDE {
10056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, rrect.rect(), paint);
10156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
10256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawPath(const SkDraw& draw, const SkPath& path,
10356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          const SkPaint& paint, const SkMatrix* prePathMatrix,
10456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          bool pathIsMutable) SK_OVERRIDE {
10556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bm;
10656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bm)) {
10756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
10856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
10956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
11056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect pathBounds = path.getBounds();
11156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (NULL != prePathMatrix) {
11256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            prePathMatrix->mapRect(&pathBounds);
1132e9a7157ee8ce47dae6e692162440c4f94a05574skia.committer@gmail.com        }
11456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
11556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, pathBounds, paint);
11656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
11756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
11856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                            const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
11956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkMatrix totMatrix;
12056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        totMatrix.setConcat(*draw.fMatrix, matrix);
12156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
1222e9a7157ee8ce47dae6e692162440c4f94a05574skia.committer@gmail.com        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
12356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                           SkIntToScalar(bitmap.height()));
12456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect mappedRect;
12556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        totMatrix.mapRect(&mappedRect, bitmapRect);
12656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        fPRCont->add(bitmap.pixelRef(), mappedRect);
12756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
12856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap paintBitmap;
12956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (GetBitmapFromPaint(paint, &paintBitmap)) {
13056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            fPRCont->add(paintBitmap.pixelRef(), mappedRect);
13156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
13256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
13356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
13456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                            int x, int y, const SkPaint& paint) SK_OVERRIDE {
13556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Sprites aren't affected by current matrix, so we can't reuse drawRect.
13656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkMatrix matrix;
13756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
13856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
1392e9a7157ee8ce47dae6e692162440c4f94a05574skia.committer@gmail.com        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
14056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                           SkIntToScalar(bitmap.height()));
14156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect mappedRect;
14256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        matrix.mapRect(&mappedRect, bitmapRect);
14356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        fPRCont->add(bitmap.pixelRef(), mappedRect);
14456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
14556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap paintBitmap;
14656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (GetBitmapFromPaint(paint, &paintBitmap)) {
14756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            fPRCont->add(paintBitmap.pixelRef(), mappedRect);
14856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
14956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
15056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
15156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                const SkRect* srcOrNull, const SkRect& dst,
15256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                const SkPaint& paint,
15356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
1542e9a7157ee8ce47dae6e692162440c4f94a05574skia.committer@gmail.com        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
15556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                           SkIntToScalar(bitmap.height()));
15656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkMatrix matrix;
15756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        matrix.setRectToRect(bitmapRect, dst, SkMatrix::kFill_ScaleToFit);
15856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawBitmap(draw, bitmap, matrix, paint);
15956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
16056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawText(const SkDraw& draw, const void* text, size_t len,
16156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          SkScalar x, SkScalar y,
16256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          const SkPaint& paint) SK_OVERRIDE {
16356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bitmap;
16456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bitmap)) {
16556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
16656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
16756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
16856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Math is borrowed from SkBBoxRecord
16956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bounds;
17056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        paint.measureText(text, len, &bounds);
17156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPaint::FontMetrics metrics;
17256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        paint.getFontMetrics(&metrics);
17356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
17456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (paint.isVerticalText()) {
17556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkScalar h = bounds.fBottom - bounds.fTop;
17656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            if (paint.getTextAlign() == SkPaint::kCenter_Align) {
17756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fTop -= h / 2;
17856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fBottom -= h / 2;
17956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            }
18056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            bounds.fBottom += metrics.fBottom;
18156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            bounds.fTop += metrics.fTop;
18256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        } else {
18356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkScalar w = bounds.fRight - bounds.fLeft;
18456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            if (paint.getTextAlign() == SkPaint::kCenter_Align) {
18556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fLeft -= w / 2;
18656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fRight -= w / 2;
18756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
18856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fLeft -= w;
18956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fRight -= w;
19056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            }
19156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            bounds.fTop = metrics.fTop;
19256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            bounds.fBottom = metrics.fBottom;
19356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
19456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
19556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
19656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fLeft -= pad;
19756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fRight += pad;
19856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.offset(x, y);
19956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
20056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, bounds, paint);
20156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
20256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
20356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                             const SkScalar pos[], SkScalar constY,
20456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                             int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
20556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bitmap;
20656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bitmap)) {
20756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
20856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
20956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
21056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (0 == len) {
21156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
21256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
21356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
21456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Similar to SkDraw asserts.
21556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2);
21656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
217f0a4013467dd5aab0b35ddc89f86ad9827ea49adrobertphillips@google.com        SkScalar y = scalarsPerPos == 1 ? constY : constY + pos[1];
218f0a4013467dd5aab0b35ddc89f86ad9827ea49adrobertphillips@google.com
21956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPoint min, max;
220f0a4013467dd5aab0b35ddc89f86ad9827ea49adrobertphillips@google.com        min.set(pos[0], y);
221f0a4013467dd5aab0b35ddc89f86ad9827ea49adrobertphillips@google.com        max.set(pos[0], y);
22256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
22356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        for (size_t i = 1; i < len; ++i) {
22456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkScalar x = pos[i * scalarsPerPos];
22556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkScalar y = constY;
22656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            if (2 == scalarsPerPos) {
22756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                y += pos[i * scalarsPerPos + 1];
22856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            }
22956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
23056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            min.set(SkMinScalar(x, min.x()), SkMinScalar(y, min.y()));
23156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            max.set(SkMaxScalar(x, max.x()), SkMaxScalar(y, max.y()));
23256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
23356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
23456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x(), max.y());
23556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
23656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Math is borrowed from SkBBoxRecord
23756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPaint::FontMetrics metrics;
23856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        paint.getFontMetrics(&metrics);
23956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
24056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fTop += metrics.fTop;
24156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fBottom += metrics.fBottom;
24256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
24356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
24456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fLeft -= pad;
24556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fRight += pad;
24656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
24756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, bounds, paint);
24856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
24956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
25056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                const SkPath& path, const SkMatrix* matrix,
25156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                const SkPaint& paint) SK_OVERRIDE {
25256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bitmap;
25356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bitmap)) {
25456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
25556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
25656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
25756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Math is borrowed from SkBBoxRecord
25856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bounds = path.getBounds();
25956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPaint::FontMetrics metrics;
26056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        paint.getFontMetrics(&metrics);
26156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
26256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkScalar pad = metrics.fTop;
26356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // TODO: inset?!
26456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fLeft += pad;
26556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fRight -= pad;
26656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fTop += pad;
26756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fBottom -= pad;
26856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
26956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, bounds, paint);
27056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
27156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
27256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              const SkPoint verts[], const SkPoint texs[],
27356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              const SkColor colors[], SkXfermode* xmode,
27456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              const uint16_t indices[], int indexCount,
27556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              const SkPaint& paint) SK_OVERRIDE {
2762e9a7157ee8ce47dae6e692162440c4f94a05574skia.committer@gmail.com        this->drawPoints(draw, SkCanvas::kPolygon_PointMode, vertexCount, verts, paint);
27756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
27856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
27956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                            const SkPaint&) SK_OVERRIDE {
28056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        NothingToDo();
28156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
28256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    // TODO: allow this call to return failure, or move to SkBitmapDevice only.
28356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
28456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return fEmptyBitmap;
28556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
28656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
28756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
288ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org    virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
289ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org    virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
2904cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
29156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                             SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
29256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return false;
29356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
29456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
29556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.comprivate:
29656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    SkPictureUtils::SkPixelRefContainer* fPRCont;
29756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    SkISize                              fSize;
29856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
29956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    SkBitmap                             fEmptyBitmap; // legacy -- need to remove
30056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
30156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    static bool GetBitmapFromPaint(const SkPaint &paint, SkBitmap* bitmap) {
30256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkShader* shader = paint.getShader();
30356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (NULL != shader) {
30456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) {
30556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, NULL, NULL);
30656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            }
30756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
30856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return false;
30956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
31056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
31156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
31256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        NotSupported();
31356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
31456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
31515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
31656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // we expect to only get called via savelayer, in which case it is fine.
31756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkASSERT(kSaveLayer_Usage == usage);
31815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice,
31915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                          (info.width(), info.height(), fPRCont));
32056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
32156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
32256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void flush() SK_OVERRIDE {}
32356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
32456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    static void NotSupported() {
32556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkDEBUGFAIL("this method should never be called");
32656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
32756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
32856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    static void NothingToDo() {}
32956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
33056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    typedef SkBaseDevice INHERITED;
33156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com};
33256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
33356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#endif // SkGatherPixelRefsAndRects_DEFINED
334