OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkLatticeIter.h" | 8 #include "SkLatticeIter.h" |
9 #include "SkRect.h" | 9 #include "SkRect.h" |
10 | 10 |
11 /** | 11 /** |
12 * Divs must be in increasing order with no duplicates. | 12 * Divs must be in increasing order with no duplicates. |
13 */ | 13 */ |
14 static bool valid_divs(const int* divs, int count, int len) { | 14 static bool valid_divs(const int* divs, int count, int start, int end) { |
15 int prev = -1; | 15 int prev = start - 1; |
16 for (int i = 0; i < count; i++) { | 16 for (int i = 0; i < count; i++) { |
17 if (prev >= divs[i] || divs[i] >= len) { | 17 if (prev >= divs[i] || divs[i] >= end) { |
18 return false; | 18 return false; |
19 } | 19 } |
20 } | 20 } |
21 | 21 |
22 return true; | 22 return true; |
23 } | 23 } |
24 | 24 |
25 bool SkLatticeIter::Valid(int width, int height, const SkCanvas::Lattice& lattic
e) { | 25 bool SkLatticeIter::Valid(int width, int height, const SkCanvas::Lattice& lattic
e) { |
26 bool zeroXDivs = lattice.fXCount <= 0 || (1 == lattice.fXCount && 0 == latti
ce.fXDivs[0]); | 26 SkIRect totalBounds = SkIRect::MakeWH(width, height); |
27 bool zeroYDivs = lattice.fYCount <= 0 || (1 == lattice.fYCount && 0 == latti
ce.fYDivs[0]); | 27 SkASSERT(lattice.fBounds); |
| 28 const SkIRect latticeBounds = *lattice.fBounds; |
| 29 if (!totalBounds.contains(latticeBounds)) { |
| 30 return false; |
| 31 } |
| 32 |
| 33 bool zeroXDivs = lattice.fXCount <= 0 || (1 == lattice.fXCount && |
| 34 latticeBounds.fLeft == lattice.fXD
ivs[0]); |
| 35 bool zeroYDivs = lattice.fYCount <= 0 || (1 == lattice.fYCount && |
| 36 latticeBounds.fTop == lattice.fYDi
vs[0]); |
28 if (zeroXDivs && zeroYDivs) { | 37 if (zeroXDivs && zeroYDivs) { |
29 return false; | 38 return false; |
30 } | 39 } |
31 | 40 |
32 return valid_divs(lattice.fXDivs, lattice.fXCount, width) && | 41 return valid_divs(lattice.fXDivs, lattice.fXCount, latticeBounds.fLeft, latt
iceBounds.fRight) |
33 valid_divs(lattice.fYDivs, lattice.fYCount, height); | 42 && valid_divs(lattice.fYDivs, lattice.fYCount, latticeBounds.fTop, latti
ceBounds.fBottom); |
34 } | 43 } |
35 | 44 |
36 /** | 45 /** |
37 * Count the number of pixels that are in "scalable" patches. | 46 * Count the number of pixels that are in "scalable" patches. |
38 */ | 47 */ |
39 static int count_scalable_pixels(const int32_t* divs, int numDivs, bool firstIsS
calable, | 48 static int count_scalable_pixels(const int32_t* divs, int numDivs, bool firstIsS
calable, |
40 int length) { | 49 int start, int end) { |
41 if (0 == numDivs) { | 50 if (0 == numDivs) { |
42 return firstIsScalable ? length : 0; | 51 return firstIsScalable ? end - start : 0; |
43 } | 52 } |
44 | 53 |
45 int i; | 54 int i; |
46 int count; | 55 int count; |
47 if (firstIsScalable) { | 56 if (firstIsScalable) { |
48 count = divs[0]; | 57 count = divs[0] - start; |
49 i = 1; | 58 i = 1; |
50 } else { | 59 } else { |
51 count = 0; | 60 count = 0; |
52 i = 0; | 61 i = 0; |
53 } | 62 } |
54 | 63 |
55 for (; i < numDivs; i += 2) { | 64 for (; i < numDivs; i += 2) { |
56 // Alternatively, we could use |top| and |bottom| as variable names, ins
tead of | 65 // Alternatively, we could use |top| and |bottom| as variable names, ins
tead of |
57 // |left| and |right|. | 66 // |left| and |right|. |
58 int left = divs[i]; | 67 int left = divs[i]; |
59 int right = (i + 1 < numDivs) ? divs[i + 1] : length; | 68 int right = (i + 1 < numDivs) ? divs[i + 1] : end; |
60 count += right - left; | 69 count += right - left; |
61 } | 70 } |
62 | 71 |
63 return count; | 72 return count; |
64 } | 73 } |
65 | 74 |
66 /** | 75 /** |
67 * Set points for the src and dst rects on subsequent draw calls. | 76 * Set points for the src and dst rects on subsequent draw calls. |
68 */ | 77 */ |
69 static void set_points(float* dst, float* src, const int* divs, int divCount, in
t srcFixed, | 78 static void set_points(float* dst, float* src, const int* divs, int divCount, in
t srcFixed, |
70 int srcScalable, float dstStart, float dstStop, bool isSc
alable) { | 79 int srcScalable, float srcStart, float srcEnd, float dstS
tart, float dstEnd, |
| 80 bool isScalable) { |
71 | 81 |
72 float dstLen = dstStop - dstStart; | 82 float dstLen = dstEnd - dstStart; |
73 int srcLen = srcFixed + srcScalable; | |
74 float scale; | 83 float scale; |
75 if (srcFixed <= dstLen) { | 84 if (srcFixed <= dstLen) { |
76 // This is the "normal" case, where we scale the "scalable" patches and
leave | 85 // This is the "normal" case, where we scale the "scalable" patches and
leave |
77 // the other patches fixed. | 86 // the other patches fixed. |
78 scale = (dstLen - ((float) srcFixed)) / ((float) srcScalable); | 87 scale = (dstLen - ((float) srcFixed)) / ((float) srcScalable); |
79 } else { | 88 } else { |
80 // In this case, we eliminate the "scalable" patches and scale the "fixe
d" patches. | 89 // In this case, we eliminate the "scalable" patches and scale the "fixe
d" patches. |
81 scale = dstLen / ((float) srcFixed); | 90 scale = dstLen / ((float) srcFixed); |
82 } | 91 } |
83 | 92 |
84 src[0] = 0.0f; | 93 src[0] = srcStart; |
85 dst[0] = dstStart; | 94 dst[0] = dstStart; |
86 for (int i = 0; i < divCount; i++) { | 95 for (int i = 0; i < divCount; i++) { |
87 src[i + 1] = (float) (divs[i]); | 96 src[i + 1] = (float) (divs[i]); |
88 float srcDelta = src[i + 1] - src[i]; | 97 float srcDelta = src[i + 1] - src[i]; |
89 float dstDelta; | 98 float dstDelta; |
90 if (srcFixed <= dstLen) { | 99 if (srcFixed <= dstLen) { |
91 dstDelta = isScalable ? scale * srcDelta : srcDelta; | 100 dstDelta = isScalable ? scale * srcDelta : srcDelta; |
92 } else { | 101 } else { |
93 dstDelta = isScalable ? 0.0f : scale * srcDelta; | 102 dstDelta = isScalable ? 0.0f : scale * srcDelta; |
94 } | 103 } |
95 dst[i + 1] = dst[i] + dstDelta; | 104 dst[i + 1] = dst[i] + dstDelta; |
96 | 105 |
97 // Alternate between "scalable" and "fixed" patches. | 106 // Alternate between "scalable" and "fixed" patches. |
98 isScalable = !isScalable; | 107 isScalable = !isScalable; |
99 } | 108 } |
100 | 109 |
101 src[divCount + 1] = (float) srcLen; | 110 src[divCount + 1] = srcEnd; |
102 dst[divCount + 1] = dstStop; | 111 dst[divCount + 1] = dstEnd; |
103 } | 112 } |
104 | 113 |
105 SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattic
e& lattice, | 114 SkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst
) { |
106 const SkRect& dst) | |
107 { | |
108 const int* xDivs = lattice.fXDivs; | 115 const int* xDivs = lattice.fXDivs; |
109 const int origXCount = lattice.fXCount; | 116 const int origXCount = lattice.fXCount; |
110 const int* yDivs = lattice.fYDivs; | 117 const int* yDivs = lattice.fYDivs; |
111 const int origYCount = lattice.fYCount; | 118 const int origYCount = lattice.fYCount; |
| 119 SkASSERT(lattice.fBounds); |
| 120 const SkIRect src = *lattice.fBounds; |
112 | 121 |
113 // In the x-dimension, the first rectangle always starts at x = 0 and is "sc
alable". | 122 // In the x-dimension, the first rectangle always starts at x = 0 and is "sc
alable". |
114 // If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so
the | 123 // If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so
the |
115 // first real rectangle "scalable" in the x-direction. | 124 // first real rectangle "scalable" in the x-direction. |
116 // | 125 // |
117 // The same interpretation applies to the y-dimension. | 126 // The same interpretation applies to the y-dimension. |
118 // | 127 // |
119 // As we move left to right across the image, alternating patches will be "f
ixed" or | 128 // As we move left to right across the image, alternating patches will be "f
ixed" or |
120 // "scalable" in the x-direction. Similarly, as move top to bottom, alterna
ting | 129 // "scalable" in the x-direction. Similarly, as move top to bottom, alterna
ting |
121 // patches will be "fixed" or "scalable" in the y-direction. | 130 // patches will be "fixed" or "scalable" in the y-direction. |
122 int xCount = origXCount; | 131 int xCount = origXCount; |
123 int yCount = origYCount; | 132 int yCount = origYCount; |
124 bool xIsScalable = (xCount > 0 && 0 == xDivs[0]); | 133 bool xIsScalable = (xCount > 0 && src.fLeft == xDivs[0]); |
125 if (xIsScalable) { | 134 if (xIsScalable) { |
126 // Once we've decided that the first patch is "scalable", we don't need
the | 135 // Once we've decided that the first patch is "scalable", we don't need
the |
127 // xDiv. It is always implied that we start at zero. | 136 // xDiv. It is always implied that we start at the edge of the bounds. |
128 xDivs++; | 137 xDivs++; |
129 xCount--; | 138 xCount--; |
130 } | 139 } |
131 bool yIsScalable = (yCount > 0 && 0 == yDivs[0]); | 140 bool yIsScalable = (yCount > 0 && src.fTop == yDivs[0]); |
132 if (yIsScalable) { | 141 if (yIsScalable) { |
133 // Once we've decided that the first patch is "scalable", we don't need
the | 142 // Once we've decided that the first patch is "scalable", we don't need
the |
134 // yDiv. It is always implied that we start at zero. | 143 // yDiv. It is always implied that we start at the edge of the bounds. |
135 yDivs++; | 144 yDivs++; |
136 yCount--; | 145 yCount--; |
137 } | 146 } |
138 | 147 |
139 // Count "scalable" and "fixed" pixels in each dimension. | 148 // Count "scalable" and "fixed" pixels in each dimension. |
140 int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, srcWi
dth); | 149 int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, src.f
Left, src.fRight); |
141 int xCountFixed = srcWidth - xCountScalable; | 150 int xCountFixed = src.width() - xCountScalable; |
142 int yCountScalable = count_scalable_pixels(yDivs, yCount, yIsScalable, srcHe
ight); | 151 int yCountScalable = count_scalable_pixels(yDivs, yCount, yIsScalable, src.f
Top, src.fBottom); |
143 int yCountFixed = srcHeight - yCountScalable; | 152 int yCountFixed = src.height() - yCountScalable; |
144 | 153 |
145 fSrcX.reset(xCount + 2); | 154 fSrcX.reset(xCount + 2); |
146 fDstX.reset(xCount + 2); | 155 fDstX.reset(xCount + 2); |
147 set_points(fDstX.begin(), fSrcX.begin(), xDivs, xCount, xCountFixed, xCountS
calable, | 156 set_points(fDstX.begin(), fSrcX.begin(), xDivs, xCount, xCountFixed, xCountS
calable, |
148 dst.fLeft, dst.fRight, xIsScalable); | 157 src.fLeft, src.fRight, dst.fLeft, dst.fRight, xIsScalable); |
149 | 158 |
150 fSrcY.reset(yCount + 2); | 159 fSrcY.reset(yCount + 2); |
151 fDstY.reset(yCount + 2); | 160 fDstY.reset(yCount + 2); |
152 set_points(fDstY.begin(), fSrcY.begin(), yDivs, yCount, yCountFixed, yCountS
calable, | 161 set_points(fDstY.begin(), fSrcY.begin(), yDivs, yCount, yCountFixed, yCountS
calable, |
153 dst.fTop, dst.fBottom, yIsScalable); | 162 src.fTop, src.fBottom, dst.fTop, dst.fBottom, yIsScalable); |
154 | 163 |
155 fCurrX = fCurrY = 0; | 164 fCurrX = fCurrY = 0; |
156 fNumRectsInLattice = (xCount + 1) * (yCount + 1); | 165 fNumRectsInLattice = (xCount + 1) * (yCount + 1); |
157 fNumRectsToDraw = fNumRectsInLattice; | 166 fNumRectsToDraw = fNumRectsInLattice; |
158 | 167 |
159 if (lattice.fFlags) { | 168 if (lattice.fFlags) { |
160 fFlags.push_back_n(fNumRectsInLattice); | 169 fFlags.push_back_n(fNumRectsInLattice); |
161 | 170 |
162 const SkCanvas::Lattice::Flags* flags = lattice.fFlags; | 171 const SkCanvas::Lattice::Flags* flags = lattice.fFlags; |
163 | 172 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 for (int i = 0; i < fDstX.count(); i++) { | 279 for (int i = 0; i < fDstX.count(); i++) { |
271 fDstX[i] = fDstX[i] * sx + tx; | 280 fDstX[i] = fDstX[i] * sx + tx; |
272 } | 281 } |
273 | 282 |
274 SkScalar ty = matrix.getTranslateY(); | 283 SkScalar ty = matrix.getTranslateY(); |
275 SkScalar sy = matrix.getScaleY(); | 284 SkScalar sy = matrix.getScaleY(); |
276 for (int i = 0; i < fDstY.count(); i++) { | 285 for (int i = 0; i < fDstY.count(); i++) { |
277 fDstY[i] = fDstY[i] * sy + ty; | 286 fDstY[i] = fDstY[i] * sy + ty; |
278 } | 287 } |
279 } | 288 } |
OLD | NEW |