SkLocalMatrixShader.cpp revision 96fb7489ba46909c3f81bb2d94755e7d4ccb5fad
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#include "SkShader.h"
9#include "SkReadBuffer.h"
10#include "SkWriteBuffer.h"
11
12class SkLocalMatrixShader : public SkShader {
13public:
14    SkLocalMatrixShader(SkShader* proxy, const SkMatrix& localMatrix)
15        : fProxyShader(SkRef(proxy))
16        , fProxyLocalMatrix(localMatrix)
17    {}
18
19    virtual size_t contextSize() const SK_OVERRIDE {
20        return fProxyShader->contextSize();
21    }
22
23    virtual BitmapType asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
24                                 TileMode* mode) const SK_OVERRIDE {
25        return fProxyShader->asABitmap(bitmap, matrix, mode);
26    }
27
28    virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE {
29        return fProxyShader->asAGradient(info);
30    }
31
32    // TODO: need to augment this API to pass in a localmatrix (which we can augment)
33    virtual GrEffectRef* asNewEffect(GrContext* ctx, const SkPaint& paint,
34                                     const SkMatrix* localMatrix) const SK_OVERRIDE {
35        SkMatrix tmp = fProxyLocalMatrix;
36        if (localMatrix) {
37            tmp.preConcat(*localMatrix);
38        }
39        return fProxyShader->asNewEffect(ctx, paint, &tmp);
40    }
41
42    virtual SkShader* refAsALocalMatrixShader(SkMatrix* localMatrix) const SK_OVERRIDE {
43        if (localMatrix) {
44            *localMatrix = fProxyLocalMatrix;
45        }
46        return SkRef(fProxyShader.get());
47    }
48
49    SK_TO_STRING_OVERRIDE()
50    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLocalMatrixShader)
51
52protected:
53    SkLocalMatrixShader(SkReadBuffer&);
54    virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
55    virtual Context* onCreateContext(const ContextRec&, void*) const SK_OVERRIDE;
56
57private:
58    SkAutoTUnref<SkShader> fProxyShader;
59    SkMatrix  fProxyLocalMatrix;
60
61    typedef SkShader INHERITED;
62};
63
64SkLocalMatrixShader::SkLocalMatrixShader(SkReadBuffer& buffer) : INHERITED(buffer) {
65    buffer.readMatrix(&fProxyLocalMatrix);
66    fProxyShader.reset(buffer.readFlattenable<SkShader>());
67    if (NULL == fProxyShader.get()) {
68        sk_throw();
69    }
70}
71
72void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const {
73    this->INHERITED::flatten(buffer);
74    buffer.writeMatrix(fProxyLocalMatrix);
75    buffer.writeFlattenable(fProxyShader.get());
76}
77
78SkShader::Context* SkLocalMatrixShader::onCreateContext(const ContextRec& rec,
79                                                        void* storage) const {
80    ContextRec newRec(rec);
81    SkMatrix tmp;
82    if (rec.fLocalMatrix) {
83        tmp.setConcat(fProxyLocalMatrix, *rec.fLocalMatrix);
84        newRec.fLocalMatrix = &tmp;
85    } else {
86        newRec.fLocalMatrix = &fProxyLocalMatrix;
87    }
88    return fProxyShader->createContext(newRec, storage);
89}
90
91#ifndef SK_IGNORE_TO_STRING
92void SkLocalMatrixShader::toString(SkString* str) const {
93    str->append("SkLocalMatrixShader: (");
94
95    fProxyShader->toString(str);
96
97    this->INHERITED::toString(str);
98
99    str->append(")");
100}
101#endif
102
103SkShader* SkShader::CreateLocalMatrixShader(SkShader* proxy, const SkMatrix& localMatrix) {
104    if (localMatrix.isIdentity()) {
105        return SkRef(proxy);
106    }
107
108    const SkMatrix* lm = &localMatrix;
109
110    SkMatrix otherLocalMatrix;
111    SkAutoTUnref<SkShader> otherProxy(proxy->refAsALocalMatrixShader(&otherLocalMatrix));
112    if (otherProxy.get()) {
113        otherLocalMatrix.preConcat(localMatrix);
114        lm = &otherLocalMatrix;
115        proxy = otherProxy.get();
116    }
117
118    return SkNEW_ARGS(SkLocalMatrixShader, (proxy, *lm));
119}
120