Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(682)

Side by Side Diff: src/core/SkPictureShader.cpp

Issue 221923007: Initial picture shader implementation (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Remove unneeded suppression. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "SkPictureShader.h"
9
10 #include "SkBitmap.h"
11 #include "SkBitmapProcShader.h"
12 #include "SkCanvas.h"
13 #include "SkMatrixUtils.h"
14 #include "SkPicture.h"
15 #include "SkReadBuffer.h"
16
17 #if SK_SUPPORT_GPU
18 #include "GrContext.h"
19 #endif
20
21 SkPictureShader::SkPictureShader(SkPicture* picture, TileMode tmx, TileMode tmy)
22 : fPicture(picture)
23 , fTmx(tmx)
24 , fTmy(tmy) {
25 SkSafeRef(fPicture);
26 }
27
28 SkPictureShader::SkPictureShader(SkReadBuffer& buffer)
29 : INHERITED(buffer) {
30 fTmx = static_cast<SkShader::TileMode>(buffer.read32());
31 fTmy = static_cast<SkShader::TileMode>(buffer.read32());
32 if (buffer.readBool()) {
33 fPicture = SkPicture::CreateFromBuffer(buffer);
34 } else {
35 fPicture = NULL;
36 }
37 }
38
39 SkPictureShader::~SkPictureShader() {
40 SkSafeUnref(fPicture);
41 }
42
43 SkPictureShader* SkPictureShader::Create(SkPicture* picture, TileMode tmx, TileM ode tmy) {
44 return SkNEW_ARGS(SkPictureShader, (picture, tmx, tmy));
45 }
46
47 void SkPictureShader::flatten(SkWriteBuffer& buffer) const {
48 this->INHERITED::flatten(buffer);
49
50 buffer.write32(fTmx);
51 buffer.write32(fTmy);
52 buffer.writeBool(NULL != fPicture);
53 if (fPicture) {
54 fPicture->flatten(buffer);
55 }
56 }
57
58 bool SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const {
59 if (!fPicture || (0 == fPicture->width() && 0 == fPicture->height())) {
scroggo 2014/04/11 15:23:15 It appears that if the picture is NULL or it has z
f(malita) 2014/04/11 16:05:18 Good point. After making the constructor private,
60 return false;
61 }
62
63 SkMatrix m;
64 if (this->hasLocalMatrix()) {
65 m.setConcat(matrix, this->getLocalMatrix());
66 } else {
67 m = matrix;
68 }
69
70 // Use a rotation-invariant scale
71 SkPoint scale;
72 if (!SkDecomposeUpper2x2(m, NULL, &scale, NULL)) {
73 // Decomposition failed, use an approximation.
74 scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m. getSkewX()),
75 SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m. getSkewY()));
76 }
77 SkSize scaledSize = SkSize::Make(scale.x() * fPicture->width(), scale.y() * fPicture->height());
78
79 SkISize tileSize = scaledSize.toRound();
80 if (tileSize.isEmpty()) {
81 return false;
82 }
83
84 // The actual scale, compensating for rounding.
85 SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture-> width(),
86 SkIntToScalar(tileSize.height()) / fPicture- >height());
87
88 if (!fCachedShader || tileScale != fCachedTileScale) {
89 SkBitmap bm;
90 if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) {
91 return false;
92 }
93 bm.eraseColor(SK_ColorTRANSPARENT);
94
95 SkCanvas canvas(bm);
96 canvas.scale(tileScale.width(), tileScale.height());
97 canvas.drawPicture(*fPicture);
98
99 fCachedShader.reset(CreateBitmapShader(bm, fTmx, fTmy));
100 fCachedTileScale = tileScale;
101 }
102
103 SkMatrix shaderMatrix = this->getLocalMatrix();
104 shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
105 fCachedShader->setLocalMatrix(shaderMatrix);
106
107 return true;
108 }
109
110 bool SkPictureShader::setContext(const SkBitmap& device,
111 const SkPaint& paint,
112 const SkMatrix& matrix) {
113 if (!this->buildBitmapShader(matrix)) {
114 return false;
115 }
116
117 if (!this->INHERITED::setContext(device, paint, matrix)) {
118 return false;
119 }
120
121 SkASSERT(fCachedShader);
122 if (!fCachedShader->setContext(device, paint, matrix)) {
123 this->INHERITED::endContext();
124 return false;
125 }
126
127 return true;
128 }
129
130 void SkPictureShader::endContext() {
131 SkASSERT(fCachedShader);
132 fCachedShader->endContext();
133
134 this->INHERITED::endContext();
135 }
136
137 uint32_t SkPictureShader::getFlags() {
138 if (NULL != fCachedShader) {
139 return fCachedShader->getFlags();
140 }
141 return 0;
142 }
143
144 SkShader::ShadeProc SkPictureShader::asAShadeProc(void** ctx) {
145 if (fCachedShader) {
146 return fCachedShader->asAShadeProc(ctx);
147 }
148 return NULL;
149 }
150
151 void SkPictureShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
152 SkASSERT(fCachedShader);
153 fCachedShader->shadeSpan(x, y, dstC, count);
154 }
155
156 void SkPictureShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
157 SkASSERT(fCachedShader);
158 fCachedShader->shadeSpan16(x, y, dstC, count);
159 }
160
161 #ifndef SK_IGNORE_TO_STRING
162 void SkPictureShader::toString(SkString* str) const {
163 static const char* gTileModeName[SkShader::kTileModeCount] = {
164 "clamp", "repeat", "mirror"
165 };
166
167 str->appendf("PictureShader: [%d:%d] ",
168 fPicture ? fPicture->width() : 0,
169 fPicture ? fPicture->height() : 0);
170
171 str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]);
172
173 this->INHERITED::toString(str);
174 }
175 #endif
176
177 #if SK_SUPPORT_GPU
178 GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& pai nt) const {
179 if (!this->buildBitmapShader(context->getMatrix())) {
180 return NULL;
181 }
182 SkASSERT(fCachedShader);
183 return fCachedShader->asNewEffect(context, paint);
184 }
185 #endif
OLDNEW
« include/core/SkShader.h ('K') | « src/core/SkPictureShader.h ('k') | src/core/SkShader.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698