9d18b7873c
fill modes except hairline are supported. Note that the path renderer is not enabled by default; to enable it, replace "GrCreatePathRenderer_none.cpp" with "GrCreatePathRenderer_tesselated.cpp" in skia.gyp, and run gyp_skia, and build. This change also contains a number of build fixes for Win32 (for building SampleApp on VS2008) and Mac (for my ancient Mac Pro which supports GL_EXT_framebuffer_object but not GL_ARB_framebuffer_object). Also, priorityq-heap.c was removed from the SampleApp build, since it's #included by priorityq.c (weird, I know). NB: When this change is rolled into chrome, some modifications to chromium's skia.gyp will be necessary. Review URL: http://codereview.appspot.com/4289072/ git-svn-id: http://skia.googlecode.com/svn/trunk@1012 2bbb7eff-a529-9590-31e7-b0007b416f81
145 lines
5.1 KiB
C++
145 lines
5.1 KiB
C++
/*
|
|
Copyright 2011 Google Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
#include "GrPathUtils.h"
|
|
|
|
#include "GrPathIter.h"
|
|
#include "GrPoint.h"
|
|
|
|
const GrScalar GrPathUtils::gTolerance = GR_Scalar1;
|
|
|
|
static const uint32_t MAX_POINTS_PER_CURVE = 1 << 10;
|
|
|
|
uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[],
|
|
GrScalar tol) {
|
|
GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);
|
|
if (d < tol) {
|
|
return 1;
|
|
} else {
|
|
// Each time we subdivide, d should be cut in 4. So we need to
|
|
// subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)
|
|
// points.
|
|
// 2^(log4(x)) = sqrt(x);
|
|
d = ceilf(sqrtf(d/tol));
|
|
return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);
|
|
}
|
|
}
|
|
|
|
uint32_t GrPathUtils::generateQuadraticPoints(const GrPoint& p0,
|
|
const GrPoint& p1,
|
|
const GrPoint& p2,
|
|
GrScalar tolSqd,
|
|
GrPoint** points,
|
|
uint32_t pointsLeft) {
|
|
if (pointsLeft < 2 ||
|
|
(p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {
|
|
(*points)[0] = p2;
|
|
*points += 1;
|
|
return 1;
|
|
}
|
|
|
|
GrPoint q[] = {
|
|
GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
|
|
GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
|
|
};
|
|
GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY));
|
|
|
|
pointsLeft >>= 1;
|
|
uint32_t a = generateQuadraticPoints(p0, q[0], r, tolSqd, points, pointsLeft);
|
|
uint32_t b = generateQuadraticPoints(r, q[1], p2, tolSqd, points, pointsLeft);
|
|
return a + b;
|
|
}
|
|
|
|
uint32_t GrPathUtils::cubicPointCount(const GrPoint points[],
|
|
GrScalar tol) {
|
|
GrScalar d = GrMax(points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),
|
|
points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));
|
|
d = sqrtf(d);
|
|
if (d < tol) {
|
|
return 1;
|
|
} else {
|
|
d = ceilf(sqrtf(d/tol));
|
|
return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);
|
|
}
|
|
}
|
|
|
|
uint32_t GrPathUtils::generateCubicPoints(const GrPoint& p0,
|
|
const GrPoint& p1,
|
|
const GrPoint& p2,
|
|
const GrPoint& p3,
|
|
GrScalar tolSqd,
|
|
GrPoint** points,
|
|
uint32_t pointsLeft) {
|
|
if (pointsLeft < 2 ||
|
|
(p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&
|
|
p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) {
|
|
(*points)[0] = p3;
|
|
*points += 1;
|
|
return 1;
|
|
}
|
|
GrPoint q[] = {
|
|
GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
|
|
GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
|
|
GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY))
|
|
};
|
|
GrPoint r[] = {
|
|
GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)),
|
|
GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY))
|
|
};
|
|
GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY));
|
|
pointsLeft >>= 1;
|
|
uint32_t a = generateCubicPoints(p0, q[0], r[0], s, tolSqd, points, pointsLeft);
|
|
uint32_t b = generateCubicPoints(s, r[1], q[2], p3, tolSqd, points, pointsLeft);
|
|
return a + b;
|
|
}
|
|
|
|
int GrPathUtils::worstCasePointCount(GrPathIter* path,
|
|
int* subpaths,
|
|
GrScalar tol) {
|
|
int pointCount = 0;
|
|
*subpaths = 1;
|
|
|
|
bool first = true;
|
|
|
|
GrPathCmd cmd;
|
|
|
|
GrPoint pts[4];
|
|
while ((cmd = path->next(pts)) != kEnd_PathCmd) {
|
|
|
|
switch (cmd) {
|
|
case kLine_PathCmd:
|
|
pointCount += 1;
|
|
break;
|
|
case kQuadratic_PathCmd:
|
|
pointCount += quadraticPointCount(pts, tol);
|
|
break;
|
|
case kCubic_PathCmd:
|
|
pointCount += cubicPointCount(pts, tol);
|
|
break;
|
|
case kMove_PathCmd:
|
|
pointCount += 1;
|
|
if (!first) {
|
|
++(*subpaths);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
first = false;
|
|
}
|
|
return pointCount;
|
|
}
|