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