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