SkGatherPixelRefsAndRects.h revision f0a4013467dd5aab0b35ddc89f86ad9827ea49ad
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
2656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.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);
3156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        fEmptyBitmap.setConfig(SkBitmap::kNo_Config, width, height);
3256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
3356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
3456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual ~SkGatherPixelRefsAndRectsDevice() {
3556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkSafeUnref(fPRCont);
3656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
3756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
3856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual uint32_t getDeviceCapabilities() SK_OVERRIDE { return 0; }
3956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
4056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual int width() const SK_OVERRIDE { return fSize.width(); }
4156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual int height() const SK_OVERRIDE { return fSize.height(); }
4256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual bool isOpaque() const SK_OVERRIDE { return false; }
4356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual SkBitmap::Config config() const SK_OVERRIDE {
4456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return SkBitmap::kNo_Config;
4556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
4656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void writePixels(const SkBitmap& bitmap, int x, int y,
4756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                             SkCanvas::Config8888 config8888) SK_OVERRIDE {
4856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        NotSupported();
4956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
5056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
5156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
5256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.comprotected:
5356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
5456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return false;
5556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
5656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void clear(SkColor color) SK_OVERRIDE {
5756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        NothingToDo();
5856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
5956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
6056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bm;
6156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
6256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (GetBitmapFromPaint(paint, &bm)) {
6356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
6456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            fPRCont->add(bm.pixelRef(), clipRect);
6556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
6656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
6756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
6856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                            const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
6956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bm;
7056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bm)) {
7156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
7256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
7356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
7456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (0 == count) {
7556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
7656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
7756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
7856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPoint min = points[0];
7956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPoint max = points[0];
8056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        for (size_t i = 1; i < count; ++i) {
8156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            const SkPoint& point = points[i];
8256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
8356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            min.set(SkMinScalar(min.x(), point.x()), SkMinScalar(min.y(), point.y()));
8456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            max.set(SkMaxScalar(max.x(), point.x()), SkMaxScalar(max.y(), point.y()));
8556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
8656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
8756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x()+1, max.y()+1);
8856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
8956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, bounds, paint);
9056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
9156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawRect(const SkDraw& draw, const SkRect& rect,
9256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          const SkPaint& paint) SK_OVERRIDE {
9356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bm;
9456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (GetBitmapFromPaint(paint, &bm)) {
9556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkRect mappedRect;
9656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            draw.fMatrix->mapRect(&mappedRect, rect);
9756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
9856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            mappedRect.intersect(clipRect);
9956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            fPRCont->add(bm.pixelRef(), mappedRect);
10056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
10156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
10256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawOval(const SkDraw& draw, const SkRect& rect,
10356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          const SkPaint& paint) SK_OVERRIDE {
10456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, rect, paint);
10556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
10656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
10756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                           const SkPaint& paint) SK_OVERRIDE {
10856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, rrect.rect(), paint);
10956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
11056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawPath(const SkDraw& draw, const SkPath& path,
11156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          const SkPaint& paint, const SkMatrix* prePathMatrix,
11256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          bool pathIsMutable) SK_OVERRIDE {
11356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bm;
11456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bm)) {
11556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
11656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
11756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
11856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect pathBounds = path.getBounds();
11956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (NULL != prePathMatrix) {
12056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            prePathMatrix->mapRect(&pathBounds);
12156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
12256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
12356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, pathBounds, paint);
12456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
12556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
12656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                            const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
12756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkMatrix totMatrix;
12856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        totMatrix.setConcat(*draw.fMatrix, matrix);
12956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
13056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
13156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                           SkIntToScalar(bitmap.height()));
13256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect mappedRect;
13356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        totMatrix.mapRect(&mappedRect, bitmapRect);
13456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        fPRCont->add(bitmap.pixelRef(), mappedRect);
13556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
13656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap paintBitmap;
13756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (GetBitmapFromPaint(paint, &paintBitmap)) {
13856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            fPRCont->add(paintBitmap.pixelRef(), mappedRect);
13956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
14056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
14156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
14256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                            int x, int y, const SkPaint& paint) SK_OVERRIDE {
14356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Sprites aren't affected by current matrix, so we can't reuse drawRect.
14456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkMatrix matrix;
14556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
14656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
14756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
14856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                           SkIntToScalar(bitmap.height()));
14956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect mappedRect;
15056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        matrix.mapRect(&mappedRect, bitmapRect);
15156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        fPRCont->add(bitmap.pixelRef(), mappedRect);
15256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
15356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap paintBitmap;
15456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (GetBitmapFromPaint(paint, &paintBitmap)) {
15556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            fPRCont->add(paintBitmap.pixelRef(), mappedRect);
15656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
15756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
15856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
15956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                const SkRect* srcOrNull, const SkRect& dst,
16056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                const SkPaint& paint,
16156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
16256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
16356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                           SkIntToScalar(bitmap.height()));
16456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkMatrix matrix;
16556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        matrix.setRectToRect(bitmapRect, dst, SkMatrix::kFill_ScaleToFit);
16656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawBitmap(draw, bitmap, matrix, paint);
16756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
16856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawText(const SkDraw& draw, const void* text, size_t len,
16956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          SkScalar x, SkScalar y,
17056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                          const SkPaint& paint) SK_OVERRIDE {
17156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bitmap;
17256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bitmap)) {
17356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
17456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
17556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
17656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Math is borrowed from SkBBoxRecord
17756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bounds;
17856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        paint.measureText(text, len, &bounds);
17956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPaint::FontMetrics metrics;
18056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        paint.getFontMetrics(&metrics);
18156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
18256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (paint.isVerticalText()) {
18356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkScalar h = bounds.fBottom - bounds.fTop;
18456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            if (paint.getTextAlign() == SkPaint::kCenter_Align) {
18556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fTop -= h / 2;
18656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fBottom -= h / 2;
18756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            }
18856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            bounds.fBottom += metrics.fBottom;
18956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            bounds.fTop += metrics.fTop;
19056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        } else {
19156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkScalar w = bounds.fRight - bounds.fLeft;
19256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            if (paint.getTextAlign() == SkPaint::kCenter_Align) {
19356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fLeft -= w / 2;
19456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fRight -= w / 2;
19556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
19656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fLeft -= w;
19756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                bounds.fRight -= w;
19856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            }
19956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            bounds.fTop = metrics.fTop;
20056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            bounds.fBottom = metrics.fBottom;
20156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
20256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
20356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
20456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fLeft -= pad;
20556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fRight += pad;
20656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.offset(x, y);
20756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
20856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, bounds, paint);
20956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
21056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
21156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                             const SkScalar pos[], SkScalar constY,
21256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                             int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
21356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bitmap;
21456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bitmap)) {
21556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
21656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
21756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
21856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (0 == len) {
21956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
22056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
22156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
22256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Similar to SkDraw asserts.
22356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2);
22456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
225f0a4013467dd5aab0b35ddc89f86ad9827ea49adrobertphillips@google.com        SkScalar y = scalarsPerPos == 1 ? constY : constY + pos[1];
226f0a4013467dd5aab0b35ddc89f86ad9827ea49adrobertphillips@google.com
22756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPoint min, max;
228f0a4013467dd5aab0b35ddc89f86ad9827ea49adrobertphillips@google.com        min.set(pos[0], y);
229f0a4013467dd5aab0b35ddc89f86ad9827ea49adrobertphillips@google.com        max.set(pos[0], y);
23056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
23156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        for (size_t i = 1; i < len; ++i) {
23256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkScalar x = pos[i * scalarsPerPos];
23356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            SkScalar y = constY;
23456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            if (2 == scalarsPerPos) {
23556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                y += pos[i * scalarsPerPos + 1];
23656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            }
23756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
23856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            min.set(SkMinScalar(x, min.x()), SkMinScalar(y, min.y()));
23956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            max.set(SkMaxScalar(x, max.x()), SkMaxScalar(y, max.y()));
24056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
24156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
24256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x(), max.y());
24356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
24456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Math is borrowed from SkBBoxRecord
24556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPaint::FontMetrics metrics;
24656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        paint.getFontMetrics(&metrics);
24756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
24856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fTop += metrics.fTop;
24956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fBottom += metrics.fBottom;
25056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
25156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
25256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fLeft -= pad;
25356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fRight += pad;
25456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
25556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, bounds, paint);
25656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
25756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
25856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                const SkPath& path, const SkMatrix* matrix,
25956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                const SkPaint& paint) SK_OVERRIDE {
26056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkBitmap bitmap;
26156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (!GetBitmapFromPaint(paint, &bitmap)) {
26256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            return;
26356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
26456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
26556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // Math is borrowed from SkBBoxRecord
26656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkRect bounds = path.getBounds();
26756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkPaint::FontMetrics metrics;
26856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        paint.getFontMetrics(&metrics);
26956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
27056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkScalar pad = metrics.fTop;
27156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // TODO: inset?!
27256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fLeft += pad;
27356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fRight -= pad;
27456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fTop += pad;
27556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        bounds.fBottom -= pad;
27656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
27756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawRect(draw, bounds, paint);
27856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
27956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
28056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              const SkPoint verts[], const SkPoint texs[],
28156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              const SkColor colors[], SkXfermode* xmode,
28256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              const uint16_t indices[], int indexCount,
28356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              const SkPaint& paint) SK_OVERRIDE {
28456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        this->drawPoints(draw, SkCanvas::kPolygon_PointMode, vertexCount, verts, paint);
28556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
28656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
28756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                            const SkPaint&) SK_OVERRIDE {
28856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        NothingToDo();
28956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
29056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    // TODO: allow this call to return failure, or move to SkBitmapDevice only.
29156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
29256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return fEmptyBitmap;
29356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
29456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual bool onReadPixels(const SkBitmap& bitmap,
29556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              int x, int y,
29656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                              SkCanvas::Config8888 config8888) SK_OVERRIDE {
29756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        NotSupported();
29856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return false;
29956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
30056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
30156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
30256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE { return false; }
30356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual bool canHandleImageFilter(SkImageFilter*) SK_OVERRIDE { return false; }
30456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&,
30556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                             SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
30656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return false;
30756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
30856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
30956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.comprivate:
31056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    SkPictureUtils::SkPixelRefContainer* fPRCont;
31156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    SkISize                              fSize;
31256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
31356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    SkBitmap                             fEmptyBitmap; // legacy -- need to remove
31456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
31556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    static bool GetBitmapFromPaint(const SkPaint &paint, SkBitmap* bitmap) {
31656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkShader* shader = paint.getShader();
31756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        if (NULL != shader) {
31856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) {
31956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, NULL, NULL);
32056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com            }
32156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        }
32256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return false;
32356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
32456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
32556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
32656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        NotSupported();
32756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
32856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
32956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
33056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                                   int width, int height,
33156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                                   bool isOpaque,
33256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com                                                   Usage usage) SK_OVERRIDE {
33356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        // we expect to only get called via savelayer, in which case it is fine.
33456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkASSERT(kSaveLayer_Usage == usage);
33556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice, (width, height, fPRCont));
33656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
33756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
33856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    virtual void flush() SK_OVERRIDE {}
33956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
34056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    static void NotSupported() {
34156bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com        SkDEBUGFAIL("this method should never be called");
34256bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    }
34356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
34456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    static void NothingToDo() {}
34556bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
34656bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    typedef SkBaseDevice INHERITED;
34756bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com};
34856bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
34956bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com#endif // SkGatherPixelRefsAndRects_DEFINED
35056bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
351