1c573a40ed5024b463e47088d307e3164a486dba5msarett/* 2c573a40ed5024b463e47088d307e3164a486dba5msarett * Copyright 2015 Google Inc. 3c573a40ed5024b463e47088d307e3164a486dba5msarett * 4c573a40ed5024b463e47088d307e3164a486dba5msarett * Use of this source code is governed by a BSD-style license that can be 5c573a40ed5024b463e47088d307e3164a486dba5msarett * found in the LICENSE file. 6c573a40ed5024b463e47088d307e3164a486dba5msarett */ 7c573a40ed5024b463e47088d307e3164a486dba5msarett 8c573a40ed5024b463e47088d307e3164a486dba5msarett#include "SkLatticeIter.h" 9c573a40ed5024b463e47088d307e3164a486dba5msarett#include "SkRect.h" 10c573a40ed5024b463e47088d307e3164a486dba5msarett 11c573a40ed5024b463e47088d307e3164a486dba5msarett/** 12c573a40ed5024b463e47088d307e3164a486dba5msarett * Divs must be in increasing order with no duplicates. 13c573a40ed5024b463e47088d307e3164a486dba5msarett */ 1471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarettstatic bool valid_divs(const int* divs, int count, int start, int end) { 1571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett int prev = start - 1; 16c573a40ed5024b463e47088d307e3164a486dba5msarett for (int i = 0; i < count; i++) { 1771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett if (prev >= divs[i] || divs[i] >= end) { 18c573a40ed5024b463e47088d307e3164a486dba5msarett return false; 19c573a40ed5024b463e47088d307e3164a486dba5msarett } 20815486c42f1ca66c81e12d8ccc9fb142e3c10544Brian Salomon prev = divs[i]; 21c573a40ed5024b463e47088d307e3164a486dba5msarett } 22c573a40ed5024b463e47088d307e3164a486dba5msarett 23c573a40ed5024b463e47088d307e3164a486dba5msarett return true; 24c573a40ed5024b463e47088d307e3164a486dba5msarett} 25c573a40ed5024b463e47088d307e3164a486dba5msarett 26c573a40ed5024b463e47088d307e3164a486dba5msarettbool SkLatticeIter::Valid(int width, int height, const SkCanvas::Lattice& lattice) { 2771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett SkIRect totalBounds = SkIRect::MakeWH(width, height); 2871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett SkASSERT(lattice.fBounds); 2971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett const SkIRect latticeBounds = *lattice.fBounds; 3071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett if (!totalBounds.contains(latticeBounds)) { 3171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett return false; 3271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett } 3371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett 3471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett bool zeroXDivs = lattice.fXCount <= 0 || (1 == lattice.fXCount && 3571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett latticeBounds.fLeft == lattice.fXDivs[0]); 3671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett bool zeroYDivs = lattice.fYCount <= 0 || (1 == lattice.fYCount && 3771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett latticeBounds.fTop == lattice.fYDivs[0]); 380764efe6a9ae65ad83992f614f57ca9db5b1f191msarett if (zeroXDivs && zeroYDivs) { 390764efe6a9ae65ad83992f614f57ca9db5b1f191msarett return false; 400764efe6a9ae65ad83992f614f57ca9db5b1f191msarett } 410764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 4271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett return valid_divs(lattice.fXDivs, lattice.fXCount, latticeBounds.fLeft, latticeBounds.fRight) 4371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett && valid_divs(lattice.fYDivs, lattice.fYCount, latticeBounds.fTop, latticeBounds.fBottom); 44c573a40ed5024b463e47088d307e3164a486dba5msarett} 45c573a40ed5024b463e47088d307e3164a486dba5msarett 46c573a40ed5024b463e47088d307e3164a486dba5msarett/** 47c573a40ed5024b463e47088d307e3164a486dba5msarett * Count the number of pixels that are in "scalable" patches. 48c573a40ed5024b463e47088d307e3164a486dba5msarett */ 49c573a40ed5024b463e47088d307e3164a486dba5msarettstatic int count_scalable_pixels(const int32_t* divs, int numDivs, bool firstIsScalable, 5071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett int start, int end) { 51c573a40ed5024b463e47088d307e3164a486dba5msarett if (0 == numDivs) { 5271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett return firstIsScalable ? end - start : 0; 53c573a40ed5024b463e47088d307e3164a486dba5msarett } 54c573a40ed5024b463e47088d307e3164a486dba5msarett 55c573a40ed5024b463e47088d307e3164a486dba5msarett int i; 56c573a40ed5024b463e47088d307e3164a486dba5msarett int count; 57c573a40ed5024b463e47088d307e3164a486dba5msarett if (firstIsScalable) { 5871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett count = divs[0] - start; 59c573a40ed5024b463e47088d307e3164a486dba5msarett i = 1; 60c573a40ed5024b463e47088d307e3164a486dba5msarett } else { 61c573a40ed5024b463e47088d307e3164a486dba5msarett count = 0; 62c573a40ed5024b463e47088d307e3164a486dba5msarett i = 0; 63c573a40ed5024b463e47088d307e3164a486dba5msarett } 64c573a40ed5024b463e47088d307e3164a486dba5msarett 65c573a40ed5024b463e47088d307e3164a486dba5msarett for (; i < numDivs; i += 2) { 66c573a40ed5024b463e47088d307e3164a486dba5msarett // Alternatively, we could use |top| and |bottom| as variable names, instead of 67c573a40ed5024b463e47088d307e3164a486dba5msarett // |left| and |right|. 68c573a40ed5024b463e47088d307e3164a486dba5msarett int left = divs[i]; 6971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett int right = (i + 1 < numDivs) ? divs[i + 1] : end; 70c573a40ed5024b463e47088d307e3164a486dba5msarett count += right - left; 71c573a40ed5024b463e47088d307e3164a486dba5msarett } 72c573a40ed5024b463e47088d307e3164a486dba5msarett 73c573a40ed5024b463e47088d307e3164a486dba5msarett return count; 74c573a40ed5024b463e47088d307e3164a486dba5msarett} 75c573a40ed5024b463e47088d307e3164a486dba5msarett 76c573a40ed5024b463e47088d307e3164a486dba5msarett/** 77c573a40ed5024b463e47088d307e3164a486dba5msarett * Set points for the src and dst rects on subsequent draw calls. 78c573a40ed5024b463e47088d307e3164a486dba5msarett */ 79a172bd75619900fc0abda81670e772f07ba4a1d9Leon Scroggins IIIstatic void set_points(float* dst, int* src, const int* divs, int divCount, int srcFixed, 80a172bd75619900fc0abda81670e772f07ba4a1d9Leon Scroggins III int srcScalable, int srcStart, int srcEnd, float dstStart, float dstEnd, 8171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett bool isScalable) { 8271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett float dstLen = dstEnd - dstStart; 83c573a40ed5024b463e47088d307e3164a486dba5msarett float scale; 84c573a40ed5024b463e47088d307e3164a486dba5msarett if (srcFixed <= dstLen) { 85c573a40ed5024b463e47088d307e3164a486dba5msarett // This is the "normal" case, where we scale the "scalable" patches and leave 86c573a40ed5024b463e47088d307e3164a486dba5msarett // the other patches fixed. 87c573a40ed5024b463e47088d307e3164a486dba5msarett scale = (dstLen - ((float) srcFixed)) / ((float) srcScalable); 88c573a40ed5024b463e47088d307e3164a486dba5msarett } else { 89c573a40ed5024b463e47088d307e3164a486dba5msarett // In this case, we eliminate the "scalable" patches and scale the "fixed" patches. 90c573a40ed5024b463e47088d307e3164a486dba5msarett scale = dstLen / ((float) srcFixed); 91c573a40ed5024b463e47088d307e3164a486dba5msarett } 92c573a40ed5024b463e47088d307e3164a486dba5msarett 9371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett src[0] = srcStart; 94c573a40ed5024b463e47088d307e3164a486dba5msarett dst[0] = dstStart; 95c573a40ed5024b463e47088d307e3164a486dba5msarett for (int i = 0; i < divCount; i++) { 96a172bd75619900fc0abda81670e772f07ba4a1d9Leon Scroggins III src[i + 1] = divs[i]; 97a172bd75619900fc0abda81670e772f07ba4a1d9Leon Scroggins III int srcDelta = src[i + 1] - src[i]; 98c573a40ed5024b463e47088d307e3164a486dba5msarett float dstDelta; 99c573a40ed5024b463e47088d307e3164a486dba5msarett if (srcFixed <= dstLen) { 100c573a40ed5024b463e47088d307e3164a486dba5msarett dstDelta = isScalable ? scale * srcDelta : srcDelta; 101c573a40ed5024b463e47088d307e3164a486dba5msarett } else { 102c573a40ed5024b463e47088d307e3164a486dba5msarett dstDelta = isScalable ? 0.0f : scale * srcDelta; 103c573a40ed5024b463e47088d307e3164a486dba5msarett } 104c573a40ed5024b463e47088d307e3164a486dba5msarett dst[i + 1] = dst[i] + dstDelta; 105c573a40ed5024b463e47088d307e3164a486dba5msarett 106c573a40ed5024b463e47088d307e3164a486dba5msarett // Alternate between "scalable" and "fixed" patches. 107c573a40ed5024b463e47088d307e3164a486dba5msarett isScalable = !isScalable; 108c573a40ed5024b463e47088d307e3164a486dba5msarett } 109c573a40ed5024b463e47088d307e3164a486dba5msarett 11071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett src[divCount + 1] = srcEnd; 11171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett dst[divCount + 1] = dstEnd; 112c573a40ed5024b463e47088d307e3164a486dba5msarett} 113c573a40ed5024b463e47088d307e3164a486dba5msarett 11471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarettSkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst) { 115c573a40ed5024b463e47088d307e3164a486dba5msarett const int* xDivs = lattice.fXDivs; 1160764efe6a9ae65ad83992f614f57ca9db5b1f191msarett const int origXCount = lattice.fXCount; 117c573a40ed5024b463e47088d307e3164a486dba5msarett const int* yDivs = lattice.fYDivs; 1180764efe6a9ae65ad83992f614f57ca9db5b1f191msarett const int origYCount = lattice.fYCount; 11971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett SkASSERT(lattice.fBounds); 12071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett const SkIRect src = *lattice.fBounds; 121c573a40ed5024b463e47088d307e3164a486dba5msarett 122c573a40ed5024b463e47088d307e3164a486dba5msarett // In the x-dimension, the first rectangle always starts at x = 0 and is "scalable". 123c573a40ed5024b463e47088d307e3164a486dba5msarett // If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so the 124c573a40ed5024b463e47088d307e3164a486dba5msarett // first real rectangle "scalable" in the x-direction. 125c573a40ed5024b463e47088d307e3164a486dba5msarett // 126c573a40ed5024b463e47088d307e3164a486dba5msarett // The same interpretation applies to the y-dimension. 127c573a40ed5024b463e47088d307e3164a486dba5msarett // 128c573a40ed5024b463e47088d307e3164a486dba5msarett // As we move left to right across the image, alternating patches will be "fixed" or 129c573a40ed5024b463e47088d307e3164a486dba5msarett // "scalable" in the x-direction. Similarly, as move top to bottom, alternating 130c573a40ed5024b463e47088d307e3164a486dba5msarett // patches will be "fixed" or "scalable" in the y-direction. 1310764efe6a9ae65ad83992f614f57ca9db5b1f191msarett int xCount = origXCount; 1320764efe6a9ae65ad83992f614f57ca9db5b1f191msarett int yCount = origYCount; 13371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett bool xIsScalable = (xCount > 0 && src.fLeft == xDivs[0]); 134c573a40ed5024b463e47088d307e3164a486dba5msarett if (xIsScalable) { 135c573a40ed5024b463e47088d307e3164a486dba5msarett // Once we've decided that the first patch is "scalable", we don't need the 13671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett // xDiv. It is always implied that we start at the edge of the bounds. 137c573a40ed5024b463e47088d307e3164a486dba5msarett xDivs++; 138c573a40ed5024b463e47088d307e3164a486dba5msarett xCount--; 139c573a40ed5024b463e47088d307e3164a486dba5msarett } 14071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett bool yIsScalable = (yCount > 0 && src.fTop == yDivs[0]); 141c573a40ed5024b463e47088d307e3164a486dba5msarett if (yIsScalable) { 142c573a40ed5024b463e47088d307e3164a486dba5msarett // Once we've decided that the first patch is "scalable", we don't need the 14371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett // yDiv. It is always implied that we start at the edge of the bounds. 144c573a40ed5024b463e47088d307e3164a486dba5msarett yDivs++; 145c573a40ed5024b463e47088d307e3164a486dba5msarett yCount--; 146c573a40ed5024b463e47088d307e3164a486dba5msarett } 147c573a40ed5024b463e47088d307e3164a486dba5msarett 148c573a40ed5024b463e47088d307e3164a486dba5msarett // Count "scalable" and "fixed" pixels in each dimension. 14971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, src.fLeft, src.fRight); 15071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett int xCountFixed = src.width() - xCountScalable; 15171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett int yCountScalable = count_scalable_pixels(yDivs, yCount, yIsScalable, src.fTop, src.fBottom); 15271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett int yCountFixed = src.height() - yCountScalable; 153c573a40ed5024b463e47088d307e3164a486dba5msarett 154c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcX.reset(xCount + 2); 155c573a40ed5024b463e47088d307e3164a486dba5msarett fDstX.reset(xCount + 2); 156c573a40ed5024b463e47088d307e3164a486dba5msarett set_points(fDstX.begin(), fSrcX.begin(), xDivs, xCount, xCountFixed, xCountScalable, 15771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett src.fLeft, src.fRight, dst.fLeft, dst.fRight, xIsScalable); 158c573a40ed5024b463e47088d307e3164a486dba5msarett 159c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcY.reset(yCount + 2); 160c573a40ed5024b463e47088d307e3164a486dba5msarett fDstY.reset(yCount + 2); 161c573a40ed5024b463e47088d307e3164a486dba5msarett set_points(fDstY.begin(), fSrcY.begin(), yDivs, yCount, yCountFixed, yCountScalable, 16271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett src.fTop, src.fBottom, dst.fTop, dst.fBottom, yIsScalable); 163c573a40ed5024b463e47088d307e3164a486dba5msarett 164c573a40ed5024b463e47088d307e3164a486dba5msarett fCurrX = fCurrY = 0; 1650764efe6a9ae65ad83992f614f57ca9db5b1f191msarett fNumRectsInLattice = (xCount + 1) * (yCount + 1); 1660764efe6a9ae65ad83992f614f57ca9db5b1f191msarett fNumRectsToDraw = fNumRectsInLattice; 1670764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 168ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev if (lattice.fRectTypes) { 169ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev fRectTypes.push_back_n(fNumRectsInLattice); 170ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev fColors.push_back_n(fNumRectsInLattice); 1710764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 172ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev const SkCanvas::Lattice::RectType* flags = lattice.fRectTypes; 173ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev const SkColor* colors = lattice.fColors; 1740764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 1750764efe6a9ae65ad83992f614f57ca9db5b1f191msarett bool hasPadRow = (yCount != origYCount); 1760764efe6a9ae65ad83992f614f57ca9db5b1f191msarett bool hasPadCol = (xCount != origXCount); 1770764efe6a9ae65ad83992f614f57ca9db5b1f191msarett if (hasPadRow) { 1780764efe6a9ae65ad83992f614f57ca9db5b1f191msarett // The first row of rects are all empty, skip the first row of flags. 1790764efe6a9ae65ad83992f614f57ca9db5b1f191msarett flags += origXCount + 1; 180ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev colors += origXCount + 1; 1810764efe6a9ae65ad83992f614f57ca9db5b1f191msarett } 1820764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 1830764efe6a9ae65ad83992f614f57ca9db5b1f191msarett int i = 0; 1840764efe6a9ae65ad83992f614f57ca9db5b1f191msarett for (int y = 0; y < yCount + 1; y++) { 1850764efe6a9ae65ad83992f614f57ca9db5b1f191msarett for (int x = 0; x < origXCount + 1; x++) { 1860764efe6a9ae65ad83992f614f57ca9db5b1f191msarett if (0 == x && hasPadCol) { 1870764efe6a9ae65ad83992f614f57ca9db5b1f191msarett // The first column of rects are all empty. Skip a rect. 1880764efe6a9ae65ad83992f614f57ca9db5b1f191msarett flags++; 189ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev colors++; 1900764efe6a9ae65ad83992f614f57ca9db5b1f191msarett continue; 1910764efe6a9ae65ad83992f614f57ca9db5b1f191msarett } 1920764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 193ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev fRectTypes[i] = *flags; 19434adefa453d70629bc1fa4db96243c5d8eb61aebCary Clark fColors[i] = SkCanvas::Lattice::kFixedColor == *flags ? *colors : 0; 1950764efe6a9ae65ad83992f614f57ca9db5b1f191msarett flags++; 196ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev colors++; 1970764efe6a9ae65ad83992f614f57ca9db5b1f191msarett i++; 1980764efe6a9ae65ad83992f614f57ca9db5b1f191msarett } 1990764efe6a9ae65ad83992f614f57ca9db5b1f191msarett } 2000764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 201ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev for (int j = 0; j < fRectTypes.count(); j++) { 202ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev if (SkCanvas::Lattice::kTransparent == fRectTypes[j]) { 2030764efe6a9ae65ad83992f614f57ca9db5b1f191msarett fNumRectsToDraw--; 2040764efe6a9ae65ad83992f614f57ca9db5b1f191msarett } 2050764efe6a9ae65ad83992f614f57ca9db5b1f191msarett } 2060764efe6a9ae65ad83992f614f57ca9db5b1f191msarett } 207c573a40ed5024b463e47088d307e3164a486dba5msarett} 208c573a40ed5024b463e47088d307e3164a486dba5msarett 209c573a40ed5024b463e47088d307e3164a486dba5msarettbool SkLatticeIter::Valid(int width, int height, const SkIRect& center) { 210c573a40ed5024b463e47088d307e3164a486dba5msarett return !center.isEmpty() && SkIRect::MakeWH(width, height).contains(center); 211c573a40ed5024b463e47088d307e3164a486dba5msarett} 212c573a40ed5024b463e47088d307e3164a486dba5msarett 213c573a40ed5024b463e47088d307e3164a486dba5msarettSkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst) { 214c573a40ed5024b463e47088d307e3164a486dba5msarett SkASSERT(SkIRect::MakeWH(w, h).contains(c)); 215c573a40ed5024b463e47088d307e3164a486dba5msarett 216c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcX.reset(4); 217c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcY.reset(4); 218c573a40ed5024b463e47088d307e3164a486dba5msarett fDstX.reset(4); 219c573a40ed5024b463e47088d307e3164a486dba5msarett fDstY.reset(4); 220c573a40ed5024b463e47088d307e3164a486dba5msarett 221c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcX[0] = 0; 222c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcX[1] = SkIntToScalar(c.fLeft); 223c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcX[2] = SkIntToScalar(c.fRight); 224c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcX[3] = SkIntToScalar(w); 225c573a40ed5024b463e47088d307e3164a486dba5msarett 226c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcY[0] = 0; 227c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcY[1] = SkIntToScalar(c.fTop); 228c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcY[2] = SkIntToScalar(c.fBottom); 229c573a40ed5024b463e47088d307e3164a486dba5msarett fSrcY[3] = SkIntToScalar(h); 230c573a40ed5024b463e47088d307e3164a486dba5msarett 231c573a40ed5024b463e47088d307e3164a486dba5msarett fDstX[0] = dst.fLeft; 232c573a40ed5024b463e47088d307e3164a486dba5msarett fDstX[1] = dst.fLeft + SkIntToScalar(c.fLeft); 233c573a40ed5024b463e47088d307e3164a486dba5msarett fDstX[2] = dst.fRight - SkIntToScalar(w - c.fRight); 234c573a40ed5024b463e47088d307e3164a486dba5msarett fDstX[3] = dst.fRight; 235c573a40ed5024b463e47088d307e3164a486dba5msarett 236c573a40ed5024b463e47088d307e3164a486dba5msarett fDstY[0] = dst.fTop; 237c573a40ed5024b463e47088d307e3164a486dba5msarett fDstY[1] = dst.fTop + SkIntToScalar(c.fTop); 238c573a40ed5024b463e47088d307e3164a486dba5msarett fDstY[2] = dst.fBottom - SkIntToScalar(h - c.fBottom); 239c573a40ed5024b463e47088d307e3164a486dba5msarett fDstY[3] = dst.fBottom; 240c573a40ed5024b463e47088d307e3164a486dba5msarett 241c573a40ed5024b463e47088d307e3164a486dba5msarett if (fDstX[1] > fDstX[2]) { 242c573a40ed5024b463e47088d307e3164a486dba5msarett fDstX[1] = fDstX[0] + (fDstX[3] - fDstX[0]) * c.fLeft / (w - c.width()); 243c573a40ed5024b463e47088d307e3164a486dba5msarett fDstX[2] = fDstX[1]; 244c573a40ed5024b463e47088d307e3164a486dba5msarett } 245c573a40ed5024b463e47088d307e3164a486dba5msarett 246c573a40ed5024b463e47088d307e3164a486dba5msarett if (fDstY[1] > fDstY[2]) { 247c573a40ed5024b463e47088d307e3164a486dba5msarett fDstY[1] = fDstY[0] + (fDstY[3] - fDstY[0]) * c.fTop / (h - c.height()); 248c573a40ed5024b463e47088d307e3164a486dba5msarett fDstY[2] = fDstY[1]; 249c573a40ed5024b463e47088d307e3164a486dba5msarett } 250c573a40ed5024b463e47088d307e3164a486dba5msarett 251c573a40ed5024b463e47088d307e3164a486dba5msarett fCurrX = fCurrY = 0; 2520764efe6a9ae65ad83992f614f57ca9db5b1f191msarett fNumRectsInLattice = 9; 2530764efe6a9ae65ad83992f614f57ca9db5b1f191msarett fNumRectsToDraw = 9; 254c573a40ed5024b463e47088d307e3164a486dba5msarett} 255c573a40ed5024b463e47088d307e3164a486dba5msarett 256a172bd75619900fc0abda81670e772f07ba4a1d9Leon Scroggins IIIbool SkLatticeIter::next(SkIRect* src, SkRect* dst, bool* isFixedColor, SkColor* fixedColor) { 2570764efe6a9ae65ad83992f614f57ca9db5b1f191msarett int currRect = fCurrX + fCurrY * (fSrcX.count() - 1); 2580764efe6a9ae65ad83992f614f57ca9db5b1f191msarett if (currRect == fNumRectsInLattice) { 259c573a40ed5024b463e47088d307e3164a486dba5msarett return false; 260c573a40ed5024b463e47088d307e3164a486dba5msarett } 261c573a40ed5024b463e47088d307e3164a486dba5msarett 262c573a40ed5024b463e47088d307e3164a486dba5msarett const int x = fCurrX; 263c573a40ed5024b463e47088d307e3164a486dba5msarett const int y = fCurrY; 264c573a40ed5024b463e47088d307e3164a486dba5msarett SkASSERT(x >= 0 && x < fSrcX.count() - 1); 265c573a40ed5024b463e47088d307e3164a486dba5msarett SkASSERT(y >= 0 && y < fSrcY.count() - 1); 266c573a40ed5024b463e47088d307e3164a486dba5msarett 267c573a40ed5024b463e47088d307e3164a486dba5msarett if (fSrcX.count() - 1 == ++fCurrX) { 268c573a40ed5024b463e47088d307e3164a486dba5msarett fCurrX = 0; 269c573a40ed5024b463e47088d307e3164a486dba5msarett fCurrY += 1; 270c573a40ed5024b463e47088d307e3164a486dba5msarett } 2710764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 272ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev if (fRectTypes.count() > 0 273ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev && SkToBool(SkCanvas::Lattice::kTransparent == fRectTypes[currRect])) { 274ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev return this->next(src, dst, isFixedColor, fixedColor); 2750764efe6a9ae65ad83992f614f57ca9db5b1f191msarett } 2760764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 2770764efe6a9ae65ad83992f614f57ca9db5b1f191msarett src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]); 2780764efe6a9ae65ad83992f614f57ca9db5b1f191msarett dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]); 279ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev if (isFixedColor && fixedColor) { 280ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev *isFixedColor = fRectTypes.count() > 0 281ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev && SkToBool(SkCanvas::Lattice::kFixedColor == fRectTypes[currRect]); 282ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev if (*isFixedColor) { 283ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev *fixedColor = fColors[currRect]; 284ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev } 285ca8c0953e8da1def5e6c12dde6d4368b4bf16077Stan Iliev } 286c573a40ed5024b463e47088d307e3164a486dba5msarett return true; 287c573a40ed5024b463e47088d307e3164a486dba5msarett} 28810e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett 28910e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarettvoid SkLatticeIter::mapDstScaleTranslate(const SkMatrix& matrix) { 29010e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett SkASSERT(matrix.isScaleTranslate()); 29110e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett SkScalar tx = matrix.getTranslateX(); 29210e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett SkScalar sx = matrix.getScaleX(); 29310e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett for (int i = 0; i < fDstX.count(); i++) { 29410e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett fDstX[i] = fDstX[i] * sx + tx; 29510e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett } 29610e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett 29710e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett SkScalar ty = matrix.getTranslateY(); 29810e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett SkScalar sy = matrix.getScaleY(); 29910e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett for (int i = 0; i < fDstY.count(); i++) { 30010e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett fDstY[i] = fDstY[i] * sy + ty; 30110e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett } 30210e3d9bf59bdec92c05367ae0b71e1ce1ee4a690msarett} 303