1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkEdge_DEFINED 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkEdge_DEFINED 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRect.h" 14b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com#include "SkFDot6.h" 15b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com#include "SkMath.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17e4646db4dc747b568e2b61cab300606d57cf645areed@google.com// This correctly favors the lower-pixel when y0 is on a 1/2 pixel boundary 18e4646db4dc747b568e2b61cab300606d57cf645areed@google.com#define SkEdge_Compute_DY(top, y0) ((top << 6) + 32 - (y0)) 1909a029b687465190c828bde896173e23aa350c4creed@google.com 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkEdge { 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum Type { 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kLine_Type, 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kQuad_Type, 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kCubic_Type 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge* fNext; 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge* fPrev; 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fX; 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fDX; 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t fFirstY; 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t fLastY; 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int8_t fCurveCount; // only used by kQuad(+) and kCubic(-) 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t fCurveShift; // appled to all Dx/DDx/DDDx except for fCubicDShift exception 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t fCubicDShift; // applied to fCDx and fCDy only in cubic 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int8_t fWinding; // 1 or -1 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 39e053ca4380713a5b9e6a31119a1bdd6d529208aareed int setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip, int shiftUp); 40b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com // call this version if you know you don't have a clip 41b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com inline int setLine(const SkPoint& p0, const SkPoint& p1, int shiftUp); 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inline int updateLine(SkFixed ax, SkFixed ay, SkFixed bx, SkFixed by); 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void chopLineWithClip(const SkIRect& clip); 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inline bool intersectsClip(const SkIRect& clip) const { 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fFirstY < clip.fBottom); 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fLastY >= clip.fTop; 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void dump() const { 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("edge: firstY:%d lastY:%d x:%g dx:%g w:%d\n", fFirstY, fLastY, SkFixedToFloat(fX), SkFixedToFloat(fDX), fWinding); 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void validate() const { 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fPrev && fNext); 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fPrev->fNext == this); 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fNext->fPrev == this); 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fFirstY <= fLastY); 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkAbs32(fWinding) == 1); 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkQuadraticEdge : public SkEdge { 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fQx, fQy; 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fQDx, fQDy; 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fQDDx, fQDDy; 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fQLastX, fQLastY; 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 72c07d23a6e220c0aff36e3e4e06c1b685a440108ereed@android.com int setQuadratic(const SkPoint pts[3], int shiftUp); 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int updateQuadratic(); 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkCubicEdge : public SkEdge { 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fCx, fCy; 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fCDx, fCDy; 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fCDDx, fCDDy; 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fCDDDx, fCDDDy; 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fCLastX, fCLastY; 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 83e053ca4380713a5b9e6a31119a1bdd6d529208aareed int setCubic(const SkPoint pts[4], int shiftUp); 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int updateCubic(); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 87b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.comint SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) { 88b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com SkFDot6 x0, y0, x1, y1; 89fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 90b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com { 912f26528e59908856e36e88aa3be94d84014e9a58george#ifdef SK_RASTERIZE_EVEN_ROUNDING 922f26528e59908856e36e88aa3be94d84014e9a58george x0 = SkScalarRoundToFDot6(p0.fX, shift); 932f26528e59908856e36e88aa3be94d84014e9a58george y0 = SkScalarRoundToFDot6(p0.fY, shift); 942f26528e59908856e36e88aa3be94d84014e9a58george x1 = SkScalarRoundToFDot6(p1.fX, shift); 952f26528e59908856e36e88aa3be94d84014e9a58george y1 = SkScalarRoundToFDot6(p1.fY, shift); 962f26528e59908856e36e88aa3be94d84014e9a58george#else 97b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com float scale = float(1 << (shift + 6)); 98b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com x0 = int(p0.fX * scale); 99b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com y0 = int(p0.fY * scale); 100b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com x1 = int(p1.fX * scale); 101b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com y1 = int(p1.fY * scale); 1022f26528e59908856e36e88aa3be94d84014e9a58george#endif 103b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com } 104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 105b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com int winding = 1; 106fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 107b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com if (y0 > y1) { 108b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com SkTSwap(x0, x1); 109b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com SkTSwap(y0, y1); 110b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com winding = -1; 111b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com } 112fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 113b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com int top = SkFDot6Round(y0); 114b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com int bot = SkFDot6Round(y1); 115fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 116b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com // are we a zero-height line? 117b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com if (top == bot) { 118b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com return 0; 119b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com } 120fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 121b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com SkFixed slope = SkFDot6Div(x1 - x0, y1 - y0); 1221c762161d88f0ace8cee1eea43d1b7350c06242eqiankun.miao const SkFDot6 dy = SkEdge_Compute_DY(top, y0); 123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 12409a029b687465190c828bde896173e23aa350c4creed@google.com fX = SkFDot6ToFixed(x0 + SkFixedMul(slope, dy)); // + SK_Fixed1/2 125b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com fDX = slope; 126b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com fFirstY = top; 127b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com fLastY = bot - 1; 128b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com fCurveCount = 0; 129b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com fWinding = SkToS8(winding); 130b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com fCurveShift = 0; 131b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com return 1; 132b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com} 133b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com 134b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 136