SkLatticeIter.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * Copyright 2015 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. #include "include/core/SkRect.h"
  8. #include "src/core/SkLatticeIter.h"
  9. /**
  10. * Divs must be in increasing order with no duplicates.
  11. */
  12. static bool valid_divs(const int* divs, int count, int start, int end) {
  13. int prev = start - 1;
  14. for (int i = 0; i < count; i++) {
  15. if (prev >= divs[i] || divs[i] >= end) {
  16. return false;
  17. }
  18. prev = divs[i];
  19. }
  20. return true;
  21. }
  22. bool SkLatticeIter::Valid(int width, int height, const SkCanvas::Lattice& lattice) {
  23. SkIRect totalBounds = SkIRect::MakeWH(width, height);
  24. SkASSERT(lattice.fBounds);
  25. const SkIRect latticeBounds = *lattice.fBounds;
  26. if (!totalBounds.contains(latticeBounds)) {
  27. return false;
  28. }
  29. bool zeroXDivs = lattice.fXCount <= 0 || (1 == lattice.fXCount &&
  30. latticeBounds.fLeft == lattice.fXDivs[0]);
  31. bool zeroYDivs = lattice.fYCount <= 0 || (1 == lattice.fYCount &&
  32. latticeBounds.fTop == lattice.fYDivs[0]);
  33. if (zeroXDivs && zeroYDivs) {
  34. return false;
  35. }
  36. return valid_divs(lattice.fXDivs, lattice.fXCount, latticeBounds.fLeft, latticeBounds.fRight)
  37. && valid_divs(lattice.fYDivs, lattice.fYCount, latticeBounds.fTop, latticeBounds.fBottom);
  38. }
  39. /**
  40. * Count the number of pixels that are in "scalable" patches.
  41. */
  42. static int count_scalable_pixels(const int32_t* divs, int numDivs, bool firstIsScalable,
  43. int start, int end) {
  44. if (0 == numDivs) {
  45. return firstIsScalable ? end - start : 0;
  46. }
  47. int i;
  48. int count;
  49. if (firstIsScalable) {
  50. count = divs[0] - start;
  51. i = 1;
  52. } else {
  53. count = 0;
  54. i = 0;
  55. }
  56. for (; i < numDivs; i += 2) {
  57. // Alternatively, we could use |top| and |bottom| as variable names, instead of
  58. // |left| and |right|.
  59. int left = divs[i];
  60. int right = (i + 1 < numDivs) ? divs[i + 1] : end;
  61. count += right - left;
  62. }
  63. return count;
  64. }
  65. /**
  66. * Set points for the src and dst rects on subsequent draw calls.
  67. */
  68. static void set_points(float* dst, int* src, const int* divs, int divCount, int srcFixed,
  69. int srcScalable, int srcStart, int srcEnd, float dstStart, float dstEnd,
  70. bool isScalable) {
  71. float dstLen = dstEnd - dstStart;
  72. float scale;
  73. if (srcFixed <= dstLen) {
  74. // This is the "normal" case, where we scale the "scalable" patches and leave
  75. // the other patches fixed.
  76. scale = (dstLen - ((float) srcFixed)) / ((float) srcScalable);
  77. } else {
  78. // In this case, we eliminate the "scalable" patches and scale the "fixed" patches.
  79. scale = dstLen / ((float) srcFixed);
  80. }
  81. src[0] = srcStart;
  82. dst[0] = dstStart;
  83. for (int i = 0; i < divCount; i++) {
  84. src[i + 1] = divs[i];
  85. int srcDelta = src[i + 1] - src[i];
  86. float dstDelta;
  87. if (srcFixed <= dstLen) {
  88. dstDelta = isScalable ? scale * srcDelta : srcDelta;
  89. } else {
  90. dstDelta = isScalable ? 0.0f : scale * srcDelta;
  91. }
  92. dst[i + 1] = dst[i] + dstDelta;
  93. // Alternate between "scalable" and "fixed" patches.
  94. isScalable = !isScalable;
  95. }
  96. src[divCount + 1] = srcEnd;
  97. dst[divCount + 1] = dstEnd;
  98. }
  99. SkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst) {
  100. const int* xDivs = lattice.fXDivs;
  101. const int origXCount = lattice.fXCount;
  102. const int* yDivs = lattice.fYDivs;
  103. const int origYCount = lattice.fYCount;
  104. SkASSERT(lattice.fBounds);
  105. const SkIRect src = *lattice.fBounds;
  106. // In the x-dimension, the first rectangle always starts at x = 0 and is "scalable".
  107. // If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so the
  108. // first real rectangle "scalable" in the x-direction.
  109. //
  110. // The same interpretation applies to the y-dimension.
  111. //
  112. // As we move left to right across the image, alternating patches will be "fixed" or
  113. // "scalable" in the x-direction. Similarly, as move top to bottom, alternating
  114. // patches will be "fixed" or "scalable" in the y-direction.
  115. int xCount = origXCount;
  116. int yCount = origYCount;
  117. bool xIsScalable = (xCount > 0 && src.fLeft == xDivs[0]);
  118. if (xIsScalable) {
  119. // Once we've decided that the first patch is "scalable", we don't need the
  120. // xDiv. It is always implied that we start at the edge of the bounds.
  121. xDivs++;
  122. xCount--;
  123. }
  124. bool yIsScalable = (yCount > 0 && src.fTop == yDivs[0]);
  125. if (yIsScalable) {
  126. // Once we've decided that the first patch is "scalable", we don't need the
  127. // yDiv. It is always implied that we start at the edge of the bounds.
  128. yDivs++;
  129. yCount--;
  130. }
  131. // Count "scalable" and "fixed" pixels in each dimension.
  132. int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, src.fLeft, src.fRight);
  133. int xCountFixed = src.width() - xCountScalable;
  134. int yCountScalable = count_scalable_pixels(yDivs, yCount, yIsScalable, src.fTop, src.fBottom);
  135. int yCountFixed = src.height() - yCountScalable;
  136. fSrcX.reset(xCount + 2);
  137. fDstX.reset(xCount + 2);
  138. set_points(fDstX.begin(), fSrcX.begin(), xDivs, xCount, xCountFixed, xCountScalable,
  139. src.fLeft, src.fRight, dst.fLeft, dst.fRight, xIsScalable);
  140. fSrcY.reset(yCount + 2);
  141. fDstY.reset(yCount + 2);
  142. set_points(fDstY.begin(), fSrcY.begin(), yDivs, yCount, yCountFixed, yCountScalable,
  143. src.fTop, src.fBottom, dst.fTop, dst.fBottom, yIsScalable);
  144. fCurrX = fCurrY = 0;
  145. fNumRectsInLattice = (xCount + 1) * (yCount + 1);
  146. fNumRectsToDraw = fNumRectsInLattice;
  147. if (lattice.fRectTypes) {
  148. fRectTypes.push_back_n(fNumRectsInLattice);
  149. fColors.push_back_n(fNumRectsInLattice);
  150. const SkCanvas::Lattice::RectType* flags = lattice.fRectTypes;
  151. const SkColor* colors = lattice.fColors;
  152. bool hasPadRow = (yCount != origYCount);
  153. bool hasPadCol = (xCount != origXCount);
  154. if (hasPadRow) {
  155. // The first row of rects are all empty, skip the first row of flags.
  156. flags += origXCount + 1;
  157. colors += origXCount + 1;
  158. }
  159. int i = 0;
  160. for (int y = 0; y < yCount + 1; y++) {
  161. for (int x = 0; x < origXCount + 1; x++) {
  162. if (0 == x && hasPadCol) {
  163. // The first column of rects are all empty. Skip a rect.
  164. flags++;
  165. colors++;
  166. continue;
  167. }
  168. fRectTypes[i] = *flags;
  169. fColors[i] = SkCanvas::Lattice::kFixedColor == *flags ? *colors : 0;
  170. flags++;
  171. colors++;
  172. i++;
  173. }
  174. }
  175. for (int j = 0; j < fRectTypes.count(); j++) {
  176. if (SkCanvas::Lattice::kTransparent == fRectTypes[j]) {
  177. fNumRectsToDraw--;
  178. }
  179. }
  180. }
  181. }
  182. bool SkLatticeIter::Valid(int width, int height, const SkIRect& center) {
  183. return !center.isEmpty() && SkIRect::MakeWH(width, height).contains(center);
  184. }
  185. SkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst) {
  186. SkASSERT(SkIRect::MakeWH(w, h).contains(c));
  187. fSrcX.reset(4);
  188. fSrcY.reset(4);
  189. fDstX.reset(4);
  190. fDstY.reset(4);
  191. fSrcX[0] = 0;
  192. fSrcX[1] = SkIntToScalar(c.fLeft);
  193. fSrcX[2] = SkIntToScalar(c.fRight);
  194. fSrcX[3] = SkIntToScalar(w);
  195. fSrcY[0] = 0;
  196. fSrcY[1] = SkIntToScalar(c.fTop);
  197. fSrcY[2] = SkIntToScalar(c.fBottom);
  198. fSrcY[3] = SkIntToScalar(h);
  199. fDstX[0] = dst.fLeft;
  200. fDstX[1] = dst.fLeft + SkIntToScalar(c.fLeft);
  201. fDstX[2] = dst.fRight - SkIntToScalar(w - c.fRight);
  202. fDstX[3] = dst.fRight;
  203. fDstY[0] = dst.fTop;
  204. fDstY[1] = dst.fTop + SkIntToScalar(c.fTop);
  205. fDstY[2] = dst.fBottom - SkIntToScalar(h - c.fBottom);
  206. fDstY[3] = dst.fBottom;
  207. if (fDstX[1] > fDstX[2]) {
  208. fDstX[1] = fDstX[0] + (fDstX[3] - fDstX[0]) * c.fLeft / (w - c.width());
  209. fDstX[2] = fDstX[1];
  210. }
  211. if (fDstY[1] > fDstY[2]) {
  212. fDstY[1] = fDstY[0] + (fDstY[3] - fDstY[0]) * c.fTop / (h - c.height());
  213. fDstY[2] = fDstY[1];
  214. }
  215. fCurrX = fCurrY = 0;
  216. fNumRectsInLattice = 9;
  217. fNumRectsToDraw = 9;
  218. }
  219. bool SkLatticeIter::next(SkIRect* src, SkRect* dst, bool* isFixedColor, SkColor* fixedColor) {
  220. int currRect = fCurrX + fCurrY * (fSrcX.count() - 1);
  221. if (currRect == fNumRectsInLattice) {
  222. return false;
  223. }
  224. const int x = fCurrX;
  225. const int y = fCurrY;
  226. SkASSERT(x >= 0 && x < fSrcX.count() - 1);
  227. SkASSERT(y >= 0 && y < fSrcY.count() - 1);
  228. if (fSrcX.count() - 1 == ++fCurrX) {
  229. fCurrX = 0;
  230. fCurrY += 1;
  231. }
  232. if (fRectTypes.count() > 0
  233. && SkToBool(SkCanvas::Lattice::kTransparent == fRectTypes[currRect])) {
  234. return this->next(src, dst, isFixedColor, fixedColor);
  235. }
  236. src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]);
  237. dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]);
  238. if (isFixedColor && fixedColor) {
  239. *isFixedColor = fRectTypes.count() > 0
  240. && SkToBool(SkCanvas::Lattice::kFixedColor == fRectTypes[currRect]);
  241. if (*isFixedColor) {
  242. *fixedColor = fColors[currRect];
  243. }
  244. }
  245. return true;
  246. }
  247. void SkLatticeIter::mapDstScaleTranslate(const SkMatrix& matrix) {
  248. SkASSERT(matrix.isScaleTranslate());
  249. SkScalar tx = matrix.getTranslateX();
  250. SkScalar sx = matrix.getScaleX();
  251. for (int i = 0; i < fDstX.count(); i++) {
  252. fDstX[i] = fDstX[i] * sx + tx;
  253. }
  254. SkScalar ty = matrix.getTranslateY();
  255. SkScalar sy = matrix.getScaleY();
  256. for (int i = 0; i < fDstY.count(); i++) {
  257. fDstY[i] = fDstY[i] * sy + ty;
  258. }
  259. }