aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkAnalyticEdge.h
diff options
context:
space:
mode:
authorGravatar liyuqian <liyuqian@google.com>2016-10-04 11:23:22 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-10-04 11:23:22 -0700
commit38911a7cb53474575e1cd1cb545902b50ee00889 (patch)
treee8186ee1c91bb4f9206457debdb0103c1a38218f /src/core/SkAnalyticEdge.h
parent421a3c1cc1b227084c7c84618d0b6a6804faabef (diff)
Resubmit issue 2221103002 to fix the iOS build by declaring the flag in
SkCommonFlags.h TBR=reed@google.com,caryclark@google.com BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2393643002 Review-Url: https://codereview.chromium.org/2393643002
Diffstat (limited to 'src/core/SkAnalyticEdge.h')
-rw-r--r--src/core/SkAnalyticEdge.h154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/core/SkAnalyticEdge.h b/src/core/SkAnalyticEdge.h
new file mode 100644
index 0000000000..f4b23ba2b6
--- /dev/null
+++ b/src/core/SkAnalyticEdge.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAnalyticEdge_DEFINED
+#define SkAnalyticEdge_DEFINED
+
+#include "SkEdge.h"
+
+inline SkFixed SkFixedMul_lowprec(SkFixed a, SkFixed b) {
+ SkASSERT(((int64_t)a >> 8) * (b >> 8) <= SK_MaxS32);
+ return (a >> 8) * (b >> 8);
+}
+
+struct SkAnalyticEdge {
+ // Similar to SkEdge, the conic edges will be converted to quadratic edges
+ enum Type {
+ kLine_Type,
+ kQuad_Type,
+ kCubic_Type
+ };
+
+ SkAnalyticEdge* fNext;
+ SkAnalyticEdge* fPrev;
+
+ SkFixed fX;
+ SkFixed fDX;
+ SkFixed fUpperX; // The x value when y = fUpperY
+ SkFixed fY; // The current y
+ SkFixed fUpperY; // The upper bound of y (our edge is from y = fUpperY to y = fLowerY)
+ SkFixed fLowerY; // The lower bound of y (our edge is from y = fUpperY to y = fLowerY)
+ SkFixed fDY; // abs(1/fDX); may be SK_MaxS32 when fDX is close to 0.
+ // fDY is only used for blitting trapezoids.
+
+ int8_t fCurveCount; // only used by kQuad(+) and kCubic(-)
+ uint8_t fCurveShift; // appled to all Dx/DDx/DDDx except for fCubicDShift exception
+ uint8_t fCubicDShift; // applied to fCDx and fCDy only in cubic
+ int8_t fWinding; // 1 or -1
+
+ static const int kDefaultAccuracy = 2; // default accuracy for snapping
+
+ static inline SkFixed snapY(SkFixed y, int accuracy = kDefaultAccuracy) {
+ return SkFixedRoundToFixed(y << accuracy) >> accuracy;
+ }
+
+ // Update fX, fY of this edge so fY = y
+ inline void goY(SkFixed y) {
+ if (y == fY + SK_Fixed1) {
+ fX = fX + fDX;
+ fY = y;
+ } else if (y != fY) {
+ // Drop lower digits as our alpha only has 8 bits
+ // (fDX and y - fUpperY may be greater than SK_Fixed1)
+ fX = fUpperX + SkFixedMul_lowprec(fDX, y - fUpperY);
+ fY = y;
+ }
+ }
+
+ inline bool setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip = nullptr);
+ inline bool updateLine(SkFixed ax, SkFixed ay, SkFixed bx, SkFixed by, SkFixed slope);
+ void chopLineWithClip(const SkIRect& clip);
+
+ inline bool intersectsClip(const SkIRect& clip) const {
+ SkASSERT(SkFixedFloorToInt(fUpperY) < clip.fBottom);
+ return SkFixedCeilToInt(fLowerY) > clip.fTop;
+ }
+
+#ifdef SK_DEBUG
+ void dump() const {
+ SkDebugf("edge: upperY:%d lowerY:%d y:%g x:%g dx:%g w:%d\n",
+ fUpperY, fLowerY, SkFixedToFloat(fY), SkFixedToFloat(fX),
+ SkFixedToFloat(fDX), fWinding);
+ }
+
+ void validate() const {
+ SkASSERT(fPrev && fNext);
+ SkASSERT(fPrev->fNext == this);
+ SkASSERT(fNext->fPrev == this);
+
+ SkASSERT(fUpperY < fLowerY);
+ SkASSERT(SkAbs32(fWinding) == 1);
+ }
+#endif
+};
+
+struct SkAnalyticQuadraticEdge : public SkAnalyticEdge {
+ SkQuadraticEdge fQEdge;
+
+ // snap y to integer points in the middle of the curve to accelerate AAA path filling
+ SkFixed fSnappedX, fSnappedY;
+
+ bool setQuadratic(const SkPoint pts[3]);
+ bool updateQuadratic();
+};
+
+struct SkAnalyticCubicEdge : public SkAnalyticEdge {
+ SkCubicEdge fCEdge;
+
+ bool setCubic(const SkPoint pts[4]);
+ bool updateCubic();
+};
+
+bool SkAnalyticEdge::setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip) {
+ // We must set X/Y using the same way (times 4, to FDot6, then to Fixed) as Quads/Cubics.
+ // Otherwise the order of the edge might be wrong due to precision limit.
+ SkFixed x0 = SkFDot6ToFixed(SkScalarToFDot6(p0.fX * 4)) >> 2;
+ SkFixed y0 = snapY(SkFDot6ToFixed(SkScalarToFDot6(p0.fY * 4)) >> 2);
+ SkFixed x1 = SkFDot6ToFixed(SkScalarToFDot6(p1.fX * 4)) >> 2;
+ SkFixed y1 = snapY(SkFDot6ToFixed(SkScalarToFDot6(p1.fY * 4)) >> 2);
+
+ // are we a zero-height line?
+ if (y0 == y1) {
+ return false;
+ }
+
+ int top = SkFixedFloorToInt(y0);
+ int bot = SkFixedCeilToInt(y1);
+
+ // are we completely above or below the clip?
+ if (clip && (top >= clip->fBottom || bot <= clip->fTop)) {
+ return false;
+ }
+
+ int winding = 1;
+
+ if (y0 > y1) {
+ SkTSwap(x0, x1);
+ SkTSwap(y0, y1);
+ winding = -1;
+ }
+
+ SkFixed slope = SkFixedDiv(x1 - x0, y1 - y0);
+
+ fX = x0;
+ fDX = slope;
+ fUpperX = x0;
+ fY = y0;
+ fUpperY = y0;
+ fLowerY = y1;
+ fDY = x1 != x0 ? SkAbs32(SkFixedDiv(y1 - y0, x1 - x0)) : SK_MaxS32;
+ fCurveCount = 0;
+ fWinding = SkToS8(winding);
+ fCurveShift = 0;
+
+ if (clip) {
+ this->chopLineWithClip(*clip);
+ }
+ return true;
+}
+
+#endif