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>
This commit is contained in:
Mike Reed 2017-03-17 14:29:05 -04:00 committed by Skia Commit-Bot
parent 9bb0a28b84
commit 795c5ea657
10 changed files with 155 additions and 759 deletions

View File

@ -1,258 +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 "Benchmark.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkPaint.h"
#include "SkPatchGrid.h"
#include "SkString.h"
/**
* This bench measures the rendering time of a gridof patches.
* This bench also tests the different combination of optional parameters for the function
* (passing texture coordinates and colors, only textures coordinates, only colors or none).
* Finally, it also has 3 possible sizes small, medium and big to test if the size of the patches
* in the grid affects time.
*/
class PatchGridBench : public Benchmark {
public:
enum Size {
kSmall_Size,
kMedium_Size,
kBig_Size
};
enum VertexMode {
kNone_VertexMode,
kColors_VertexMode,
kTexCoords_VertexMode,
kBoth_VertexMode
};
PatchGridBench(Size size, VertexMode vertexMode)
: fVertexMode(vertexMode)
, fSize(size) { }
void setScale(SkCanvas* canvas){
switch (fSize) {
case kSmall_Size:
canvas->scale(0.1f, 0.1f);
break;
case kMedium_Size:
canvas->scale(1.0f, 1.0f);
break;
case kBig_Size:
canvas->scale(3.0f, 3.0f);
break;
}
}
void setGrid() {
SkPoint vertices[4][5] = {
{{50,50}, {150,50}, {250,50},{350,50},{450,50}},
{{50,150}, {120,120}, {250,150},{350,150},{450,150}},
{{50,250}, {150,250}, {250,250},{350,250},{450,250}},
{{100,300}, {150,350}, {250,350},{350,350},{450,350}}
};
SkColor cornerColors[4][5] = {
{SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
{SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
{SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
{SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
};
SkPoint texCoords[4][5] = {
{{0.0f,0.0f}, {1.0f,0.0f}, {2.0f,0.0f}, {3.0f,0.0f}, {4.0f,0.0f}},
{{0.0f,1.0f}, {1.0f,1.0f}, {2.0f,1.0f}, {3.0f,1.0f}, {4.0f,1.0f}},
{{0.0f,2.0f}, {1.0f,2.0f}, {2.0f,2.0f}, {3.0f,2.0f}, {4.0f,2.0f}},
{{0.0f,3.0f}, {1.0f,3.0f}, {2.0f,3.0f}, {3.0f,3.0f}, {4.0f,3.0f}},
};
SkPoint hrzCtrl[4][8] = {
{{75,30},{125,45},{175,70},{225,20},{275,50},{325,50},{375,5},{425,90}},
{{75,150},{125,150},{175,150},{225,150},{275,150},{325,150},{375,150},{425,150}},
{{75,250},{125,250},{175,250},{225,250},{275,200},{325,150},{375,250},{425,250}},
{{75,350},{125,350},{175,350},{225,350},{275,350},{325,350},{375,350},{425,350}}
};
SkPoint vrtCtrl[6][5] = {
{{50,75},{150,75},{250,75},{350,75},{450,75}},
{{50,125},{150,125},{250,125},{350,125},{450,125}},
{{50,175},{150,175},{220,225},{350,175},{470,225}},
{{50,225},{150,225},{220,175},{350,225},{470,155}},
{{50,275},{150,275},{250,275},{350,275},{400,305}},
{{50,325},{150,325},{250,325},{350,325},{450,325}}
};
static const int kRows = 3;
static const int kCols = 4;
fGrid.reset(kRows, kCols, SkPatchGrid::kColors_VertexType, SkBlendMode::kModulate);
for (int i = 0; i < kRows; i++) {
for (int j = 0; j < kCols; j++) {
SkPoint points[12];
//set corners
points[SkPatchUtils::kTopP0_CubicCtrlPts] = vertices[i][j];
points[SkPatchUtils::kTopP3_CubicCtrlPts] = vertices[i][j + 1];
points[SkPatchUtils::kBottomP0_CubicCtrlPts] = vertices[i + 1][j];
points[SkPatchUtils::kBottomP3_CubicCtrlPts] = vertices[i + 1][j + 1];
points[SkPatchUtils::kTopP1_CubicCtrlPts] = hrzCtrl[i][j * 2];
points[SkPatchUtils::kTopP2_CubicCtrlPts] = hrzCtrl[i][j * 2 + 1];
points[SkPatchUtils::kBottomP1_CubicCtrlPts] = hrzCtrl[i + 1][j * 2];
points[SkPatchUtils::kBottomP2_CubicCtrlPts] = hrzCtrl[i + 1][j * 2 + 1];
points[SkPatchUtils::kLeftP1_CubicCtrlPts] = vrtCtrl[i * 2][j];
points[SkPatchUtils::kLeftP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j];
points[SkPatchUtils::kRightP1_CubicCtrlPts] = vrtCtrl[i * 2][j + 1];
points[SkPatchUtils::kRightP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j + 1];
SkColor colors[4];
colors[0] = cornerColors[i][j];
colors[1] = cornerColors[i][j + 1];
colors[3] = cornerColors[i + 1][j];
colors[2] = cornerColors[i + 1][j + 1];
SkPoint texs[4];
texs[0] = texCoords[i][j];
texs[1] = texCoords[i][j + 1];
texs[3] = texCoords[i + 1][j];
texs[2] = texCoords[i + 1][j + 1];
switch (fVertexMode) {
case kNone_VertexMode:
fGrid.setPatch(j, i, points, nullptr, nullptr);
break;
case kColors_VertexMode:
fGrid.setPatch(j, i, points, colors, nullptr);
break;
case kTexCoords_VertexMode:
fGrid.setPatch(j, i, points, nullptr, texs);
break;
case kBoth_VertexMode:
fGrid.setPatch(j, i, points, colors, texs);
break;
default:
break;
}
}
}
}
// override this method to change the shader
sk_sp<SkShader> createShader() {
const SkColor colors[] = {
SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE,
SK_ColorMAGENTA, SK_ColorBLUE, SK_ColorYELLOW,
};
const SkPoint pts[] = { { 200.f / 4.f, 0.f }, { 3.f * 200.f / 4, 200.f } };
return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
SkShader::kMirror_TileMode);
}
protected:
const char* onGetName() override {
SkString vertexMode;
switch (fVertexMode) {
case kNone_VertexMode:
vertexMode.set("meshlines");
break;
case kColors_VertexMode:
vertexMode.set("colors");
break;
case kTexCoords_VertexMode:
vertexMode.set("texs");
break;
case kBoth_VertexMode:
vertexMode.set("colors_texs");
break;
default:
break;
}
SkString size;
switch (fSize) {
case kSmall_Size:
size.set("small");
break;
case kMedium_Size:
size.set("medium");
break;
case kBig_Size:
size.set("big");
break;
default:
break;
}
fName.printf("patch_grid_%s_%s", vertexMode.c_str(), size.c_str());
return fName.c_str();
}
void onDelayedSetup() override {
this->setGrid();
switch (fVertexMode) {
case kTexCoords_VertexMode:
case kBoth_VertexMode:
fPaint.setShader(createShader());
break;
default:
fPaint.setShader(nullptr);
break;
}
this->setupPaint(&fPaint);
}
void onDraw(int loops, SkCanvas* canvas) override {
this->setScale(canvas);
for (int i = 0; i < loops; i++) {
fGrid.draw(canvas, fPaint);
}
}
SkPaint fPaint;
SkString fName;
SkPatchGrid fGrid;
VertexMode fVertexMode;
Size fSize;
typedef Benchmark INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
PatchGridBench::kNone_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
PatchGridBench::kColors_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
PatchGridBench::kTexCoords_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kSmall_Size,
PatchGridBench::kBoth_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
PatchGridBench::kNone_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
PatchGridBench::kColors_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
PatchGridBench::kTexCoords_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kMedium_Size,
PatchGridBench::kBoth_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
PatchGridBench::kNone_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
PatchGridBench::kColors_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
PatchGridBench::kTexCoords_VertexMode); )
DEF_BENCH( return new PatchGridBench(PatchGridBench::kBig_Size,
PatchGridBench::kBoth_VertexMode); )

View File

@ -1,159 +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 "gm.h"
#include "SkPatchGrid.h"
static void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) {
//draw control points
SkPaint paint;
SkPoint bottom[4];
SkPatchUtils::getBottomCubic(cubics, bottom);
SkPoint top[4];
SkPatchUtils::getTopCubic(cubics, top);
SkPoint left[4];
SkPatchUtils::getLeftCubic(cubics, left);
SkPoint right[4];
SkPatchUtils::getRightCubic(cubics, right);
paint.setColor(SK_ColorBLACK);
paint.setStrokeWidth(0.5);
SkPoint corners[4] = { bottom[0], bottom[3], top[0], top[3] };
canvas->drawPoints(SkCanvas::kLines_PointMode, 4, bottom, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, bottom+1, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 4, top, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 4, left, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 4, right, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, top+1, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, left+1, paint);
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, right+1, paint);
paint.setStrokeWidth(2);
paint.setColor(SK_ColorRED);
canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, corners, paint);
paint.setColor(SK_ColorBLUE);
canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, bottom+1, paint);
paint.setColor(SK_ColorCYAN);
canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, top+1, paint);
paint.setColor(SK_ColorYELLOW);
canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, left+1, paint);
paint.setColor(SK_ColorGREEN);
canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, right+1, paint);
}
namespace skiagm {
/**
* This GM draws a grid of patches, it only uses colors so it could be considered a mesh gradient.
*/
class SkPatchGridGM : public GM {
public:
SkPatchGridGM() {
this->setBGColor(0xFFFFFFFF);
}
protected:
SkString onShortName() override {
return SkString("patch_grid");
}
SkISize onISize() override {
return SkISize::Make(800, 800);
}
void onDraw(SkCanvas* canvas) override {
SkPaint paint;
SkPoint vertices[4][5] = {
{{50,50}, {150,50}, {250,50},{350,50},{450,50}},
{{50,150}, {120,120}, {250,150},{350,150},{450,150}},
{{50,250}, {150,250}, {250,250},{350,250},{450,250}},
{{100,300}, {150,350}, {250,350},{350,350},{450,350}}
};
SkColor cornerColors[4][5] = {
{SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
{SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
{SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE},
{SK_ColorRED, SK_ColorBLUE, SK_ColorRED, SK_ColorBLUE, SK_ColorRED},
};
SkPoint hrzCtrl[4][8] = {
{{75,30},{125,45},{175,70},{225,20},{275,50},{325,50},{375,5},{425,90}},
{{75,150},{125,150},{175,150},{225,150},{275,150},{325,150},{375,150},{425,150}},
{{75,250},{125,250},{175,250},{225,250},{275,200},{325,150},{375,250},{425,250}},
{{75,350},{125,350},{175,350},{225,350},{275,350},{325,350},{375,350},{425,350}}
};
SkPoint vrtCtrl[6][5] = {
{{50,75},{150,75},{250,75},{350,75},{450,75}},
{{50,125},{150,125},{250,125},{350,125},{450,125}},
{{50,175},{150,175},{220,225},{350,175},{470,225}},
{{50,225},{150,225},{220,175},{350,225},{470,155}},
{{50,275},{150,275},{250,275},{350,275},{400,305}},
{{50,325},{150,325},{250,325},{350,325},{450,325}}
};
constexpr int kRows = 3;
constexpr int kCols = 4;
canvas->scale(3, 3);
SkPatchGrid grid(kRows, kCols, SkPatchGrid::kColors_VertexType);
for (int i = 0; i < kRows; i++) {
for (int j = 0; j < kCols; j++) {
SkPoint points[12];
//set corners
points[SkPatchUtils::kTopP0_CubicCtrlPts] = vertices[i][j];
points[SkPatchUtils::kTopP3_CubicCtrlPts] = vertices[i][j + 1];
points[SkPatchUtils::kBottomP0_CubicCtrlPts] = vertices[i + 1][j];
points[SkPatchUtils::kBottomP3_CubicCtrlPts] = vertices[i + 1][j + 1];
points[SkPatchUtils::kTopP1_CubicCtrlPts] = hrzCtrl[i][j * 2];
points[SkPatchUtils::kTopP2_CubicCtrlPts] = hrzCtrl[i][j * 2 + 1];
points[SkPatchUtils::kBottomP1_CubicCtrlPts] = hrzCtrl[i + 1][j * 2];
points[SkPatchUtils::kBottomP2_CubicCtrlPts] = hrzCtrl[i + 1][j * 2 + 1];
points[SkPatchUtils::kLeftP1_CubicCtrlPts] = vrtCtrl[i * 2][j];
points[SkPatchUtils::kLeftP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j];
points[SkPatchUtils::kRightP1_CubicCtrlPts] = vrtCtrl[i * 2][j + 1];
points[SkPatchUtils::kRightP2_CubicCtrlPts] = vrtCtrl[i * 2 + 1][j + 1];
SkColor colors[4];
colors[0] = cornerColors[i][j];
colors[1] = cornerColors[i][j + 1];
colors[3] = cornerColors[i + 1][j];
colors[2] = cornerColors[i + 1][j + 1];
grid.setPatch(j, i, points, colors, nullptr);
}
}
grid.draw(canvas, paint);
SkISize dims = grid.getDimensions();
for (int y = 0; y < dims.height(); y++) {
for (int x = 0; x < dims.width(); x++) {
SkPoint cubics[12];
grid.getPatch(x, y, cubics, nullptr, nullptr);
draw_control_points(canvas, cubics);
}
}
}
private:
typedef GM INHERITED;
};
DEF_GM(return new SkPatchGridGM;)
}

View File

@ -78,7 +78,6 @@ bench_sources = [
"$_bench/MutexBench.cpp",
"$_bench/pack_int_uint16_t_Bench.cpp",
"$_bench/PatchBench.cpp",
"$_bench/PatchGridBench.cpp",
"$_bench/PathBench.cpp",
"$_bench/PathIterBench.cpp",
"$_bench/PDFBench.cpp",

View File

@ -207,7 +207,6 @@ gm_sources = [
"$_gm/overdrawcolorfilter.cpp",
"$_gm/OverStroke.cpp",
"$_gm/patch.cpp",
"$_gm/patchgrid.cpp",
"$_gm/path_stroke_with_zero_length.cpp",
"$_gm/pathcontourstart.cpp",
"$_gm/patheffects.cpp",

View File

@ -58,8 +58,6 @@ skia_utils_sources = [
"$_src/utils/SkParse.cpp",
"$_src/utils/SkParseColor.cpp",
"$_src/utils/SkParsePath.cpp",
"$_src/utils/SkPatchGrid.cpp",
"$_src/utils/SkPatchGrid.h",
"$_src/utils/SkPatchUtils.cpp",
"$_src/utils/SkPatchUtils.h",
"$_src/utils/SkRGBAToYUV.cpp",

View File

@ -129,13 +129,9 @@ void SkBaseDevice::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
SkPatchUtils::VertexData data;
SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &this->ctm());
// It automatically adjusts lodX and lodY in case it exceeds the number of indices.
// If it fails to generate the vertices, then we do not draw.
if (SkPatchUtils::getVertexData(&data, cubics, colors, texCoords, lod.width(), lod.height())) {
this->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount, data.fPoints,
data.fTexCoords, data.fColors, bmode, data.fIndices, data.fIndexCount,
paint);
auto vertices = SkPatchUtils::MakeVertices(cubics, colors, texCoords, lod.width(), lod.height());
if (vertices) {
this->drawVerticesObject(vertices.get(), bmode, paint);
}
}

View File

@ -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;
}

View File

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

View File

@ -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();
}

View File

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