Index: skia/sgl/SkStrokerPriv.cpp |
=================================================================== |
--- skia/sgl/SkStrokerPriv.cpp (revision 16859) |
+++ skia/sgl/SkStrokerPriv.cpp (working copy) |
@@ -1,275 +0,0 @@ |
-/* libs/graphics/sgl/SkStrokerPriv.cpp |
-** |
-** Copyright 2006, The Android Open Source Project |
-** |
-** 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 "SkStrokerPriv.h" |
-#include "SkGeometry.h" |
-#include "SkPath.h" |
- |
-static void ButtCapper(SkPath* path, const SkPoint& pivot, |
- const SkVector& normal, const SkPoint& stop, |
- SkPath*) |
-{ |
- path->lineTo(stop.fX, stop.fY); |
-} |
- |
-static void RoundCapper(SkPath* path, const SkPoint& pivot, |
- const SkVector& normal, const SkPoint& stop, |
- SkPath*) |
-{ |
- SkScalar px = pivot.fX; |
- SkScalar py = pivot.fY; |
- SkScalar nx = normal.fX; |
- SkScalar ny = normal.fY; |
- SkScalar sx = SkScalarMul(nx, CUBIC_ARC_FACTOR); |
- SkScalar sy = SkScalarMul(ny, CUBIC_ARC_FACTOR); |
- |
- path->cubicTo(px + nx + CWX(sx, sy), py + ny + CWY(sx, sy), |
- px + CWX(nx, ny) + sx, py + CWY(nx, ny) + sy, |
- px + CWX(nx, ny), py + CWY(nx, ny)); |
- path->cubicTo(px + CWX(nx, ny) - sx, py + CWY(nx, ny) - sy, |
- px - nx + CWX(sx, sy), py - ny + CWY(sx, sy), |
- stop.fX, stop.fY); |
-} |
- |
-static void SquareCapper(SkPath* path, const SkPoint& pivot, |
- const SkVector& normal, const SkPoint& stop, |
- SkPath* otherPath) |
-{ |
- SkVector parallel; |
- normal.rotateCW(¶llel); |
- |
- if (otherPath) |
- { |
- path->setLastPt(pivot.fX + normal.fX + parallel.fX, pivot.fY + normal.fY + parallel.fY); |
- path->lineTo(pivot.fX - normal.fX + parallel.fX, pivot.fY - normal.fY + parallel.fY); |
- } |
- else |
- { |
- path->lineTo(pivot.fX + normal.fX + parallel.fX, pivot.fY + normal.fY + parallel.fY); |
- path->lineTo(pivot.fX - normal.fX + parallel.fX, pivot.fY - normal.fY + parallel.fY); |
- path->lineTo(stop.fX, stop.fY); |
- } |
-} |
- |
-///////////////////////////////////////////////////////////////////////////// |
- |
-static bool is_clockwise(const SkVector& before, const SkVector& after) |
-{ |
- return SkScalarMul(before.fX, after.fY) - SkScalarMul(before.fY, after.fX) > 0; |
-} |
- |
-enum AngleType { |
- kNearly180_AngleType, |
- kSharp_AngleType, |
- kShallow_AngleType, |
- kNearlyLine_AngleType |
-}; |
- |
-static AngleType Dot2AngleType(SkScalar dot) |
-{ |
-// need more precise fixed normalization |
-// SkASSERT(SkScalarAbs(dot) <= SK_Scalar1 + SK_ScalarNearlyZero); |
- |
- if (dot >= 0) // shallow or line |
- return SkScalarNearlyZero(SK_Scalar1 - dot) ? kNearlyLine_AngleType : kShallow_AngleType; |
- else // sharp or 180 |
- return SkScalarNearlyZero(SK_Scalar1 + dot) ? kNearly180_AngleType : kSharp_AngleType; |
-} |
- |
-static void HandleInnerJoin(SkPath* inner, const SkPoint& pivot, const SkVector& after) |
-{ |
-#if 1 |
- /* In the degenerate case that the stroke radius is larger than our segments |
- just connecting the two inner segments may "show through" as a funny |
- diagonal. To pseudo-fix this, we go through the pivot point. This adds |
- an extra point/edge, but I can't see a cheap way to know when this is |
- not needed :( |
- */ |
- inner->lineTo(pivot.fX, pivot.fY); |
-#endif |
- |
- inner->lineTo(pivot.fX - after.fX, pivot.fY - after.fY); |
-} |
- |
-static void BluntJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal, |
- const SkPoint& pivot, const SkVector& afterUnitNormal, |
- SkScalar radius, SkScalar invMiterLimit, bool, bool) |
-{ |
- SkVector after; |
- afterUnitNormal.scale(radius, &after); |
- |
- if (!is_clockwise(beforeUnitNormal, afterUnitNormal)) |
- { |
- SkTSwap<SkPath*>(outer, inner); |
- after.negate(); |
- } |
- |
- outer->lineTo(pivot.fX + after.fX, pivot.fY + after.fY); |
- HandleInnerJoin(inner, pivot, after); |
-} |
- |
-static void RoundJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal, |
- const SkPoint& pivot, const SkVector& afterUnitNormal, |
- SkScalar radius, SkScalar invMiterLimit, bool, bool) |
-{ |
- SkScalar dotProd = SkPoint::DotProduct(beforeUnitNormal, afterUnitNormal); |
- AngleType angleType = Dot2AngleType(dotProd); |
- |
- if (angleType == kNearlyLine_AngleType) |
- return; |
- |
- SkVector before = beforeUnitNormal; |
- SkVector after = afterUnitNormal; |
- SkRotationDirection dir = kCW_SkRotationDirection; |
- |
- if (!is_clockwise(before, after)) |
- { |
- SkTSwap<SkPath*>(outer, inner); |
- before.negate(); |
- after.negate(); |
- dir = kCCW_SkRotationDirection; |
- } |
- |
- SkPoint pts[kSkBuildQuadArcStorage]; |
- SkMatrix matrix; |
- matrix.setScale(radius, radius); |
- matrix.postTranslate(pivot.fX, pivot.fY); |
- int count = SkBuildQuadArc(before, after, dir, &matrix, pts); |
- SkASSERT((count & 1) == 1); |
- |
- if (count > 1) |
- { |
- for (int i = 1; i < count; i += 2) |
- outer->quadTo(pts[i].fX, pts[i].fY, pts[i+1].fX, pts[i+1].fY); |
- |
- after.scale(radius); |
- HandleInnerJoin(inner, pivot, after); |
- } |
-} |
- |
-#ifdef SK_SCALAR_IS_FLOAT |
- #define kOneOverSqrt2 (0.707106781f) |
-#else |
- #define kOneOverSqrt2 (46341) |
-#endif |
- |
-static void MiterJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal, |
- const SkPoint& pivot, const SkVector& afterUnitNormal, |
- SkScalar radius, SkScalar invMiterLimit, |
- bool prevIsLine, bool currIsLine) |
-{ |
- // negate the dot since we're using normals instead of tangents |
- SkScalar dotProd = SkPoint::DotProduct(beforeUnitNormal, afterUnitNormal); |
- AngleType angleType = Dot2AngleType(dotProd); |
- SkVector before = beforeUnitNormal; |
- SkVector after = afterUnitNormal; |
- SkVector mid; |
- SkScalar sinHalfAngle; |
- bool ccw; |
- |
- if (angleType == kNearlyLine_AngleType) |
- return; |
- if (angleType == kNearly180_AngleType) |
- { |
- currIsLine = false; |
- goto DO_BLUNT; |
- } |
- |
- ccw = !is_clockwise(before, after); |
- if (ccw) |
- { |
- SkTSwap<SkPath*>(outer, inner); |
- before.negate(); |
- after.negate(); |
- } |
- |
- /* Before we enter the world of square-roots and divides, |
- check if we're trying to join an upright right angle |
- (common case for stroking rectangles). If so, special case |
- that (for speed an accuracy). |
- Note: we only need to check one normal if dot==0 |
- */ |
- if (0 == dotProd && invMiterLimit <= kOneOverSqrt2) |
- { |
- mid.set(SkScalarMul(before.fX + after.fX, radius), |
- SkScalarMul(before.fY + after.fY, radius)); |
- goto DO_MITER; |
- } |
- |
- /* midLength = radius / sinHalfAngle |
- if (midLength > miterLimit * radius) abort |
- if (radius / sinHalf > miterLimit * radius) abort |
- if (1 / sinHalf > miterLimit) abort |
- if (1 / miterLimit > sinHalf) abort |
- My dotProd is opposite sign, since it is built from normals and not tangents |
- hence 1 + dot instead of 1 - dot in the formula |
- */ |
- sinHalfAngle = SkScalarSqrt(SkScalarHalf(SK_Scalar1 + dotProd)); |
- if (sinHalfAngle < invMiterLimit) |
- { |
- currIsLine = false; |
- goto DO_BLUNT; |
- } |
- |
- // choose the most accurate way to form the initial mid-vector |
- if (angleType == kSharp_AngleType) |
- { |
- mid.set(after.fY - before.fY, before.fX - after.fX); |
- if (ccw) |
- mid.negate(); |
- } |
- else |
- mid.set(before.fX + after.fX, before.fY + after.fY); |
- |
- mid.setLength(SkScalarDiv(radius, sinHalfAngle)); |
-DO_MITER: |
- if (prevIsLine) |
- outer->setLastPt(pivot.fX + mid.fX, pivot.fY + mid.fY); |
- else |
- outer->lineTo(pivot.fX + mid.fX, pivot.fY + mid.fY); |
- |
-DO_BLUNT: |
- after.scale(radius); |
- if (!currIsLine) |
- outer->lineTo(pivot.fX + after.fX, pivot.fY + after.fY); |
- HandleInnerJoin(inner, pivot, after); |
-} |
- |
-///////////////////////////////////////////////////////////////////////////// |
- |
-SkStrokerPriv::CapProc SkStrokerPriv::CapFactory(SkPaint::Cap cap) |
-{ |
- static const SkStrokerPriv::CapProc gCappers[] = { |
- ButtCapper, RoundCapper, SquareCapper |
- }; |
- |
- SkASSERT((unsigned)cap < SkPaint::kCapCount); |
- return gCappers[cap]; |
-} |
- |
-SkStrokerPriv::JoinProc SkStrokerPriv::JoinFactory(SkPaint::Join join) |
-{ |
- static const SkStrokerPriv::JoinProc gJoiners[] = { |
- MiterJoiner, RoundJoiner, BluntJoiner |
- }; |
- |
- SkASSERT((unsigned)join < SkPaint::kJoinCount); |
- return gJoiners[join]; |
-} |
- |
- |
- |