ba4847cc3b
This is a reland of 1b016d50b9
Original change's description:
> Intersection calc cleanup.
>
> * Fixes some bugs in compute_intersection
> * Adds an intersection check that doesn't need to compute the exact pt
> * Make some of the variable names consistent
> * General floating point tweaks
>
> Bug: skia:
> Change-Id: Ib2fb8bee39b5d9c635d62e606fe826b7efe64dfa
> Reviewed-on: https://skia-review.googlesource.com/145532
> Commit-Queue: Jim Van Verth <jvanverth@google.com>
> Reviewed-by: Brian Osman <brianosman@google.com>
Bug: skia:
Change-Id: I3fe00add6f700b58fd756b9fbb24078e010ed9ba
Reviewed-on: https://skia-review.googlesource.com/145920
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
635 lines
17 KiB
C++
635 lines
17 KiB
C++
/*
|
|
* Copyright 2018 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 "sk_tool_utils.h"
|
|
#include "SkPolyUtils.h"
|
|
#include "SkPathPriv.h"
|
|
|
|
static void create_ngon(int n, SkPoint* pts, SkScalar w, SkScalar h, SkPath::Direction dir) {
|
|
float angleStep = 360.0f / n, angle = 0.0f, sin, cos;
|
|
if ((n % 2) == 1) {
|
|
angle = angleStep/2.0f;
|
|
}
|
|
if (SkPath::kCCW_Direction == dir) {
|
|
angle = -angle;
|
|
angleStep = -angleStep;
|
|
}
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
sin = SkScalarSinCos(SkDegreesToRadians(angle), &cos);
|
|
pts[i].fX = -sin * w;
|
|
pts[i].fY = cos * h;
|
|
angle += angleStep;
|
|
}
|
|
}
|
|
|
|
namespace PolygonOffsetData {
|
|
// narrow rect
|
|
const SkPoint gPoints0[] = {
|
|
{ -1.5f, -50.0f },
|
|
{ 1.5f, -50.0f },
|
|
{ 1.5f, 50.0f },
|
|
{ -1.5f, 50.0f }
|
|
};
|
|
// narrow rect on an angle
|
|
const SkPoint gPoints1[] = {
|
|
{ -50.0f, -49.0f },
|
|
{ -49.0f, -50.0f },
|
|
{ 50.0f, 49.0f },
|
|
{ 49.0f, 50.0f }
|
|
};
|
|
// trap - narrow on top - wide on bottom
|
|
const SkPoint gPoints2[] = {
|
|
{ -10.0f, -50.0f },
|
|
{ 10.0f, -50.0f },
|
|
{ 50.0f, 50.0f },
|
|
{ -50.0f, 50.0f }
|
|
};
|
|
// wide skewed rect
|
|
const SkPoint gPoints3[] = {
|
|
{ -50.0f, -50.0f },
|
|
{ 0.0f, -50.0f },
|
|
{ 50.0f, 50.0f },
|
|
{ 0.0f, 50.0f }
|
|
};
|
|
// thin rect with colinear-ish lines
|
|
const SkPoint gPoints4[] = {
|
|
{ -6.0f, -50.0f },
|
|
{ 4.0f, -50.0f },
|
|
{ 5.0f, -25.0f },
|
|
{ 6.0f, 0.0f },
|
|
{ 5.0f, 25.0f },
|
|
{ 4.0f, 50.0f },
|
|
{ -4.0f, 50.0f }
|
|
};
|
|
// degenerate
|
|
const SkPoint gPoints5[] = {
|
|
{ -0.025f, -0.025f },
|
|
{ 0.025f, -0.025f },
|
|
{ 0.025f, 0.025f },
|
|
{ -0.025f, 0.025f }
|
|
};
|
|
// Quad with near coincident point
|
|
const SkPoint gPoints6[] = {
|
|
{ -20.0f, -13.0f },
|
|
{ -20.0f, -13.05f },
|
|
{ 20.0f, -13.0f },
|
|
{ 20.0f, 27.0f }
|
|
};
|
|
// thin rect with colinear lines
|
|
const SkPoint gPoints7[] = {
|
|
{ -10.0f, -50.0f },
|
|
{ 10.0f, -50.0f },
|
|
{ 10.0f, -20.0f },
|
|
{ 10.0f, 0.0f },
|
|
{ 10.0f, 35.0f },
|
|
{ 10.0f, 50.0f },
|
|
{ -10.0f, 50.0f }
|
|
};
|
|
// capped teardrop
|
|
const SkPoint gPoints8[] = {
|
|
{ 50.00f, 50.00f },
|
|
{ 0.00f, 50.00f },
|
|
{ -15.45f, 47.55f },
|
|
{ -29.39f, 40.45f },
|
|
{ -40.45f, 29.39f },
|
|
{ -47.55f, 15.45f },
|
|
{ -50.00f, 0.00f },
|
|
{ -47.55f, -15.45f },
|
|
{ -40.45f, -29.39f },
|
|
{ -29.39f, -40.45f },
|
|
{ -15.45f, -47.55f },
|
|
{ 0.00f, -50.00f },
|
|
{ 50.00f, -50.00f }
|
|
};
|
|
// teardrop
|
|
const SkPoint gPoints9[] = {
|
|
{ 4.39f, 40.45f },
|
|
{ -9.55f, 47.55f },
|
|
{ -25.00f, 50.00f },
|
|
{ -40.45f, 47.55f },
|
|
{ -54.39f, 40.45f },
|
|
{ -65.45f, 29.39f },
|
|
{ -72.55f, 15.45f },
|
|
{ -75.00f, 0.00f },
|
|
{ -72.55f, -15.45f },
|
|
{ -65.45f, -29.39f },
|
|
{ -54.39f, -40.45f },
|
|
{ -40.45f, -47.55f },
|
|
{ -25.0f, -50.0f },
|
|
{ -9.55f, -47.55f },
|
|
{ 4.39f, -40.45f },
|
|
{ 75.00f, 0.00f }
|
|
};
|
|
// clipped triangle
|
|
const SkPoint gPoints10[] = {
|
|
{ -10.0f, -50.0f },
|
|
{ 10.0f, -50.0f },
|
|
{ 50.0f, 31.0f },
|
|
{ 40.0f, 50.0f },
|
|
{ -40.0f, 50.0f },
|
|
{ -50.0f, 31.0f },
|
|
};
|
|
|
|
// tab
|
|
const SkPoint gPoints11[] = {
|
|
{ -45, -25 },
|
|
{ 45, -25 },
|
|
{ 45, 25 },
|
|
{ 20, 25 },
|
|
{ 19.6157f, 25.f + 3.9018f },
|
|
{ 18.4776f, 25.f + 7.6537f },
|
|
{ 16.6294f, 25.f + 11.1114f },
|
|
{ 14.1421f, 25.f + 14.1421f },
|
|
{ 11.1114f, 25.f + 16.6294f },
|
|
{ 7.6537f, 25.f + 18.4776f },
|
|
{ 3.9018f, 25.f + 19.6157f },
|
|
{ 0, 45.f },
|
|
{ -3.9018f, 25.f + 19.6157f },
|
|
{ -7.6537f, 25.f + 18.4776f },
|
|
{ -11.1114f, 25.f + 16.6294f },
|
|
{ -14.1421f, 25.f + 14.1421f },
|
|
{ -16.6294f, 25.f + 11.1114f },
|
|
{ -18.4776f, 25.f + 7.6537f },
|
|
{ -19.6157f, 25.f + 3.9018f },
|
|
{ -20, 25 },
|
|
{ -45, 25 }
|
|
};
|
|
|
|
// star of david
|
|
const SkPoint gPoints12[] = {
|
|
{ 0.0f, -50.0f },
|
|
{ 14.43f, -25.0f },
|
|
{ 43.30f, -25.0f },
|
|
{ 28.86f, 0.0f },
|
|
{ 43.30f, 25.0f },
|
|
{ 14.43f, 25.0f },
|
|
{ 0.0f, 50.0f },
|
|
{ -14.43f, 25.0f },
|
|
{ -43.30f, 25.0f },
|
|
{ -28.86f, 0.0f },
|
|
{ -43.30f, -25.0f },
|
|
{ -14.43f, -25.0f },
|
|
};
|
|
|
|
// notch
|
|
const SkScalar kBottom = 25.f;
|
|
const SkPoint gPoints13[] = {
|
|
{ -50, kBottom - 50.f },
|
|
{ 50, kBottom - 50.f },
|
|
{ 50, kBottom },
|
|
{ 20, kBottom },
|
|
{ 19.6157f, kBottom - 3.9018f },
|
|
{ 18.4776f, kBottom - 7.6537f },
|
|
{ 16.6294f, kBottom - 11.1114f },
|
|
{ 14.1421f, kBottom - 14.1421f },
|
|
{ 11.1114f, kBottom - 16.6294f },
|
|
{ 7.6537f, kBottom - 18.4776f },
|
|
{ 3.9018f, kBottom - 19.6157f },
|
|
{ 0, kBottom - 20.f },
|
|
{ -3.9018f, kBottom - 19.6157f },
|
|
{ -7.6537f, kBottom - 18.4776f },
|
|
{ -11.1114f, kBottom - 16.6294f },
|
|
{ -14.1421f, kBottom - 14.1421f },
|
|
{ -16.6294f, kBottom - 11.1114f },
|
|
{ -18.4776f, kBottom - 7.6537f },
|
|
{ -19.6157f, kBottom - 3.9018f },
|
|
{ -20, kBottom },
|
|
{ -50, kBottom }
|
|
};
|
|
|
|
// crown
|
|
const SkPoint gPoints14[] = {
|
|
{ -40, -39 },
|
|
{ 40, -39 },
|
|
{ 40, -20 },
|
|
{ 30, 40 },
|
|
{ 20, -20 },
|
|
{ 10, 40 },
|
|
{ 0, -20 },
|
|
{ -10, 40 },
|
|
{ -20, -20 },
|
|
{ -30, 40 },
|
|
{ -40, -20 }
|
|
};
|
|
|
|
// dumbbell
|
|
const SkPoint gPoints15[] = {
|
|
{ -26, -3 },
|
|
{ -24, -6.2f },
|
|
{ -22.5f, -8 },
|
|
{ -20, -9.9f },
|
|
{ -17.5f, -10.3f },
|
|
{ -15, -10.9f },
|
|
{ -12.5f, -10.2f },
|
|
{ -10, -9.7f },
|
|
{ -7.5f, -8.1f },
|
|
{ -5, -7.7f },
|
|
{ -2.5f, -7.4f },
|
|
{ 0, -7.7f },
|
|
{ 3, -9 },
|
|
{ 6.5f, -11.5f },
|
|
{ 10.6f, -14 },
|
|
{ 14, -15.2f },
|
|
{ 17, -15.5f },
|
|
{ 20, -15.2f },
|
|
{ 23.4f, -14 },
|
|
{ 27.5f, -11.5f },
|
|
{ 30, -8 },
|
|
{ 32, -4 },
|
|
{ 32.5f, 0 },
|
|
{ 32, 4 },
|
|
{ 30, 8 },
|
|
{ 27.5f, 11.5f },
|
|
{ 23.4f, 14 },
|
|
{ 20, 15.2f },
|
|
{ 17, 15.5f },
|
|
{ 14, 15.2f },
|
|
{ 10.6f, 14 },
|
|
{ 6.5f, 11.5f },
|
|
{ 3, 9 },
|
|
{ 0, 7.7f },
|
|
{ -2.5f, 7.4f },
|
|
{ -5, 7.7f },
|
|
{ -7.5f, 8.1f },
|
|
{ -10, 9.7f },
|
|
{ -12.5f, 10.2f },
|
|
{ -15, 10.9f },
|
|
{ -17.5f, 10.3f },
|
|
{ -20, 9.9f },
|
|
{ -22.5f, 8 },
|
|
{ -24, 6.2f },
|
|
{ -26, 3 },
|
|
{ -26.5f, 0 }
|
|
};
|
|
|
|
// truncated dumbbell
|
|
// (checks winding computation in OffsetSimplePolygon)
|
|
const SkPoint gPoints16[] = {
|
|
{ -15 + 3, -9 },
|
|
{ -15 + 6.5f, -11.5f },
|
|
{ -15 + 10.6f, -14 },
|
|
{ -15 + 14, -15.2f },
|
|
{ -15 + 17, -15.5f },
|
|
{ -15 + 20, -15.2f },
|
|
{ -15 + 23.4f, -14 },
|
|
{ -15 + 27.5f, -11.5f },
|
|
{ -15 + 30, -8 },
|
|
{ -15 + 32, -4 },
|
|
{ -15 + 32.5f, 0 },
|
|
{ -15 + 32, 4 },
|
|
{ -15 + 30, 8 },
|
|
{ -15 + 27.5f, 11.5f },
|
|
{ -15 + 23.4f, 14 },
|
|
{ -15 + 20, 15.2f },
|
|
{ -15 + 17, 15.5f },
|
|
{ -15 + 14, 15.2f },
|
|
{ -15 + 10.6f, 14 },
|
|
{ -15 + 6.5f, 11.5f },
|
|
{ -15 + 3, 9 },
|
|
};
|
|
|
|
// square notch
|
|
// (to detect segment-segment intersection)
|
|
const SkPoint gPoints17[] = {
|
|
{ -50, kBottom - 50.f },
|
|
{ 50, kBottom - 50.f },
|
|
{ 50, kBottom },
|
|
{ 20, kBottom },
|
|
{ 20, kBottom - 20.f },
|
|
{ -20, kBottom - 20.f },
|
|
{ -20, kBottom },
|
|
{ -50, kBottom }
|
|
};
|
|
|
|
// box with Peano curve
|
|
const SkPoint gPoints18[] = {
|
|
{ 0, 0 },
|
|
{ 0, -12 },
|
|
{ -6, -12 },
|
|
{ -6, 0 },
|
|
{ -12, 0 },
|
|
{ -12, -12},
|
|
{ -18, -12},
|
|
{ -18, 18},
|
|
{ -12, 18},
|
|
{-12, 6},
|
|
{-6, 6},
|
|
{-6, 36},
|
|
{-12, 36},
|
|
{-12, 24},
|
|
{-18, 24},
|
|
{-18, 36},
|
|
{-24, 36},
|
|
{-24, 24},
|
|
{-30, 24},
|
|
{-30, 36},
|
|
{-36, 36},
|
|
{-36, 6},
|
|
{-30, 6},
|
|
{-30, 18},
|
|
{-24, 18},
|
|
{-24, -12},
|
|
{-30, -12},
|
|
{-30, 0},
|
|
{-36, 0},
|
|
{-36, -36},
|
|
{36, -36},
|
|
{36, 36},
|
|
{12, 36},
|
|
{12, 24},
|
|
{6, 24},
|
|
{6, 36},
|
|
{0, 36},
|
|
{0, 6},
|
|
{6, 6},
|
|
{6, 18},
|
|
{12, 18},
|
|
{12, -12},
|
|
{6, -12},
|
|
{6, 0}
|
|
};
|
|
|
|
|
|
const SkPoint* gConvexPoints[] = {
|
|
gPoints0, gPoints1, gPoints2, gPoints3, gPoints4, gPoints5, gPoints6,
|
|
gPoints7, gPoints8, gPoints9, gPoints10,
|
|
};
|
|
|
|
const size_t gConvexSizes[] = {
|
|
SK_ARRAY_COUNT(gPoints0),
|
|
SK_ARRAY_COUNT(gPoints1),
|
|
SK_ARRAY_COUNT(gPoints2),
|
|
SK_ARRAY_COUNT(gPoints3),
|
|
SK_ARRAY_COUNT(gPoints4),
|
|
SK_ARRAY_COUNT(gPoints5),
|
|
SK_ARRAY_COUNT(gPoints6),
|
|
SK_ARRAY_COUNT(gPoints7),
|
|
SK_ARRAY_COUNT(gPoints8),
|
|
SK_ARRAY_COUNT(gPoints9),
|
|
SK_ARRAY_COUNT(gPoints10),
|
|
};
|
|
static_assert(SK_ARRAY_COUNT(gConvexSizes) == SK_ARRAY_COUNT(gConvexPoints), "array_mismatch");
|
|
|
|
const SkPoint* gSimplePoints[] = {
|
|
gPoints0, gPoints1, gPoints2, gPoints4, gPoints5, gPoints7,
|
|
gPoints8, gPoints11, gPoints12, gPoints13, gPoints14, gPoints15,
|
|
gPoints16, gPoints17, gPoints18,
|
|
};
|
|
|
|
const size_t gSimpleSizes[] = {
|
|
SK_ARRAY_COUNT(gPoints0),
|
|
SK_ARRAY_COUNT(gPoints1),
|
|
SK_ARRAY_COUNT(gPoints2),
|
|
SK_ARRAY_COUNT(gPoints4),
|
|
SK_ARRAY_COUNT(gPoints5),
|
|
SK_ARRAY_COUNT(gPoints7),
|
|
SK_ARRAY_COUNT(gPoints8),
|
|
SK_ARRAY_COUNT(gPoints11),
|
|
SK_ARRAY_COUNT(gPoints12),
|
|
SK_ARRAY_COUNT(gPoints13),
|
|
SK_ARRAY_COUNT(gPoints14),
|
|
SK_ARRAY_COUNT(gPoints15),
|
|
SK_ARRAY_COUNT(gPoints16),
|
|
SK_ARRAY_COUNT(gPoints17),
|
|
SK_ARRAY_COUNT(gPoints18),
|
|
};
|
|
static_assert(SK_ARRAY_COUNT(gSimpleSizes) == SK_ARRAY_COUNT(gSimplePoints), "array_mismatch");
|
|
|
|
}
|
|
|
|
namespace skiagm {
|
|
|
|
// This GM is intended to exercise the offsetting of polygons
|
|
// When fVariableOffset is true it will skew the offset by x,
|
|
// to test perspective and other variable offset functions
|
|
class PolygonOffsetGM : public GM {
|
|
public:
|
|
PolygonOffsetGM(bool convexOnly, bool variableOffset)
|
|
: fConvexOnly(convexOnly)
|
|
, fVariableOffset(variableOffset) {
|
|
this->setBGColor(0xFFFFFFFF);
|
|
}
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
if (fConvexOnly) {
|
|
if (fVariableOffset) {
|
|
return SkString("convex-polygon-inset-v");
|
|
} else {
|
|
return SkString("convex-polygon-inset");
|
|
}
|
|
} else {
|
|
if (fVariableOffset) {
|
|
return SkString("simple-polygon-offset-v");
|
|
} else {
|
|
return SkString("simple-polygon-offset");
|
|
}
|
|
}
|
|
}
|
|
SkISize onISize() override { return SkISize::Make(kGMWidth, kGMHeight); }
|
|
bool runAsBench() const override { return true; }
|
|
|
|
static void GetConvexPolygon(int index, SkPath::Direction dir,
|
|
std::unique_ptr<SkPoint[]>* data, int* numPts) {
|
|
if (index < (int)SK_ARRAY_COUNT(PolygonOffsetData::gConvexPoints)) {
|
|
// manually specified
|
|
*numPts = (int)PolygonOffsetData::gConvexSizes[index];
|
|
data->reset(new SkPoint[*numPts]);
|
|
if (SkPath::kCW_Direction == dir) {
|
|
for (int i = 0; i < *numPts; ++i) {
|
|
(*data)[i] = PolygonOffsetData::gConvexPoints[index][i];
|
|
}
|
|
} else {
|
|
for (int i = 0; i < *numPts; ++i) {
|
|
(*data)[i] = PolygonOffsetData::gConvexPoints[index][*numPts - i - 1];
|
|
}
|
|
}
|
|
} else {
|
|
// procedurally generated
|
|
SkScalar width = kMaxPathHeight / 2;
|
|
SkScalar height = kMaxPathHeight / 2;
|
|
int numPtsArray[] = { 3, 4, 5, 5, 6, 8, 8, 20, 100 };
|
|
|
|
size_t arrayIndex = index - SK_ARRAY_COUNT(PolygonOffsetData::gConvexPoints);
|
|
SkASSERT(arrayIndex < SK_ARRAY_COUNT(numPtsArray));
|
|
*numPts = numPtsArray[arrayIndex];
|
|
if (arrayIndex == 3 || arrayIndex == 6) {
|
|
// squashed pentagon and octagon
|
|
width = kMaxPathHeight / 5;
|
|
}
|
|
|
|
data->reset(new SkPoint[*numPts]);
|
|
|
|
create_ngon(*numPts, data->get(), width, height, dir);
|
|
}
|
|
}
|
|
|
|
static void GetSimplePolygon(int index, SkPath::Direction dir,
|
|
std::unique_ptr<SkPoint[]>* data, int* numPts) {
|
|
if (index < (int)SK_ARRAY_COUNT(PolygonOffsetData::gSimplePoints)) {
|
|
// manually specified
|
|
*numPts = (int)PolygonOffsetData::gSimpleSizes[index];
|
|
data->reset(new SkPoint[*numPts]);
|
|
if (SkPath::kCW_Direction == dir) {
|
|
for (int i = 0; i < *numPts; ++i) {
|
|
(*data)[i] = PolygonOffsetData::gSimplePoints[index][i];
|
|
}
|
|
} else {
|
|
for (int i = 0; i < *numPts; ++i) {
|
|
(*data)[i] = PolygonOffsetData::gSimplePoints[index][*numPts - i - 1];
|
|
}
|
|
}
|
|
} else {
|
|
// procedurally generated
|
|
SkScalar width = kMaxPathHeight / 2;
|
|
SkScalar height = kMaxPathHeight / 2;
|
|
int numPtsArray[] = { 5, 7, 8, 20, 100 };
|
|
|
|
size_t arrayIndex = index - SK_ARRAY_COUNT(PolygonOffsetData::gSimplePoints);
|
|
arrayIndex = SkTMin(arrayIndex, SK_ARRAY_COUNT(numPtsArray) - 1);
|
|
SkASSERT(arrayIndex < SK_ARRAY_COUNT(numPtsArray));
|
|
*numPts = numPtsArray[arrayIndex];
|
|
// squash horizontally
|
|
width = kMaxPathHeight / 5;
|
|
|
|
data->reset(new SkPoint[*numPts]);
|
|
|
|
create_ngon(*numPts, data->get(), width, height, dir);
|
|
}
|
|
}
|
|
// Draw a single polygon with insets and potentially outsets
|
|
void drawPolygon(SkCanvas* canvas, int index, SkPoint* offset) {
|
|
|
|
SkPoint center;
|
|
SkRect bounds;
|
|
{
|
|
std::unique_ptr<SkPoint[]> data(nullptr);
|
|
int numPts;
|
|
if (fConvexOnly) {
|
|
GetConvexPolygon(index, SkPath::kCW_Direction, &data, &numPts);
|
|
} else {
|
|
GetSimplePolygon(index, SkPath::kCW_Direction, &data, &numPts);
|
|
}
|
|
bounds.set(data.get(), numPts);
|
|
if (!fConvexOnly) {
|
|
bounds.outset(kMaxOutset, kMaxOutset);
|
|
}
|
|
if (offset->fX + bounds.width() > kGMWidth) {
|
|
offset->fX = 0;
|
|
offset->fY += kMaxPathHeight;
|
|
}
|
|
center = { offset->fX + SkScalarHalf(bounds.width()), offset->fY };
|
|
offset->fX += bounds.width();
|
|
}
|
|
|
|
const SkPath::Direction dirs[2] = { SkPath::kCW_Direction, SkPath::kCCW_Direction };
|
|
const float insets[] = { 5, 10, 15, 20, 25, 30, 35, 40 };
|
|
const float offsets[] = { 2, 5, 9, 14, 20, 27, 35, 44, -2, -5, -9 };
|
|
const SkColor colors[] = { 0xFF901313, 0xFF8D6214, 0xFF698B14, 0xFF1C8914,
|
|
0xFF148755, 0xFF146C84, 0xFF142482, 0xFF4A1480,
|
|
0xFF901313, 0xFF8D6214, 0xFF698B14 };
|
|
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(1);
|
|
|
|
std::unique_ptr<SkPoint[]> data(nullptr);
|
|
int numPts;
|
|
if (fConvexOnly) {
|
|
GetConvexPolygon(index, dirs[index % 2], &data, &numPts);
|
|
} else {
|
|
GetSimplePolygon(index, dirs[index % 2], &data, &numPts);
|
|
}
|
|
|
|
{
|
|
SkPath path;
|
|
path.moveTo(data.get()[0]);
|
|
for (int i = 1; i < numPts; ++i) {
|
|
path.lineTo(data.get()[i]);
|
|
}
|
|
path.close();
|
|
canvas->save();
|
|
canvas->translate(center.fX, center.fY);
|
|
canvas->drawPath(path, paint);
|
|
canvas->restore();
|
|
}
|
|
|
|
SkTDArray<SkPoint> offsetPoly;
|
|
size_t count = fConvexOnly ? SK_ARRAY_COUNT(insets) : SK_ARRAY_COUNT(offsets);
|
|
SkScalar localCenterX = bounds.centerX();
|
|
for (size_t i = 0; i < count; ++i) {
|
|
SkScalar offset = fConvexOnly ? insets[i] : offsets[i];
|
|
std::function<SkScalar(const SkPoint&)> offsetFunc;
|
|
if (fVariableOffset) {
|
|
offsetFunc = [offset, localCenterX](const SkPoint& p) {
|
|
return offset + 0.04f*(p.fX - localCenterX);
|
|
};
|
|
} else {
|
|
offsetFunc = [offset](const SkPoint& p) {
|
|
return offset;
|
|
};
|
|
}
|
|
|
|
bool result;
|
|
if (fConvexOnly) {
|
|
result = SkInsetConvexPolygon(data.get(), numPts, offsetFunc, &offsetPoly);
|
|
} else {
|
|
result = SkOffsetSimplePolygon(data.get(), numPts, offsetFunc, &offsetPoly);
|
|
}
|
|
if (result) {
|
|
SkPath path;
|
|
path.moveTo(offsetPoly[0]);
|
|
for (int i = 1; i < offsetPoly.count(); ++i) {
|
|
path.lineTo(offsetPoly[i]);
|
|
}
|
|
path.close();
|
|
|
|
paint.setColor(sk_tool_utils::color_to_565(colors[i]));
|
|
canvas->save();
|
|
canvas->translate(center.fX, center.fY);
|
|
canvas->drawPath(path, paint);
|
|
canvas->restore();
|
|
}
|
|
}
|
|
}
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
// the right edge of the last drawn path
|
|
SkPoint offset = { 0, SkScalarHalf(kMaxPathHeight) };
|
|
if (!fConvexOnly) {
|
|
offset.fY += kMaxOutset;
|
|
}
|
|
|
|
for (int i = 0; i < kNumPaths; ++i) {
|
|
this->drawPolygon(canvas, i, &offset);
|
|
}
|
|
}
|
|
|
|
private:
|
|
static constexpr int kNumPaths = 20;
|
|
static constexpr int kMaxPathHeight = 100;
|
|
static constexpr int kMaxOutset = 16;
|
|
static constexpr int kGMWidth = 512;
|
|
static constexpr int kGMHeight = 512;
|
|
|
|
bool fConvexOnly;
|
|
bool fVariableOffset;
|
|
|
|
typedef GM INHERITED;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
DEF_GM(return new PolygonOffsetGM(true, false);)
|
|
DEF_GM(return new PolygonOffsetGM(true, true);)
|
|
DEF_GM(return new PolygonOffsetGM(false, false);)
|
|
DEF_GM(return new PolygonOffsetGM(false, true);)
|
|
}
|