diff options
author | Mike Reed <reed@google.com> | 2017-03-17 14:29:05 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-03-17 19:28:45 +0000 |
commit | 795c5ea6572ca8b58961ed64d628cc407005f1b3 (patch) | |
tree | ab8b8ba361bc9f7a9cb42951f088c81c8a6087fd /src/utils | |
parent | 9bb0a28b8424a89b0803e6bb9d871ff276dec989 (diff) |
don't use deprecated (raw) form of SkPatchUtils, delete duplicate util
deprecated API still used in android -- will fix (and then delete)
BUG=skia:6366
Change-Id: Icd87acc680f7c8ae66ac231cb5d254f5eb178008
Reviewed-on: https://skia-review.googlesource.com/9864
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/SkPatchGrid.cpp | 189 | ||||
-rw-r--r-- | src/utils/SkPatchGrid.h | 142 | ||||
-rw-r--r-- | src/utils/SkPatchUtils.cpp | 146 | ||||
-rw-r--r-- | src/utils/SkPatchUtils.h | 6 |
4 files changed, 152 insertions, 331 deletions
diff --git a/src/utils/SkPatchGrid.cpp b/src/utils/SkPatchGrid.cpp deleted file mode 100644 index ee30ce1afe..0000000000 --- a/src/utils/SkPatchGrid.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkPatchGrid.h" -#include "SkPatchUtils.h" - -SkPatchGrid::SkPatchGrid(int rows, int cols, VertexType flags) - : fRows(0) - , fCols(0) - , fModeFlags(kNone_VertexType) - , fCornerPts(nullptr) - , fCornerColors(nullptr) - , fTexCoords(nullptr) - , fHrzCtrlPts(nullptr) - , fVrtCtrlPts(nullptr) -{ - this->reset(rows, cols, flags, SkBlendMode::kModulate); -} - -SkPatchGrid::~SkPatchGrid() { - delete[] fCornerPts; - delete[] fCornerColors; - delete[] fTexCoords; - delete[] fHrzCtrlPts; - delete[] fVrtCtrlPts; -} - -bool SkPatchGrid::setPatch(int x, int y, const SkPoint cubics[12], const SkColor colors[4], - const SkPoint texCoords[4]) { - // Check for the passed paramaters to be within the range of the grid dimensions and a valid - // pointer for the cubics' control points. - if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1 || nullptr == cubics) { - return false; - } - - // setup corners and colors - int cornerPos = y * (fCols + 1) + x; - fCornerPts[cornerPos] = cubics[SkPatchUtils::kTopP0_CubicCtrlPts]; - fCornerPts[cornerPos + 1] = cubics[SkPatchUtils::kTopP3_CubicCtrlPts]; - fCornerPts[cornerPos + (fCols + 1)] = cubics[SkPatchUtils::kBottomP0_CubicCtrlPts]; - fCornerPts[cornerPos + (fCols + 1) + 1] = cubics[SkPatchUtils::kBottomP3_CubicCtrlPts]; - - // set horizontal control points - int hrzPos = y * (fCols * 2) + (x * 2); - fHrzCtrlPts[hrzPos] = cubics[SkPatchUtils::kTopP1_CubicCtrlPts]; - fHrzCtrlPts[hrzPos + 1] = cubics[SkPatchUtils::kTopP2_CubicCtrlPts]; - fHrzCtrlPts[hrzPos + (fCols * 2)] = cubics[SkPatchUtils::kBottomP1_CubicCtrlPts]; - fHrzCtrlPts[hrzPos + (fCols * 2) + 1] = cubics[SkPatchUtils::kBottomP2_CubicCtrlPts]; - - // set vertical control points - int vrtPos = (y*2) * (fCols + 1) + x; - fVrtCtrlPts[vrtPos] = cubics[SkPatchUtils::kLeftP1_CubicCtrlPts]; - fVrtCtrlPts[vrtPos + 1] = cubics[SkPatchUtils::kRightP1_CubicCtrlPts]; - fVrtCtrlPts[vrtPos + (fCols + 1)] = cubics[SkPatchUtils::kLeftP2_CubicCtrlPts]; - fVrtCtrlPts[vrtPos + (fCols + 1) + 1] = cubics[SkPatchUtils::kRightP2_CubicCtrlPts]; - - // set optional values (colors and texture coordinates) - if ((fModeFlags & kColors_VertexType) && colors) { - fCornerColors[cornerPos] = colors[0]; - fCornerColors[cornerPos + 1] = colors[1]; - fCornerColors[cornerPos + (fCols + 1)] = colors[3]; - fCornerColors[cornerPos + (fCols + 1) + 1] = colors[2]; - } - - if ((fModeFlags & kTexs_VertexType) && texCoords) { - fTexCoords[cornerPos] = texCoords[0]; - fTexCoords[cornerPos + 1] = texCoords[1]; - fTexCoords[cornerPos + (fCols + 1)] = texCoords[3]; - fTexCoords[cornerPos + (fCols + 1) + 1] = texCoords[2]; - } - - return true; -} - -bool SkPatchGrid::getPatch(int x, int y, SkPoint cubics[12], SkColor colors[4], - SkPoint texCoords[4]) const { - - if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1 || nullptr == cubics) { - return false; - } - - // set the patch by building the array of points and colors with the corresponding values. - int cornerPos = y * (fCols + 1) + x; - cubics[SkPatchUtils::kTopP0_CubicCtrlPts] = fCornerPts[cornerPos]; - cubics[SkPatchUtils::kTopP3_CubicCtrlPts] = fCornerPts[cornerPos + 1]; - cubics[SkPatchUtils::kBottomP0_CubicCtrlPts] = fCornerPts[cornerPos + (fCols + 1)]; - cubics[SkPatchUtils::kBottomP3_CubicCtrlPts] = fCornerPts[cornerPos + (fCols + 1) + 1]; - - int hrzPos = y * (fCols * 2) + (x * 2); - cubics[SkPatchUtils::kTopP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos]; - cubics[SkPatchUtils::kTopP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + 1]; - cubics[SkPatchUtils::kBottomP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols * 2)]; - cubics[SkPatchUtils::kBottomP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols * 2) + 1]; - - int vrtPos = (y*2) * (fCols + 1) + x; - cubics[SkPatchUtils::kLeftP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos]; - cubics[SkPatchUtils::kRightP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos + 1]; - cubics[SkPatchUtils::kLeftP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols + 1)]; - cubics[SkPatchUtils::kRightP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols + 1) + 1]; - - if ((fModeFlags & kColors_VertexType) && colors) { - colors[0] = fCornerColors[cornerPos]; - colors[1] = fCornerColors[cornerPos + 1]; - colors[3] = fCornerColors[cornerPos + (fCols + 1)]; - colors[2] = fCornerColors[cornerPos + (fCols + 1) + 1]; - } - - if ((fModeFlags & kTexs_VertexType) && texCoords) { - texCoords[0] = fTexCoords[cornerPos]; - texCoords[1] = fTexCoords[cornerPos + 1]; - texCoords[3] = fTexCoords[cornerPos + (fCols + 1)]; - texCoords[2] = fTexCoords[cornerPos + (fCols + 1) + 1]; - } - - return true; -} - -void SkPatchGrid::reset(int rows, int cols, VertexType flags, SkBlendMode blendmode) { - delete[] fCornerPts; - delete[] fCornerColors; - delete[] fTexCoords; - delete[] fHrzCtrlPts; - delete[] fVrtCtrlPts; - - fCols = cols; - fRows = rows; - fModeFlags = flags; - fBlendMode = blendmode; - - fCornerPts = new SkPoint[(fRows + 1) * (fCols + 1)]; - fHrzCtrlPts = new SkPoint[(fRows + 1) * fCols * 2]; - fVrtCtrlPts = new SkPoint[fRows * 2 * (fCols + 1)]; - memset(fCornerPts, 0, (fRows + 1) * (fCols + 1) * sizeof(SkPoint)); - memset(fHrzCtrlPts, 0, (fRows + 1) * fCols * 2 * sizeof(SkPoint)); - memset(fVrtCtrlPts, 0, fRows * 2 * (fCols + 1) * sizeof(SkPoint)); - - if (fModeFlags & kColors_VertexType) { - fCornerColors = new SkColor[(fRows + 1) * (fCols + 1)]; - memset(fCornerColors, 0, (fRows + 1) * (fCols + 1) * sizeof(SkColor)); - } - - if (fModeFlags & kTexs_VertexType) { - fTexCoords = new SkPoint[(fRows + 1) * (fCols + 1)]; - memset(fTexCoords, 0, (fRows + 1) * (fCols + 1) * sizeof(SkPoint)); - } -} - -void SkPatchGrid::draw(SkCanvas* canvas, SkPaint& paint) { - int* maxCols = new int[fCols]; - int* maxRows = new int[fRows]; - memset(maxCols, 0, fCols * sizeof(int)); - memset(maxRows, 0, fRows * sizeof(int)); - - // Get the maximum level of detail per axis for each row and column - for (int y = 0; y < fRows; y++) { - for (int x = 0; x < fCols; x++) { - SkPoint cubics[12]; - this->getPatch(x, y, cubics, nullptr, nullptr); - SkMatrix matrix = canvas->getTotalMatrix(); - SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &matrix); - maxCols[x] = SkMax32(maxCols[x], lod.width()); - maxRows[y] = SkMax32(maxRows[y], lod.height()); - } - } - // Draw the patches by generating their geometry with the maximum level of detail per axis. - for (int x = 0; x < fCols; x++) { - for (int y = 0; y < fRows; y++) { - SkPoint cubics[12]; - SkPoint texCoords[4]; - SkColor colors[4]; - this->getPatch(x, y, cubics, colors, texCoords); - SkPatchUtils::VertexData data; - if (SkPatchUtils::getVertexData(&data, cubics, - fModeFlags & kColors_VertexType ? colors : nullptr, - fModeFlags & kTexs_VertexType ? texCoords : nullptr, - maxCols[x], maxRows[y])) { - canvas->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount, - data.fPoints, data.fTexCoords, data.fColors, fBlendMode, - data.fIndices, data.fIndexCount, paint); - } - } - } - delete[] maxCols; - delete[] maxRows; -} diff --git a/src/utils/SkPatchGrid.h b/src/utils/SkPatchGrid.h deleted file mode 100644 index 97a6cb3f01..0000000000 --- a/src/utils/SkPatchGrid.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkPatchGrid_DEFINED -#define SkPatchGrid_DEFINED - -#include "SkCanvas.h" -#include "SkPatchUtils.h" - -/** - * Class that represents a grid of patches. Adjacent patches share their corners and a color is - * specified at each one of them. The colors are bilinearly interpolated across the patch. - * - * This implementation defines a bidimensional array of patches. There are 3 arrays to store the - * control points of the patches to avoid storing repeated data since there are several points - * shared between adjacent patches. - * - * The array fCornerPts stores the corner control points of the patches. - * The array fHrzPts holds the intermidiate control points of the top and bottom curves of a patch. - * The array fVrtPts holds the intermidiate control points of the left and right curves of a patch. - * The array fCornerColors holds the corner colors in the same format as fCornerPts. - * The array fTexCoords holds the texture coordinates in the same format as fCornerpts. - * - * fCornerPts fHrzPts fVrtPts - * -------------- ------------------- -------------- - * | C0 | C1 | C2 | | H0 | H1 | H2 | H3 | | V0 | V1 | V2 | - * -------------- ------------------ --------------- - * | C3 | C4 | C5 | | H4 | H5 | H6 | H7 | | V4 | V5 | V6 | - * -------------- ------------------- -------------- - * | C6 | C7 | C8 | | H8 | H9 | H10| H11| | V6 | V7 | V8 | - * -------------- ------------------- -------------- - * | V9 | V10| V11| - * -------------- - * - * With the above configuration we would have a 2x2 grid of patches: - * H0 H1 H2 H3 - * / \/ \ - * C0-------C1-------C2 - * /| | |\ - * v0 | v1 | v2 - * v3 | V4 | v5 - * \| | |/ - * C3-H4-H5-C4-H6-H7-C5 - * /| | |\ - * v6 | v7 | v8 - * v9 | v10 | v11 - * \| | |/ - * C6-------C7-------C8 - * \ / \ / - * H8 H9 H10 H11 - * - * When trying to get a patch at a certain position it justs builds it with the corresponding - * points. - * When adding a patch it tries to add the points at their corresponding position trying to comply - * with the adjacent points or overwriting them. - * - * Based the idea on the SVG2 spec for mesh gradients in which a grid of patches is build as in the - * the following example: - * <meshGradient x="100" y="100"> - * <meshRow> - * <meshPatch> - * <stop .../> - * Up to four stops in first patch. See details below. - * </meshPatch> - * <meshPatch> - * Any number of meshPatches in row. - * </meshPatch> - * </meshRow> - * <meshRow> - * Any number of meshRows, each with the same number of meshPatches as in the first row. - * </meshRow> - * </meshGradient> - */ -class SkPatchGrid { - -public: - - enum VertexType { - kNone_VertexType = 0X00, - kColors_VertexType = 0x01, - kTexs_VertexType = 0x02, - kColorsAndTexs_VertexType = 0x03 - }; - - SkPatchGrid(int rows = 0, int cols = 0, VertexType flags = kNone_VertexType); - - ~SkPatchGrid(); - - /** - * Add a patch at location (x,y) overwriting the previous patch and shared points so they - * mantain C0 connectivity. - * The control points must be passed in a clockwise order starting at the top left corner. - * The colors and texCoords are the values at the corners of the patch which will be bilerp - * across it, they must also be in counterclockwise order starting at the top left corner. - */ - bool setPatch(int x, int y, const SkPoint cubics[12], const SkColor colors[4], - const SkPoint texCoords[4]); - - /** - * Get patch at location (x,y). If cubics, colors or texCoords is not nullptr it sets patch's - * array with its corresponding values. - * The function returns false if the cubics parameter is nullptr or if the (x,y) coordinates are - * not within the range of the grid. - */ - bool getPatch(int x, int y, SkPoint cubics[12], SkColor colors[4], SkPoint texCoords[4]) const; - - /** - * Resets the grid of patches to contain rows and cols of patches. - */ - void reset(int rows, int cols, VertexType flags, SkBlendMode); - - /** - * Draws the grid of patches. The patches are drawn starting at patch (0,0) drawing columns, so - * for a 2x2 grid the order would be (0,0)->(0,1)->(1,0)->(1,1). The order follows the order - * of the parametric coordinates of the coons patch. - */ - void draw(SkCanvas* canvas, SkPaint& paint); - - /** - * Get the dimensions of the grid of patches. - */ - SkISize getDimensions() const { - return SkISize::Make(fCols, fRows); - } - -private: - int fRows, fCols; - VertexType fModeFlags; - SkPoint* fCornerPts; - SkColor* fCornerColors; - SkPoint* fTexCoords; - SkPoint* fHrzCtrlPts; - SkPoint* fVrtCtrlPts; - SkBlendMode fBlendMode = SkBlendMode::kModulate; -}; - - -#endif diff --git a/src/utils/SkPatchUtils.cpp b/src/utils/SkPatchUtils.cpp index cbaae39e8e..52ecfb1ec5 100644 --- a/src/utils/SkPatchUtils.cpp +++ b/src/utils/SkPatchUtils.cpp @@ -309,3 +309,149 @@ bool SkPatchUtils::getVertexData(SkPatchUtils::VertexData* data, const SkPoint c return true; } + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +sk_sp<SkVertices> SkPatchUtils::MakeVertices(const SkPoint cubics[12], const SkColor srcColors[4], + const SkPoint srcTexCoords[4], int lodX, int lodY) { + if (lodX < 1 || lodY < 1 || nullptr == cubics) { + return nullptr; + } + + // check for overflow in multiplication + const int64_t lodX64 = (lodX + 1), + lodY64 = (lodY + 1), + mult64 = lodX64 * lodY64; + if (mult64 > SK_MaxS32) { + return nullptr; + } + + int vertexCount = SkToS32(mult64); + // it is recommended to generate draw calls of no more than 65536 indices, so we never generate + // more than 60000 indices. To accomplish that we resize the LOD and vertex count + if (vertexCount > 10000 || lodX > 200 || lodY > 200) { + float weightX = static_cast<float>(lodX) / (lodX + lodY); + float weightY = static_cast<float>(lodY) / (lodX + lodY); + + // 200 comes from the 100 * 2 which is the max value of vertices because of the limit of + // 60000 indices ( sqrt(60000 / 6) that comes from data->fIndexCount = lodX * lodY * 6) + lodX = static_cast<int>(weightX * 200); + lodY = static_cast<int>(weightY * 200); + vertexCount = (lodX + 1) * (lodY + 1); + } + const int indexCount = lodX * lodY * 6; + uint32_t flags = 0; + if (srcTexCoords) { + flags |= SkVertices::kHasTexCoords_BuilderFlag; + } + if (srcColors) { + flags |= SkVertices::kHasColors_BuilderFlag; + } + + SkVertices::Builder builder(SkCanvas::kTriangles_VertexMode, vertexCount, indexCount, flags); + SkPoint* pos = builder.positions(); + SkPoint* texs = builder.texCoords(); + SkColor* colors = builder.colors(); + uint16_t* indices = builder.indices(); + + // if colors is not null then create array for colors + SkPMColor colorsPM[kNumCorners]; + if (srcColors) { + // premultiply colors to avoid color bleeding. + for (int i = 0; i < kNumCorners; i++) { + colorsPM[i] = SkPreMultiplyColor(srcColors[i]); + } + srcColors = colorsPM; + } + + SkPoint pts[kNumPtsCubic]; + SkPatchUtils::getBottomCubic(cubics, pts); + FwDCubicEvaluator fBottom(pts); + SkPatchUtils::getTopCubic(cubics, pts); + FwDCubicEvaluator fTop(pts); + SkPatchUtils::getLeftCubic(cubics, pts); + FwDCubicEvaluator fLeft(pts); + SkPatchUtils::getRightCubic(cubics, pts); + FwDCubicEvaluator fRight(pts); + + fBottom.restart(lodX); + fTop.restart(lodX); + + SkScalar u = 0.0f; + int stride = lodY + 1; + for (int x = 0; x <= lodX; x++) { + SkPoint bottom = fBottom.next(), top = fTop.next(); + fLeft.restart(lodY); + fRight.restart(lodY); + SkScalar v = 0.f; + for (int y = 0; y <= lodY; y++) { + int dataIndex = x * (lodY + 1) + y; + + SkPoint left = fLeft.next(), right = fRight.next(); + + SkPoint s0 = SkPoint::Make((1.0f - v) * top.x() + v * bottom.x(), + (1.0f - v) * top.y() + v * bottom.y()); + SkPoint s1 = SkPoint::Make((1.0f - u) * left.x() + u * right.x(), + (1.0f - u) * left.y() + u * right.y()); + SkPoint s2 = SkPoint::Make( + (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].x() + + u * fTop.getCtrlPoints()[3].x()) + + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].x() + + u * fBottom.getCtrlPoints()[3].x()), + (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].y() + + u * fTop.getCtrlPoints()[3].y()) + + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].y() + + u * fBottom.getCtrlPoints()[3].y())); + pos[dataIndex] = s0 + s1 - s2; + + if (colors) { + uint8_t a = uint8_t(bilerp(u, v, + SkScalar(SkColorGetA(colorsPM[kTopLeft_Corner])), + SkScalar(SkColorGetA(colorsPM[kTopRight_Corner])), + SkScalar(SkColorGetA(colorsPM[kBottomLeft_Corner])), + SkScalar(SkColorGetA(colorsPM[kBottomRight_Corner])))); + uint8_t r = uint8_t(bilerp(u, v, + SkScalar(SkColorGetR(colorsPM[kTopLeft_Corner])), + SkScalar(SkColorGetR(colorsPM[kTopRight_Corner])), + SkScalar(SkColorGetR(colorsPM[kBottomLeft_Corner])), + SkScalar(SkColorGetR(colorsPM[kBottomRight_Corner])))); + uint8_t g = uint8_t(bilerp(u, v, + SkScalar(SkColorGetG(colorsPM[kTopLeft_Corner])), + SkScalar(SkColorGetG(colorsPM[kTopRight_Corner])), + SkScalar(SkColorGetG(colorsPM[kBottomLeft_Corner])), + SkScalar(SkColorGetG(colorsPM[kBottomRight_Corner])))); + uint8_t b = uint8_t(bilerp(u, v, + SkScalar(SkColorGetB(colorsPM[kTopLeft_Corner])), + SkScalar(SkColorGetB(colorsPM[kTopRight_Corner])), + SkScalar(SkColorGetB(colorsPM[kBottomLeft_Corner])), + SkScalar(SkColorGetB(colorsPM[kBottomRight_Corner])))); + colors[dataIndex] = SkPackARGB32(a,r,g,b); + } + + if (texs) { + texs[dataIndex] = SkPoint::Make(bilerp(u, v, srcTexCoords[kTopLeft_Corner].x(), + srcTexCoords[kTopRight_Corner].x(), + srcTexCoords[kBottomLeft_Corner].x(), + srcTexCoords[kBottomRight_Corner].x()), + bilerp(u, v, srcTexCoords[kTopLeft_Corner].y(), + srcTexCoords[kTopRight_Corner].y(), + srcTexCoords[kBottomLeft_Corner].y(), + srcTexCoords[kBottomRight_Corner].y())); + + } + + if(x < lodX && y < lodY) { + int i = 6 * (x * lodY + y); + indices[i] = x * stride + y; + indices[i + 1] = x * stride + 1 + y; + indices[i + 2] = (x + 1) * stride + 1 + y; + indices[i + 3] = indices[i]; + indices[i + 4] = indices[i + 2]; + indices[i + 5] = (x + 1) * stride + y; + } + v = SkScalarClampMax(v + 1.f / lodY, 1); + } + u = SkScalarClampMax(u + 1.f / lodX, 1); + } + return builder.detach(); +} diff --git a/src/utils/SkPatchUtils.h b/src/utils/SkPatchUtils.h index 67ab621e8e..c1e8ac1c2f 100644 --- a/src/utils/SkPatchUtils.h +++ b/src/utils/SkPatchUtils.h @@ -10,10 +10,12 @@ #include "SkColorPriv.h" #include "SkMatrix.h" +#include "SkVertices.h" class SK_API SkPatchUtils { public: + // DEPRECATED -- use MakeVertices() /** * Structure that holds the vertex data related to the tessellation of a patch. It is passed * as a parameter to the function getVertexData which sets the points, colors and texture @@ -104,6 +106,7 @@ public: */ static void getRightCubic(const SkPoint cubics[12], SkPoint points[4]); + // DEPRECATED -- use MakeVertices() /** * Function that evaluates the coons patch interpolation. * data refers to the pointer of the PatchData struct in which the tessellation data is set. @@ -116,6 +119,9 @@ public: static bool getVertexData(SkPatchUtils::VertexData* data, const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], int lodX, int lodY); + + static sk_sp<SkVertices> MakeVertices(const SkPoint cubics[12], const SkColor colors[4], + const SkPoint texCoords[4], int lodX, int lodY); }; #endif |