| 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 |