Flutter Engine
The Flutter Engine
Classes | Functions
SkScan_AAAPath.cpp File Reference
#include "include/core/SkColor.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkRect.h"
#include "include/private/base/SkAlign.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkFixed.h"
#include "include/private/base/SkMath.h"
#include "include/private/base/SkSafe32.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkTSort.h"
#include "src/core/SkAlphaRuns.h"
#include "src/core/SkAnalyticEdge.h"
#include "src/core/SkBlitter.h"
#include "src/core/SkEdge.h"
#include "src/core/SkEdgeBuilder.h"
#include "src/core/SkMask.h"
#include "src/core/SkScan.h"
#include "src/core/SkScanPriv.h"
#include <algorithm>
#include <cstdint>
#include <cstring>

Go to the source code of this file.

Classes

class  AdditiveBlitter
 
class  MaskAdditiveBlitter
 
class  RunBasedAdditiveBlitter
 
class  SafeRLEAdditiveBlitter
 

Functions

static void add_alpha (SkAlpha *alpha, SkAlpha delta)
 
static void safely_add_alpha (SkAlpha *alpha, SkAlpha delta)
 
static SkAlpha trapezoid_to_alpha (SkFixed l1, SkFixed l2)
 
static SkAlpha partial_triangle_to_alpha (SkFixed a, SkFixed b)
 
static SkAlpha get_partial_alpha (SkAlpha alpha, SkFixed partialHeight)
 
static SkAlpha get_partial_alpha (SkAlpha alpha, SkAlpha fullAlpha)
 
static SkAlpha fixed_to_alpha (SkFixed f)
 
static SkFixed approximate_intersection (SkFixed l1, SkFixed r1, SkFixed l2, SkFixed r2)
 
static void compute_alpha_above_line (SkAlpha *alphas, SkFixed l, SkFixed r, SkFixed dY, SkAlpha fullAlpha)
 
static void compute_alpha_below_line (SkAlpha *alphas, SkFixed l, SkFixed r, SkFixed dY, SkAlpha fullAlpha)
 
static void blit_single_alpha (AdditiveBlitter *blitter, int y, int x, SkAlpha alpha, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)
 
static void blit_two_alphas (AdditiveBlitter *blitter, int y, int x, SkAlpha a1, SkAlpha a2, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)
 
static void blit_full_alpha (AdditiveBlitter *blitter, int y, int x, int len, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)
 
static void blit_aaa_trapezoid_row (AdditiveBlitter *blitter, int y, SkFixed ul, SkFixed ur, SkFixed ll, SkFixed lr, SkFixed lDY, SkFixed rDY, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)
 
static void blit_trapezoid_row (AdditiveBlitter *blitter, int y, SkFixed ul, SkFixed ur, SkFixed ll, SkFixed lr, SkFixed lDY, SkFixed rDY, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)
 
static bool operator< (const SkAnalyticEdge &a, const SkAnalyticEdge &b)
 
static SkAnalyticEdgesort_edges (SkAnalyticEdge *list[], int count, SkAnalyticEdge **last)
 
static void validate_sort (const SkAnalyticEdge *edge)
 
static bool is_smooth_enough (SkAnalyticEdge *thisEdge, SkAnalyticEdge *nextEdge, int stop_y)
 
static bool is_smooth_enough (SkAnalyticEdge *leftE, SkAnalyticEdge *riteE, SkAnalyticEdge *currE, int stop_y)
 
static void aaa_walk_convex_edges (SkAnalyticEdge *prevHead, AdditiveBlitter *blitter, int start_y, int stop_y, SkFixed leftBound, SkFixed riteBound, bool isUsingMask)
 
static void update_next_next_y (SkFixed y, SkFixed nextY, SkFixed *nextNextY)
 
static void check_intersection (const SkAnalyticEdge *edge, SkFixed nextY, SkFixed *nextNextY)
 
static void check_intersection_fwd (const SkAnalyticEdge *edge, SkFixed nextY, SkFixed *nextNextY)
 
static void insert_new_edges (SkAnalyticEdge *newEdge, SkFixed y, SkFixed *nextNextY)
 
static void validate_edges_for_y (const SkAnalyticEdge *edge, SkFixed y)
 
static bool edges_too_close (SkAnalyticEdge *prev, SkAnalyticEdge *next, SkFixed lowerY)
 
static bool edges_too_close (int prevRite, SkFixed ul, SkFixed ll)
 
static void aaa_walk_edges (SkAnalyticEdge *prevHead, SkAnalyticEdge *nextTail, SkPathFillType fillType, AdditiveBlitter *blitter, int start_y, int stop_y, SkFixed leftClip, SkFixed rightClip, bool isUsingMask, bool forceRLE, bool skipIntersect)
 
static void aaa_fill_path (const SkPath &path, const SkIRect &clipRect, AdditiveBlitter *blitter, int start_y, int stop_y, bool pathContainedInClip, bool isUsingMask, bool forceRLE)
 
static bool try_blit_fat_anti_rect (SkBlitter *blitter, const SkPath &path, const SkIRect &clip)
 

Function Documentation

◆ aaa_fill_path()

static void aaa_fill_path ( const SkPath path,
const SkIRect clipRect,
AdditiveBlitter blitter,
int  start_y,
int  stop_y,
bool  pathContainedInClip,
bool  isUsingMask,
bool  forceRLE 
)
static

Definition at line 1608 of file SkScan_AAAPath.cpp.

1615 { // forceRLE implies that SkAAClip is calling us
1616 SkASSERT(blitter);
1617
1619 int count = builder.buildEdges(path, pathContainedInClip ? nullptr : &clipRect);
1620 SkAnalyticEdge** list = builder.analyticEdgeList();
1621
1623 if (0 == count) {
1624 if (path.isInverseFillType()) {
1625 /*
1626 * Since we are in inverse-fill, our caller has already drawn above
1627 * our top (start_y) and will draw below our bottom (stop_y). Thus
1628 * we need to restrict our drawing to the intersection of the clip
1629 * and those two limits.
1630 */
1631 if (rect.fTop < start_y) {
1632 rect.fTop = start_y;
1633 }
1634 if (rect.fBottom > stop_y) {
1635 rect.fBottom = stop_y;
1636 }
1637 if (!rect.isEmpty()) {
1638 blitter->getRealBlitter()->blitRect(
1639 rect.fLeft, rect.fTop, rect.width(), rect.height());
1640 }
1641 }
1642 return;
1643 }
1644
1645 SkAnalyticEdge headEdge, tailEdge, *last;
1646 // this returns the first and last edge after they're sorted into a dlink list
1647 SkAnalyticEdge* edge = sort_edges(list, count, &last);
1648
1649 headEdge.fPrev = nullptr;
1650 headEdge.fNext = edge;
1651 headEdge.fUpperY = headEdge.fLowerY = SK_MinS32;
1652 headEdge.fX = SK_MinS32;
1653 headEdge.fDX = 0;
1654 headEdge.fDY = SK_MaxS32;
1655 headEdge.fUpperX = SK_MinS32;
1656 edge->fPrev = &headEdge;
1657
1658 tailEdge.fPrev = last;
1659 tailEdge.fNext = nullptr;
1660 tailEdge.fUpperY = tailEdge.fLowerY = SK_MaxS32;
1661 tailEdge.fX = SK_MaxS32;
1662 tailEdge.fDX = 0;
1663 tailEdge.fDY = SK_MaxS32;
1664 tailEdge.fUpperX = SK_MaxS32;
1665 last->fNext = &tailEdge;
1666
1667 // now edge is the head of the sorted linklist
1668
1669 if (!pathContainedInClip && start_y < clipRect.fTop) {
1670 start_y = clipRect.fTop;
1671 }
1672 if (!pathContainedInClip && stop_y > clipRect.fBottom) {
1673 stop_y = clipRect.fBottom;
1674 }
1675
1676 SkFixed leftBound = SkIntToFixed(rect.fLeft);
1677 SkFixed rightBound = SkIntToFixed(rect.fRight);
1678 if (isUsingMask) {
1679 // If we're using mask, then we have to limit the bound within the path bounds.
1680 // Otherwise, the edge drift may access an invalid address inside the mask.
1681 SkIRect ir;
1682 path.getBounds().roundOut(&ir);
1683 leftBound = std::max(leftBound, SkIntToFixed(ir.fLeft));
1684 rightBound = std::min(rightBound, SkIntToFixed(ir.fRight));
1685 }
1686
1687 if (!path.isInverseFillType() && path.isConvex() && count >= 2) {
1689 &headEdge, blitter, start_y, stop_y, leftBound, rightBound, isUsingMask);
1690 } else {
1691 // We skip intersection computation if there are many points which probably already
1692 // give us enough fractional scan lines.
1693 bool skipIntersect = path.countPoints() > (stop_y - start_y) * 2;
1694
1695 aaa_walk_edges(&headEdge,
1696 &tailEdge,
1697 path.getFillType(),
1698 blitter,
1699 start_y,
1700 stop_y,
1701 leftBound,
1702 rightBound,
1703 isUsingMask,
1704 forceRLE,
1705 skipIntersect);
1706 }
1707}
int count
Definition: FontMgrTest.cpp:50
#define SkASSERT(cond)
Definition: SkAssert.h:116
int32_t SkFixed
Definition: SkFixed.h:25
#define SkIntToFixed(n)
Definition: SkFixed.h:73
static constexpr int32_t SK_MinS32
Definition: SkMath.h:22
static constexpr int32_t SK_MaxS32
Definition: SkMath.h:21
static void aaa_walk_edges(SkAnalyticEdge *prevHead, SkAnalyticEdge *nextTail, SkPathFillType fillType, AdditiveBlitter *blitter, int start_y, int stop_y, SkFixed leftClip, SkFixed rightClip, bool isUsingMask, bool forceRLE, bool skipIntersect)
static void aaa_walk_convex_edges(SkAnalyticEdge *prevHead, AdditiveBlitter *blitter, int start_y, int stop_y, SkFixed leftBound, SkFixed riteBound, bool isUsingMask)
static SkAnalyticEdge * sort_edges(SkAnalyticEdge *list[], int count, SkAnalyticEdge **last)
virtual SkBlitter * getRealBlitter(bool forceRealBlitter=false)=0
virtual void blitRect(int x, int y, int width, int height)
Blit a solid rectangle one or more pixels wide.
Definition: SkBlitter.cpp:133
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
clipRect(r.rect, r.opAA.op(), r.opAA.aa())) template<> void Draw
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
SkAnalyticEdge * fNext
SkAnalyticEdge * fPrev
Definition: SkRect.h:32
int32_t fLeft
smaller x-axis bounds
Definition: SkRect.h:33
int32_t fRight
larger x-axis bounds
Definition: SkRect.h:35

◆ aaa_walk_convex_edges()

static void aaa_walk_convex_edges ( SkAnalyticEdge prevHead,
AdditiveBlitter blitter,
int  start_y,
int  stop_y,
SkFixed  leftBound,
SkFixed  riteBound,
bool  isUsingMask 
)
static

Definition at line 1042 of file SkScan_AAAPath.cpp.

1048 {
1049 validate_sort((SkAnalyticEdge*)prevHead->fNext);
1050
1051 SkAnalyticEdge* leftE = (SkAnalyticEdge*)prevHead->fNext;
1052 SkAnalyticEdge* riteE = (SkAnalyticEdge*)leftE->fNext;
1053 SkAnalyticEdge* currE = (SkAnalyticEdge*)riteE->fNext;
1054
1055 SkFixed y = std::max(leftE->fUpperY, riteE->fUpperY);
1056
1057 for (;;) {
1058 // We have to check fLowerY first because some edges might be alone (e.g., there's only
1059 // a left edge but no right edge in a given y scan line) due to precision limit.
1060 while (leftE->fLowerY <= y) { // Due to smooth jump, we may pass multiple short edges
1061 if (!leftE->update(y)) {
1062 if (SkFixedFloorToInt(currE->fUpperY) >= stop_y) {
1063 goto END_WALK;
1064 }
1065 leftE = currE;
1066 currE = (SkAnalyticEdge*)currE->fNext;
1067 }
1068 }
1069 while (riteE->fLowerY <= y) { // Due to smooth jump, we may pass multiple short edges
1070 if (!riteE->update(y)) {
1071 if (SkFixedFloorToInt(currE->fUpperY) >= stop_y) {
1072 goto END_WALK;
1073 }
1074 riteE = currE;
1075 currE = (SkAnalyticEdge*)currE->fNext;
1076 }
1077 }
1078
1079 SkASSERT(leftE);
1080 SkASSERT(riteE);
1081
1082 // check our bottom clip
1083 if (SkFixedFloorToInt(y) >= stop_y) {
1084 break;
1085 }
1086
1087 SkASSERT(SkFixedFloorToInt(leftE->fUpperY) <= stop_y);
1088 SkASSERT(SkFixedFloorToInt(riteE->fUpperY) <= stop_y);
1089
1090 leftE->goY(y);
1091 riteE->goY(y);
1092
1093 if (leftE->fX > riteE->fX || (leftE->fX == riteE->fX && leftE->fDX > riteE->fDX)) {
1094 std::swap(leftE, riteE);
1095 }
1096
1097 SkFixed local_bot_fixed = std::min(leftE->fLowerY, riteE->fLowerY);
1098 if (is_smooth_enough(leftE, riteE, currE, stop_y)) {
1099 local_bot_fixed = SkFixedCeilToFixed(local_bot_fixed);
1100 }
1101 local_bot_fixed = std::min(local_bot_fixed, SkIntToFixed(stop_y));
1102
1103 SkFixed left = std::max(leftBound, leftE->fX);
1104 SkFixed dLeft = leftE->fDX;
1105 SkFixed rite = std::min(riteBound, riteE->fX);
1106 SkFixed dRite = riteE->fDX;
1107 if (0 == (dLeft | dRite)) {
1108 int fullLeft = SkFixedCeilToInt(left);
1109 int fullRite = SkFixedFloorToInt(rite);
1110 SkFixed partialLeft = SkIntToFixed(fullLeft) - left;
1111 SkFixed partialRite = rite - SkIntToFixed(fullRite);
1112 int fullTop = SkFixedCeilToInt(y);
1113 int fullBot = SkFixedFloorToInt(local_bot_fixed);
1114 SkFixed partialTop = SkIntToFixed(fullTop) - y;
1115 SkFixed partialBot = local_bot_fixed - SkIntToFixed(fullBot);
1116 if (fullTop > fullBot) { // The rectangle is within one pixel height...
1117 partialTop -= (SK_Fixed1 - partialBot);
1118 partialBot = 0;
1119 }
1120
1121 if (fullRite >= fullLeft) {
1122 if (partialTop > 0) { // blit first partial row
1123 if (partialLeft > 0) {
1124 blitter->blitAntiH(fullLeft - 1,
1125 fullTop - 1,
1126 fixed_to_alpha(SkFixedMul(partialTop, partialLeft)));
1127 }
1128 blitter->blitAntiH(
1129 fullLeft, fullTop - 1, fullRite - fullLeft, fixed_to_alpha(partialTop));
1130 if (partialRite > 0) {
1131 blitter->blitAntiH(fullRite,
1132 fullTop - 1,
1133 fixed_to_alpha(SkFixedMul(partialTop, partialRite)));
1134 }
1135 blitter->flush_if_y_changed(y, y + partialTop);
1136 }
1137
1138 // Blit all full-height rows from fullTop to fullBot
1139 if (fullBot > fullTop &&
1140 // SkAAClip cannot handle the empty rect so check the non-emptiness here
1141 // (bug chromium:662800)
1142 (fullRite > fullLeft || fixed_to_alpha(partialLeft) > 0 ||
1143 fixed_to_alpha(partialRite) > 0)) {
1144 blitter->getRealBlitter()->blitAntiRect(fullLeft - 1,
1145 fullTop,
1146 fullRite - fullLeft,
1147 fullBot - fullTop,
1148 fixed_to_alpha(partialLeft),
1149 fixed_to_alpha(partialRite));
1150 }
1151
1152 if (partialBot > 0) { // blit last partial row
1153 if (partialLeft > 0) {
1154 blitter->blitAntiH(fullLeft - 1,
1155 fullBot,
1156 fixed_to_alpha(SkFixedMul(partialBot, partialLeft)));
1157 }
1158 blitter->blitAntiH(
1159 fullLeft, fullBot, fullRite - fullLeft, fixed_to_alpha(partialBot));
1160 if (partialRite > 0) {
1161 blitter->blitAntiH(fullRite,
1162 fullBot,
1163 fixed_to_alpha(SkFixedMul(partialBot, partialRite)));
1164 }
1165 }
1166 } else {
1167 // Normal conditions, this means left and rite are within the same pixel, but if
1168 // both left and rite were < leftBounds or > rightBounds, both edges are clipped and
1169 // we should not do any blitting (particularly since the negative width saturates to
1170 // full alpha).
1171 SkFixed width = rite - left;
1172 if (width > 0) {
1173 if (partialTop > 0) {
1174 blitter->blitAntiH(fullLeft - 1,
1175 fullTop - 1,
1176 1,
1177 fixed_to_alpha(SkFixedMul(partialTop, width)));
1178 blitter->flush_if_y_changed(y, y + partialTop);
1179 }
1180 if (fullBot > fullTop) {
1181 blitter->getRealBlitter()->blitV(
1182 fullLeft - 1, fullTop, fullBot - fullTop, fixed_to_alpha(width));
1183 }
1184 if (partialBot > 0) {
1185 blitter->blitAntiH(fullLeft - 1,
1186 fullBot,
1187 1,
1188 fixed_to_alpha(SkFixedMul(partialBot, width)));
1189 }
1190 }
1191 }
1192
1193 y = local_bot_fixed;
1194 } else {
1195 // The following constant are used to snap X
1196 // We snap X mainly for speedup (no tiny triangle) and
1197 // avoiding edge cases caused by precision errors
1198 const SkFixed kSnapDigit = SK_Fixed1 >> 4;
1199 const SkFixed kSnapHalf = kSnapDigit >> 1;
1200 const SkFixed kSnapMask = (-1 ^ (kSnapDigit - 1));
1201 left += kSnapHalf;
1202 rite += kSnapHalf; // For fast rounding
1203
1204 // Number of blit_trapezoid_row calls we'll have
1205 int count = SkFixedCeilToInt(local_bot_fixed) - SkFixedFloorToInt(y);
1206
1207 // If we're using mask blitter, we advance the mask row in this function
1208 // to save some "if" condition checks.
1209 SkAlpha* maskRow = isUsingMask
1210 ? static_cast<MaskAdditiveBlitter*>(blitter)->getRow(y >> 16)
1211 : nullptr;
1212
1213 // Instead of writing one loop that handles both partial-row blit_trapezoid_row
1214 // and full-row trapezoid_row together, we use the following 3-stage flow to
1215 // handle partial-row blit and full-row blit separately. It will save us much time
1216 // on changing y, left, and rite.
1217 if (count > 1) {
1218 if ((int)(y & 0xFFFF0000) != y) { // There's a partial-row on the top
1219 count--;
1220 SkFixed nextY = SkFixedCeilToFixed(y + 1);
1221 SkFixed dY = nextY - y;
1222 SkFixed nextLeft = left + SkFixedMul(dLeft, dY);
1223 SkFixed nextRite = rite + SkFixedMul(dRite, dY);
1224 SkASSERT((left & kSnapMask) >= leftBound && (rite & kSnapMask) <= riteBound &&
1225 (nextLeft & kSnapMask) >= leftBound &&
1226 (nextRite & kSnapMask) <= riteBound);
1227 blit_trapezoid_row(blitter,
1228 y >> 16,
1229 left & kSnapMask,
1230 rite & kSnapMask,
1231 nextLeft & kSnapMask,
1232 nextRite & kSnapMask,
1233 leftE->fDY,
1234 riteE->fDY,
1235 get_partial_alpha(0xFF, dY),
1236 maskRow,
1237 /*noRealBlitter=*/false);
1238 blitter->flush_if_y_changed(y, nextY);
1239 left = nextLeft;
1240 rite = nextRite;
1241 y = nextY;
1242 }
1243
1244 while (count > 1) { // Full rows in the middle
1245 count--;
1246 if (isUsingMask) {
1247 maskRow = static_cast<MaskAdditiveBlitter*>(blitter)->getRow(y >> 16);
1248 }
1249 SkFixed nextY = y + SK_Fixed1, nextLeft = left + dLeft, nextRite = rite + dRite;
1250 SkASSERT((left & kSnapMask) >= leftBound && (rite & kSnapMask) <= riteBound &&
1251 (nextLeft & kSnapMask) >= leftBound &&
1252 (nextRite & kSnapMask) <= riteBound);
1253 blit_trapezoid_row(blitter,
1254 y >> 16,
1255 left & kSnapMask,
1256 rite & kSnapMask,
1257 nextLeft & kSnapMask,
1258 nextRite & kSnapMask,
1259 leftE->fDY,
1260 riteE->fDY,
1261 0xFF,
1262 maskRow,
1263 /*noRealBlitter=*/false);
1264 blitter->flush_if_y_changed(y, nextY);
1265 left = nextLeft;
1266 rite = nextRite;
1267 y = nextY;
1268 }
1269 }
1270
1271 if (isUsingMask) {
1272 maskRow = static_cast<MaskAdditiveBlitter*>(blitter)->getRow(y >> 16);
1273 }
1274
1275 SkFixed dY = local_bot_fixed - y; // partial-row on the bottom
1276 SkASSERT(dY <= SK_Fixed1);
1277 // Smooth jumping to integer y may make the last nextLeft/nextRite out of bound.
1278 // Take them back into the bound here.
1279 // Note that we substract kSnapHalf later so we have to add them to leftBound/riteBound
1280 SkFixed nextLeft = std::max(left + SkFixedMul(dLeft, dY), leftBound + kSnapHalf);
1281 SkFixed nextRite = std::min(rite + SkFixedMul(dRite, dY), riteBound + kSnapHalf);
1282 SkASSERT((left & kSnapMask) >= leftBound && (rite & kSnapMask) <= riteBound &&
1283 (nextLeft & kSnapMask) >= leftBound && (nextRite & kSnapMask) <= riteBound);
1284 blit_trapezoid_row(blitter,
1285 y >> 16,
1286 left & kSnapMask,
1287 rite & kSnapMask,
1288 nextLeft & kSnapMask,
1289 nextRite & kSnapMask,
1290 leftE->fDY,
1291 riteE->fDY,
1292 get_partial_alpha(0xFF, dY),
1293 maskRow,
1294 /*noRealBlitter=*/false);
1295 blitter->flush_if_y_changed(y, local_bot_fixed);
1296 left = nextLeft;
1297 rite = nextRite;
1298 y = local_bot_fixed;
1299 left -= kSnapHalf;
1300 rite -= kSnapHalf;
1301 }
1302
1303 leftE->fX = left;
1304 riteE->fX = rite;
1305 leftE->fY = riteE->fY = y;
1306 }
1307
1308END_WALK:;
1309}
uint8_t SkAlpha
Definition: SkColor.h:26
#define SkFixedCeilToInt(x)
Definition: SkFixed.h:77
#define SK_Fixed1
Definition: SkFixed.h:26
static SkFixed SkFixedCeilToFixed(SkFixed x)
Definition: SkFixed.h:83
#define SkFixedFloorToInt(x)
Definition: SkFixed.h:78
static SkFixed SkFixedMul(SkFixed a, SkFixed b)
Definition: SkFixed.h:96
static bool left(const SkPoint &p0, const SkPoint &p1)
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
static void validate_sort(const SkAnalyticEdge *edge)
static SkAlpha fixed_to_alpha(SkFixed f)
static bool is_smooth_enough(SkAnalyticEdge *thisEdge, SkAnalyticEdge *nextEdge, int stop_y)
static SkAlpha get_partial_alpha(SkAlpha alpha, SkFixed partialHeight)
static void blit_trapezoid_row(AdditiveBlitter *blitter, int y, SkFixed ul, SkFixed ur, SkFixed ll, SkFixed lr, SkFixed lDY, SkFixed rDY, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)
virtual void flush_if_y_changed(SkFixed y, SkFixed nextY)=0
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], int len)=0
virtual void blitAntiRect(int x, int y, int width, int height, SkAlpha leftAlpha, SkAlpha rightAlpha)
Definition: SkBlitter.cpp:143
virtual void blitV(int x, int y, int height, SkAlpha alpha)
Blit a vertical run of pixels with a constant alpha value.
Definition: SkBlitter.cpp:119
double y
int32_t width
void goY(SkFixed y)
bool update(SkFixed last_y, bool sortY=true)

◆ aaa_walk_edges()

static void aaa_walk_edges ( SkAnalyticEdge prevHead,
SkAnalyticEdge nextTail,
SkPathFillType  fillType,
AdditiveBlitter blitter,
int  start_y,
int  stop_y,
SkFixed  leftClip,
SkFixed  rightClip,
bool  isUsingMask,
bool  forceRLE,
bool  skipIntersect 
)
static

Definition at line 1409 of file SkScan_AAAPath.cpp.

1419 {
1420 prevHead->fX = prevHead->fUpperX = leftClip;
1421 nextTail->fX = nextTail->fUpperX = rightClip;
1422 SkFixed y = std::max(prevHead->fNext->fUpperY, SkIntToFixed(start_y));
1423 SkFixed nextNextY = SK_MaxS32;
1424
1425 {
1426 SkAnalyticEdge* edge;
1427 for (edge = prevHead->fNext; edge->fUpperY <= y; edge = edge->fNext) {
1428 edge->goY(y);
1429 update_next_next_y(edge->fLowerY, y, &nextNextY);
1430 }
1431 update_next_next_y(edge->fUpperY, y, &nextNextY);
1432 }
1433
1434 int windingMask = SkPathFillType_IsEvenOdd(fillType) ? 1 : -1;
1435 bool isInverse = SkPathFillType_IsInverse(fillType);
1436
1437 if (isInverse && SkIntToFixed(start_y) != y) {
1438 int width = SkFixedFloorToInt(rightClip - leftClip);
1439 if (SkFixedFloorToInt(y) != start_y) {
1440 blitter->getRealBlitter()->blitRect(
1441 SkFixedFloorToInt(leftClip), start_y, width, SkFixedFloorToInt(y) - start_y);
1442 start_y = SkFixedFloorToInt(y);
1443 }
1444 SkAlpha* maskRow =
1445 isUsingMask ? static_cast<MaskAdditiveBlitter*>(blitter)->getRow(start_y) : nullptr;
1446 blit_full_alpha(blitter,
1447 start_y,
1448 SkFixedFloorToInt(leftClip),
1449 width,
1450 fixed_to_alpha(y - SkIntToFixed(start_y)),
1451 maskRow,
1452 false);
1453 }
1454
1455 while (true) {
1456 int w = 0;
1457 bool in_interval = isInverse;
1458 SkFixed prevX = prevHead->fX;
1459 SkFixed nextY = std::min(nextNextY, SkFixedCeilToFixed(y + 1));
1460 SkAnalyticEdge* currE = prevHead->fNext;
1461 SkAnalyticEdge* leftE = prevHead;
1462 SkFixed left = leftClip;
1463 SkFixed leftDY = 0;
1464 int prevRite = SkFixedFloorToInt(leftClip);
1465
1466 nextNextY = SK_MaxS32;
1467
1468 SkASSERT((nextY & ((SK_Fixed1 >> 2) - 1)) == 0);
1469 int yShift = 0;
1470 if ((nextY - y) & (SK_Fixed1 >> 2)) {
1471 yShift = 2;
1472 nextY = y + (SK_Fixed1 >> 2);
1473 } else if ((nextY - y) & (SK_Fixed1 >> 1)) {
1474 yShift = 1;
1475 SkASSERT(nextY == y + (SK_Fixed1 >> 1));
1476 }
1477
1478 SkAlpha fullAlpha = fixed_to_alpha(nextY - y);
1479
1480 // If we're using mask blitter, we advance the mask row in this function
1481 // to save some "if" condition checks.
1482 SkAlpha* maskRow =
1483 isUsingMask
1484 ? static_cast<MaskAdditiveBlitter*>(blitter)->getRow(SkFixedFloorToInt(y))
1485 : nullptr;
1486
1487 SkASSERT(currE->fPrev == prevHead);
1488 validate_edges_for_y(currE, y);
1489
1490 // Even if next - y == SK_Fixed1, we can still break the left-to-right order requirement
1491 // of the SKAAClip: |\| (two trapezoids with overlapping middle wedges)
1492 bool noRealBlitter = forceRLE; // forceRLE && (nextY - y != SK_Fixed1);
1493
1494 while (currE->fUpperY <= y) {
1495 SkASSERT(currE->fLowerY >= nextY);
1496 SkASSERT(currE->fY == y);
1497
1498 w += currE->fWinding;
1499 bool prev_in_interval = in_interval;
1500 in_interval = !(w & windingMask) == isInverse;
1501
1502 bool isLeft = in_interval && !prev_in_interval;
1503 bool isRite = !in_interval && prev_in_interval;
1504
1505 if (isRite) {
1506 SkFixed rite = currE->fX;
1507 currE->goY(nextY, yShift);
1508 SkFixed nextLeft = std::max(leftClip, leftE->fX);
1509 rite = std::min(rightClip, rite);
1510 SkFixed nextRite = std::min(rightClip, currE->fX);
1512 blitter,
1513 y >> 16,
1514 left,
1515 rite,
1516 nextLeft,
1517 nextRite,
1518 leftDY,
1519 currE->fDY,
1520 fullAlpha,
1521 maskRow,
1522 noRealBlitter || (fullAlpha == 0xFF &&
1523 (edges_too_close(prevRite, left, leftE->fX) ||
1524 edges_too_close(currE, currE->fNext, nextY))));
1525 prevRite = SkFixedCeilToInt(std::max(rite, currE->fX));
1526 } else {
1527 if (isLeft) {
1528 left = std::max(currE->fX, leftClip);
1529 leftDY = currE->fDY;
1530 leftE = currE;
1531 }
1532 currE->goY(nextY, yShift);
1533 }
1534
1535 SkAnalyticEdge* next = currE->fNext;
1536 SkFixed newX;
1537
1538 while (currE->fLowerY <= nextY) {
1539 if (currE->fCurveCount < 0) {
1540 SkAnalyticCubicEdge* cubicEdge = (SkAnalyticCubicEdge*)currE;
1541 cubicEdge->keepContinuous();
1542 if (!cubicEdge->updateCubic()) {
1543 break;
1544 }
1545 } else if (currE->fCurveCount > 0) {
1547 quadEdge->keepContinuous();
1548 if (!quadEdge->updateQuadratic()) {
1549 break;
1550 }
1551 } else {
1552 break;
1553 }
1554 }
1555 SkASSERT(currE->fY == nextY);
1556
1557 if (currE->fLowerY <= nextY) {
1558 remove_edge(currE);
1559 } else {
1560 update_next_next_y(currE->fLowerY, nextY, &nextNextY);
1561 newX = currE->fX;
1562 SkASSERT(currE->fLowerY > nextY);
1563 if (newX < prevX) {
1564 // ripple currE backwards until it is x-sorted
1566 } else {
1567 prevX = newX;
1568 }
1569 if (!skipIntersect) {
1570 check_intersection(currE, nextY, &nextNextY);
1571 }
1572 }
1573
1574 currE = next;
1575 SkASSERT(currE);
1576 }
1577
1578 // was our right-edge culled away?
1579 if (in_interval) {
1580 blit_trapezoid_row(blitter,
1581 y >> 16,
1582 left,
1583 rightClip,
1584 std::max(leftClip, leftE->fX),
1585 rightClip,
1586 leftDY,
1587 0,
1588 fullAlpha,
1589 maskRow,
1590 noRealBlitter || (fullAlpha == 0xFF &&
1591 edges_too_close(leftE->fPrev, leftE, nextY)));
1592 }
1593
1594 if (forceRLE) {
1595 ((RunBasedAdditiveBlitter*)blitter)->flush_if_y_changed(y, nextY);
1596 }
1597
1598 y = nextY;
1599 if (y >= SkIntToFixed(stop_y)) {
1600 break;
1601 }
1602
1603 // now currE points to the first edge with a fUpperY larger than the previous y
1604 insert_new_edges(currE, y, &nextNextY);
1605 }
1606}
static float next(float f)
static bool SkPathFillType_IsInverse(SkPathFillType ft)
Definition: SkPathTypes.h:26
static bool SkPathFillType_IsEvenOdd(SkPathFillType ft)
Definition: SkPathTypes.h:22
static void remove_edge(EdgeType *edge)
Definition: SkScanPriv.h:45
void backward_insert_edge_based_on_x(EdgeType *edge)
Definition: SkScanPriv.h:59
static void update_next_next_y(SkFixed y, SkFixed nextY, SkFixed *nextNextY)
static void check_intersection(const SkAnalyticEdge *edge, SkFixed nextY, SkFixed *nextNextY)
static void validate_edges_for_y(const SkAnalyticEdge *edge, SkFixed y)
static void blit_full_alpha(AdditiveBlitter *blitter, int y, int x, int len, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)
static void insert_new_edges(SkAnalyticEdge *newEdge, SkFixed y, SkFixed *nextNextY)
static bool edges_too_close(SkAnalyticEdge *prev, SkAnalyticEdge *next, SkFixed lowerY)
SkScalar w
bool updateCubic(bool sortY=true)

◆ add_alpha()

static void add_alpha ( SkAlpha alpha,
SkAlpha  delta 
)
static

Definition at line 91 of file SkScan_AAAPath.cpp.

91 {
92 SkASSERT(*alpha + delta <= 256);
93 *alpha = SkAlphaRuns::CatchOverflow(*alpha + delta);
94}
static SkAlpha CatchOverflow(int alpha)
Definition: SkAlphaRuns.h:30

◆ approximate_intersection()

static SkFixed approximate_intersection ( SkFixed  l1,
SkFixed  r1,
SkFixed  l2,
SkFixed  r2 
)
static

Definition at line 579 of file SkScan_AAAPath.cpp.

579 {
580 if (l1 > r1) {
581 std::swap(l1, r1);
582 }
583 if (l2 > r2) {
584 std::swap(l2, r2);
585 }
586 return (std::max(l1, l2) + std::min(r1, r2)) / 2;
587}

◆ blit_aaa_trapezoid_row()

static void blit_aaa_trapezoid_row ( AdditiveBlitter blitter,
int  y,
SkFixed  ul,
SkFixed  ur,
SkFixed  ll,
SkFixed  lr,
SkFixed  lDY,
SkFixed  rDY,
SkAlpha  fullAlpha,
SkAlpha maskRow,
bool  noRealBlitter 
)
static

Definition at line 707 of file SkScan_AAAPath.cpp.

717 {
718 int L = SkFixedFloorToInt(ul), R = SkFixedCeilToInt(lr);
719 int len = R - L;
720
721 if (len == 1) {
722 SkAlpha alpha = trapezoid_to_alpha(ur - ul, lr - ll);
723 blit_single_alpha(blitter, y, L, alpha, fullAlpha, maskRow, noRealBlitter);
724 return;
725 }
726
727 const int kQuickLen = 31;
728 alignas(2) char quickMemory[(sizeof(SkAlpha) * 2 + sizeof(int16_t)) * (kQuickLen + 1)];
729 SkAlpha* alphas;
730
731 if (len <= kQuickLen) {
732 alphas = (SkAlpha*)quickMemory;
733 } else {
734 alphas = new SkAlpha[(len + 1) * (sizeof(SkAlpha) * 2 + sizeof(int16_t))];
735 }
736
737 SkAlpha* tempAlphas = alphas + len + 1;
738 int16_t* runs = (int16_t*)(alphas + (len + 1) * 2);
739
740 for (int i = 0; i < len; ++i) {
741 runs[i] = 1;
742 alphas[i] = fullAlpha;
743 }
744 runs[len] = 0;
745
746 int uL = SkFixedFloorToInt(ul);
747 int lL = SkFixedCeilToInt(ll);
748 if (uL + 2 == lL) { // We only need to compute two triangles, accelerate this special case
749 SkFixed first = SkIntToFixed(uL) + SK_Fixed1 - ul;
750 SkFixed second = ll - ul - first;
751 SkAlpha a1 = fullAlpha - partial_triangle_to_alpha(first, lDY);
752 SkAlpha a2 = partial_triangle_to_alpha(second, lDY);
753 alphas[0] = alphas[0] > a1 ? alphas[0] - a1 : 0;
754 alphas[1] = alphas[1] > a2 ? alphas[1] - a2 : 0;
755 } else {
757 tempAlphas + uL - L, ul - SkIntToFixed(uL), ll - SkIntToFixed(uL), lDY, fullAlpha);
758 for (int i = uL; i < lL; ++i) {
759 if (alphas[i - L] > tempAlphas[i - L]) {
760 alphas[i - L] -= tempAlphas[i - L];
761 } else {
762 alphas[i - L] = 0;
763 }
764 }
765 }
766
767 int uR = SkFixedFloorToInt(ur);
768 int lR = SkFixedCeilToInt(lr);
769 if (uR + 2 == lR) { // We only need to compute two triangles, accelerate this special case
770 SkFixed first = SkIntToFixed(uR) + SK_Fixed1 - ur;
771 SkFixed second = lr - ur - first;
772 SkAlpha a1 = partial_triangle_to_alpha(first, rDY);
773 SkAlpha a2 = fullAlpha - partial_triangle_to_alpha(second, rDY);
774 alphas[len - 2] = alphas[len - 2] > a1 ? alphas[len - 2] - a1 : 0;
775 alphas[len - 1] = alphas[len - 1] > a2 ? alphas[len - 1] - a2 : 0;
776 } else {
778 tempAlphas + uR - L, ur - SkIntToFixed(uR), lr - SkIntToFixed(uR), rDY, fullAlpha);
779 for (int i = uR; i < lR; ++i) {
780 if (alphas[i - L] > tempAlphas[i - L]) {
781 alphas[i - L] -= tempAlphas[i - L];
782 } else {
783 alphas[i - L] = 0;
784 }
785 }
786 }
787
788 if (maskRow) {
789 for (int i = 0; i < len; ++i) {
790 safely_add_alpha(&maskRow[L + i], alphas[i]);
791 }
792 } else {
793 if (fullAlpha == 0xFF && !noRealBlitter) {
794 // Real blitter is faster than RunBasedAdditiveBlitter
795 blitter->getRealBlitter()->blitAntiH(L, y, alphas, runs);
796 } else {
797 blitter->blitAntiH(L, y, alphas, len);
798 }
799 }
800
801 if (len > kQuickLen) {
802 delete[] alphas;
803 }
804}
static SkAlpha trapezoid_to_alpha(SkFixed l1, SkFixed l2)
static SkAlpha partial_triangle_to_alpha(SkFixed a, SkFixed b)
static void blit_single_alpha(AdditiveBlitter *blitter, int y, int x, SkAlpha alpha, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)
static void safely_add_alpha(SkAlpha *alpha, SkAlpha delta)
static void compute_alpha_below_line(SkAlpha *alphas, SkFixed l, SkFixed r, SkFixed dY, SkAlpha fullAlpha)
static void compute_alpha_above_line(SkAlpha *alphas, SkFixed l, SkFixed r, SkFixed dY, SkAlpha fullAlpha)
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])=0
#define R(r)

◆ blit_full_alpha()

static void blit_full_alpha ( AdditiveBlitter blitter,
int  y,
int  x,
int  len,
SkAlpha  fullAlpha,
SkAlpha maskRow,
bool  noRealBlitter 
)
static

Definition at line 687 of file SkScan_AAAPath.cpp.

693 {
694 if (maskRow) {
695 for (int i = 0; i < len; ++i) {
696 safely_add_alpha(&maskRow[x + i], fullAlpha);
697 }
698 } else {
699 if (fullAlpha == 0xFF && !noRealBlitter) {
700 blitter->getRealBlitter()->blitH(x, y, len);
701 } else {
702 blitter->blitAntiH(x, y, len, fullAlpha);
703 }
704 }
705}
virtual void blitH(int x, int y, int width)=0
Blit a horizontal run of one or more pixels.
double x

◆ blit_single_alpha()

static void blit_single_alpha ( AdditiveBlitter blitter,
int  y,
int  x,
SkAlpha  alpha,
SkAlpha  fullAlpha,
SkAlpha maskRow,
bool  noRealBlitter 
)
static

Definition at line 644 of file SkScan_AAAPath.cpp.

650 {
651 if (maskRow) {
652 if (fullAlpha == 0xFF && !noRealBlitter) { // noRealBlitter is needed for concave paths
653 maskRow[x] = alpha;
654 } else {
655 safely_add_alpha(&maskRow[x], get_partial_alpha(alpha, fullAlpha));
656 }
657 } else {
658 if (fullAlpha == 0xFF && !noRealBlitter) {
659 blitter->getRealBlitter()->blitV(x, y, 1, alpha);
660 } else {
661 blitter->blitAntiH(x, y, get_partial_alpha(alpha, fullAlpha));
662 }
663 }
664}

◆ blit_trapezoid_row()

static void blit_trapezoid_row ( AdditiveBlitter blitter,
int  y,
SkFixed  ul,
SkFixed  ur,
SkFixed  ll,
SkFixed  lr,
SkFixed  lDY,
SkFixed  rDY,
SkAlpha  fullAlpha,
SkAlpha maskRow,
bool  noRealBlitter 
)
static

Definition at line 806 of file SkScan_AAAPath.cpp.

816 {
817 SkASSERT(lDY >= 0 && rDY >= 0); // We should only send in the absolte value
818
819 if (ul > ur) {
820 return;
821 }
822
823 // Edge crosses. Approximate it. This should only happend due to precision limit,
824 // so the approximation could be very coarse.
825 if (ll > lr) {
826 ll = lr = approximate_intersection(ul, ll, ur, lr);
827 }
828
829 if (ul == ur && ll == lr) {
830 return; // empty trapzoid
831 }
832
833 // We're going to use the left line ul-ll and the rite line ur-lr
834 // to exclude the area that's not covered by the path.
835 // Swapping (ul, ll) or (ur, lr) won't affect that exclusion
836 // so we'll do that for simplicity.
837 if (ul > ll) {
838 std::swap(ul, ll);
839 }
840 if (ur > lr) {
841 std::swap(ur, lr);
842 }
843
844 SkFixed joinLeft = SkFixedCeilToFixed(ll);
845 SkFixed joinRite = SkFixedFloorToFixed(ur);
846 if (joinLeft <= joinRite) { // There's a rect from joinLeft to joinRite that we can blit
847 if (ul < joinLeft) {
848 int len = SkFixedCeilToInt(joinLeft - ul);
849 if (len == 1) {
850 SkAlpha alpha = trapezoid_to_alpha(joinLeft - ul, joinLeft - ll);
851 blit_single_alpha(blitter,
852 y,
853 ul >> 16,
854 alpha,
855 fullAlpha,
856 maskRow,
857 noRealBlitter);
858 } else if (len == 2) {
859 SkFixed first = joinLeft - SK_Fixed1 - ul;
860 SkFixed second = ll - ul - first;
861 SkAlpha a1 = partial_triangle_to_alpha(first, lDY);
862 SkAlpha a2 = fullAlpha - partial_triangle_to_alpha(second, lDY);
863 blit_two_alphas(blitter,
864 y,
865 ul >> 16,
866 a1,
867 a2,
868 fullAlpha,
869 maskRow,
870 noRealBlitter);
871 } else {
873 y,
874 ul,
875 joinLeft,
876 ll,
877 joinLeft,
878 lDY,
879 SK_MaxS32,
880 fullAlpha,
881 maskRow,
882 noRealBlitter);
883 }
884 }
885 // SkAAClip requires that we blit from left to right.
886 // Hence we must blit [ul, joinLeft] before blitting [joinLeft, joinRite]
887 if (joinLeft < joinRite) {
888 blit_full_alpha(blitter,
889 y,
890 SkFixedFloorToInt(joinLeft),
891 SkFixedFloorToInt(joinRite - joinLeft),
892 fullAlpha,
893 maskRow,
894 noRealBlitter);
895 }
896 if (lr > joinRite) {
897 int len = SkFixedCeilToInt(lr - joinRite);
898 if (len == 1) {
899 SkAlpha alpha = trapezoid_to_alpha(ur - joinRite, lr - joinRite);
900 blit_single_alpha(blitter,
901 y,
902 joinRite >> 16,
903 alpha,
904 fullAlpha,
905 maskRow,
906 noRealBlitter);
907 } else if (len == 2) {
908 SkFixed first = joinRite + SK_Fixed1 - ur;
909 SkFixed second = lr - ur - first;
910 SkAlpha a1 = fullAlpha - partial_triangle_to_alpha(first, rDY);
911 SkAlpha a2 = partial_triangle_to_alpha(second, rDY);
912 blit_two_alphas(blitter,
913 y,
914 joinRite >> 16,
915 a1,
916 a2,
917 fullAlpha,
918 maskRow,
919 noRealBlitter);
920 } else {
922 y,
923 joinRite,
924 ur,
925 joinRite,
926 lr,
927 SK_MaxS32,
928 rDY,
929 fullAlpha,
930 maskRow,
931 noRealBlitter);
932 }
933 }
934 } else {
936 y,
937 ul,
938 ur,
939 ll,
940 lr,
941 lDY,
942 rDY,
943 fullAlpha,
944 maskRow,
945 noRealBlitter);
946 }
947}
static SkFixed SkFixedFloorToFixed(SkFixed x)
Definition: SkFixed.h:86
static SkFixed approximate_intersection(SkFixed l1, SkFixed r1, SkFixed l2, SkFixed r2)
static void blit_two_alphas(AdditiveBlitter *blitter, int y, int x, SkAlpha a1, SkAlpha a2, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)
static void blit_aaa_trapezoid_row(AdditiveBlitter *blitter, int y, SkFixed ul, SkFixed ur, SkFixed ll, SkFixed lr, SkFixed lDY, SkFixed rDY, SkAlpha fullAlpha, SkAlpha *maskRow, bool noRealBlitter)

◆ blit_two_alphas()

static void blit_two_alphas ( AdditiveBlitter blitter,
int  y,
int  x,
SkAlpha  a1,
SkAlpha  a2,
SkAlpha  fullAlpha,
SkAlpha maskRow,
bool  noRealBlitter 
)
static

Definition at line 666 of file SkScan_AAAPath.cpp.

673 {
674 if (maskRow) {
675 safely_add_alpha(&maskRow[x], a1);
676 safely_add_alpha(&maskRow[x + 1], a2);
677 } else {
678 if (fullAlpha == 0xFF && !noRealBlitter) {
679 blitter->getRealBlitter()->blitAntiH2(x, y, a1, a2);
680 } else {
681 blitter->blitAntiH(x, y, a1);
682 blitter->blitAntiH(x + 1, y, a2);
683 }
684 }
685}
virtual void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1)
Definition: SkBlitter.h:81

◆ check_intersection()

static void check_intersection ( const SkAnalyticEdge edge,
SkFixed  nextY,
SkFixed nextNextY 
)
static

Definition at line 1315 of file SkScan_AAAPath.cpp.

1315 {
1316 if (edge->fPrev->fPrev && edge->fPrev->fX + edge->fPrev->fDX > edge->fX + edge->fDX) {
1317 *nextNextY = nextY + (SK_Fixed1 >> SkAnalyticEdge::kDefaultAccuracy);
1318 }
1319}
static const int kDefaultAccuracy

◆ check_intersection_fwd()

static void check_intersection_fwd ( const SkAnalyticEdge edge,
SkFixed  nextY,
SkFixed nextNextY 
)
static

Definition at line 1321 of file SkScan_AAAPath.cpp.

1321 {
1322 if (edge->fNext->fNext && edge->fX + edge->fDX > edge->fNext->fX + edge->fNext->fDX) {
1323 *nextNextY = nextY + (SK_Fixed1 >> SkAnalyticEdge::kDefaultAccuracy);
1324 }
1325}

◆ compute_alpha_above_line()

static void compute_alpha_above_line ( SkAlpha alphas,
SkFixed  l,
SkFixed  r,
SkFixed  dY,
SkAlpha  fullAlpha 
)
static

Definition at line 590 of file SkScan_AAAPath.cpp.

594 {
595 SkASSERT(l <= r);
596 SkASSERT(l >> 16 == 0);
597 int R = SkFixedCeilToInt(r);
598 if (R == 0) {
599 return;
600 } else if (R == 1) {
601 alphas[0] = get_partial_alpha(((R << 17) - l - r) >> 9, fullAlpha);
602 } else {
603 SkFixed first = SK_Fixed1 - l; // horizontal edge length of the left-most triangle
604 SkFixed last = r - ((R - 1) << 16); // horizontal edge length of the right-most triangle
605 SkFixed firstH = SkFixedMul(first, dY); // vertical edge of the left-most triangle
606 alphas[0] = SkFixedMul(first, firstH) >> 9; // triangle alpha
607 SkFixed alpha16 = firstH + (dY >> 1); // rectangle plus triangle
608 for (int i = 1; i < R - 1; ++i) {
609 alphas[i] = alpha16 >> 8;
610 alpha16 += dY;
611 }
612 alphas[R - 1] = fullAlpha - partial_triangle_to_alpha(last, dY);
613 }
614}

◆ compute_alpha_below_line()

static void compute_alpha_below_line ( SkAlpha alphas,
SkFixed  l,
SkFixed  r,
SkFixed  dY,
SkAlpha  fullAlpha 
)
static

Definition at line 617 of file SkScan_AAAPath.cpp.

621 {
622 SkASSERT(l <= r);
623 SkASSERT(l >> 16 == 0);
624 int R = SkFixedCeilToInt(r);
625 if (R == 0) {
626 return;
627 } else if (R == 1) {
628 alphas[0] = get_partial_alpha(trapezoid_to_alpha(l, r), fullAlpha);
629 } else {
630 SkFixed first = SK_Fixed1 - l; // horizontal edge length of the left-most triangle
631 SkFixed last = r - ((R - 1) << 16); // horizontal edge length of the right-most triangle
632 SkFixed lastH = SkFixedMul(last, dY); // vertical edge of the right-most triangle
633 alphas[R - 1] = SkFixedMul(last, lastH) >> 9; // triangle alpha
634 SkFixed alpha16 = lastH + (dY >> 1); // rectangle plus triangle
635 for (int i = R - 2; i > 0; i--) {
636 alphas[i] = (alpha16 >> 8) & 0xFF;
637 alpha16 += dY;
638 }
639 alphas[0] = fullAlpha - partial_triangle_to_alpha(first, dY);
640 }
641}

◆ edges_too_close() [1/2]

static bool edges_too_close ( int  prevRite,
SkFixed  ul,
SkFixed  ll 
)
static

Definition at line 1405 of file SkScan_AAAPath.cpp.

1405 {
1406 return prevRite > SkFixedFloorToInt(ul) || prevRite > SkFixedFloorToInt(ll);
1407}

◆ edges_too_close() [2/2]

static bool edges_too_close ( SkAnalyticEdge prev,
SkAnalyticEdge next,
SkFixed  lowerY 
)
static

Definition at line 1384 of file SkScan_AAAPath.cpp.

1384 {
1385 // When next->fDX == 0, prev->fX >= next->fX - SkAbs32(next->fDX) would be false
1386 // even if prev->fX and next->fX are close and within one pixel (e.g., prev->fX == 0.1,
1387 // next->fX == 0.9). Adding SLACK = 1 to the formula would guarantee it to be true if two
1388 // edges prev and next are within one pixel.
1389 constexpr SkFixed SLACK = SK_Fixed1;
1390
1391 // Note that even if the following test failed, the edges might still be very close to each
1392 // other at some point within the current pixel row because of prev->fDX and next->fDX.
1393 // However, to handle that case, we have to sacrafice more performance.
1394 // I think the current quality is good enough (mainly by looking at Nebraska-StateSeal.svg)
1395 // so I'll ignore fDX for performance tradeoff.
1396 return next && prev && next->fUpperY < lowerY &&
1397 prev->fX + SLACK >= next->fX - SkAbs32(next->fDX);
1398 // The following is more accurate but also slower.
1399 // return (prev && prev->fPrev && next && next->fNext != nullptr && next->fUpperY < lowerY &&
1400 // prev->fX + SkAbs32(prev->fDX) + SLACK >= next->fX - SkAbs32(next->fDX));
1401}
static float prev(float f)
static int32_t SkAbs32(int32_t value)
Definition: SkSafe32.h:41

◆ fixed_to_alpha()

static SkAlpha fixed_to_alpha ( SkFixed  f)
static

Definition at line 572 of file SkScan_AAAPath.cpp.

572 {
573 SkASSERT(f <= SK_Fixed1);
574 return get_partial_alpha(0xFF, f);
575}

◆ get_partial_alpha() [1/2]

static SkAlpha get_partial_alpha ( SkAlpha  alpha,
SkAlpha  fullAlpha 
)
static

Definition at line 565 of file SkScan_AAAPath.cpp.

565 {
566 return (alpha * fullAlpha) >> 8;
567}

◆ get_partial_alpha() [2/2]

static SkAlpha get_partial_alpha ( SkAlpha  alpha,
SkFixed  partialHeight 
)
static

Definition at line 561 of file SkScan_AAAPath.cpp.

561 {
562 return SkToU8(SkFixedRoundToInt(alpha * partialHeight));
563}
#define SkFixedRoundToInt(x)
Definition: SkFixed.h:76
constexpr uint8_t SkToU8(S x)
Definition: SkTo.h:22

◆ insert_new_edges()

static void insert_new_edges ( SkAnalyticEdge newEdge,
SkFixed  y,
SkFixed nextNextY 
)
static

Definition at line 1327 of file SkScan_AAAPath.cpp.

1327 {
1328 if (newEdge->fUpperY > y) {
1329 update_next_next_y(newEdge->fUpperY, y, nextNextY);
1330 return;
1331 }
1332 SkAnalyticEdge* prev = newEdge->fPrev;
1333 if (prev->fX <= newEdge->fX) {
1334 while (newEdge->fUpperY <= y) {
1335 check_intersection(newEdge, y, nextNextY);
1336 update_next_next_y(newEdge->fLowerY, y, nextNextY);
1337 newEdge = newEdge->fNext;
1338 }
1339 update_next_next_y(newEdge->fUpperY, y, nextNextY);
1340 return;
1341 }
1342 // find first x pos to insert
1344 // insert the lot, fixing up the links as we go
1345 do {
1346 SkAnalyticEdge* next = newEdge->fNext;
1347 do {
1348 if (start->fNext == newEdge) {
1349 goto nextEdge;
1350 }
1351 SkAnalyticEdge* after = start->fNext;
1352 if (after->fX >= newEdge->fX) {
1353 break;
1354 }
1355 SkASSERT(start != after);
1356 start = after;
1357 } while (true);
1358 remove_edge(newEdge);
1359 insert_edge_after(newEdge, start);
1360 nextEdge:
1361 check_intersection(newEdge, y, nextNextY);
1362 check_intersection_fwd(newEdge, y, nextNextY);
1363 update_next_next_y(newEdge->fLowerY, y, nextNextY);
1364 start = newEdge;
1365 newEdge = next;
1366 } while (newEdge->fUpperY <= y);
1367 update_next_next_y(newEdge->fUpperY, y, nextNextY);
1368}
static void insert_edge_after(EdgeType *edge, EdgeType *afterMe)
Definition: SkScanPriv.h:51
EdgeType * backward_insert_start(EdgeType *prev, SkFixed x)
Definition: SkScanPriv.h:76
static void check_intersection_fwd(const SkAnalyticEdge *edge, SkFixed nextY, SkFixed *nextNextY)

◆ is_smooth_enough() [1/2]

static bool is_smooth_enough ( SkAnalyticEdge leftE,
SkAnalyticEdge riteE,
SkAnalyticEdge currE,
int  stop_y 
)
static

Definition at line 1017 of file SkScan_AAAPath.cpp.

1020 {
1021 if (currE->fUpperY >= SkLeftShift(stop_y, 16)) {
1022 return false; // We're at the end so we won't skip anything
1023 }
1024 if (leftE->fLowerY + SK_Fixed1 < riteE->fLowerY) {
1025 return is_smooth_enough(leftE, currE, stop_y); // Only leftE is changing
1026 } else if (leftE->fLowerY > riteE->fLowerY + SK_Fixed1) {
1027 return is_smooth_enough(riteE, currE, stop_y); // Only riteE is changing
1028 }
1029
1030 // Now both edges are changing, find the second next edge
1031 SkAnalyticEdge* nextCurrE = currE->fNext;
1032 if (nextCurrE->fUpperY >= stop_y << 16) { // Check if we're at the end
1033 return false;
1034 }
1035 // Ensure that currE is the next left edge and nextCurrE is the next right edge. Swap if not.
1036 if (nextCurrE->fUpperX < currE->fUpperX) {
1037 std::swap(currE, nextCurrE);
1038 }
1039 return is_smooth_enough(leftE, currE, stop_y) && is_smooth_enough(riteE, nextCurrE, stop_y);
1040}
static constexpr int32_t SkLeftShift(int32_t value, int32_t shift)
Definition: SkMath.h:37

◆ is_smooth_enough() [2/2]

static bool is_smooth_enough ( SkAnalyticEdge thisEdge,
SkAnalyticEdge nextEdge,
int  stop_y 
)
static

Definition at line 996 of file SkScan_AAAPath.cpp.

996 {
997 if (thisEdge->fCurveCount < 0) {
998 const SkCubicEdge& cEdge = static_cast<SkAnalyticCubicEdge*>(thisEdge)->fCEdge;
999 int ddshift = cEdge.fCurveShift;
1000 return SkAbs32(cEdge.fCDx) >> 1 >= SkAbs32(cEdge.fCDDx) >> ddshift &&
1001 SkAbs32(cEdge.fCDy) >> 1 >= SkAbs32(cEdge.fCDDy) >> ddshift &&
1002 // current Dy is (fCDy - (fCDDy >> ddshift)) >> dshift
1003 (cEdge.fCDy - (cEdge.fCDDy >> ddshift)) >> cEdge.fCubicDShift >= SK_Fixed1;
1004 } else if (thisEdge->fCurveCount > 0) {
1005 const SkQuadraticEdge& qEdge = static_cast<SkAnalyticQuadraticEdge*>(thisEdge)->fQEdge;
1006 return SkAbs32(qEdge.fQDx) >> 1 >= SkAbs32(qEdge.fQDDx) &&
1007 SkAbs32(qEdge.fQDy) >> 1 >= SkAbs32(qEdge.fQDDy) &&
1008 // current Dy is (fQDy - fQDDy) >> shift
1009 (qEdge.fQDy - qEdge.fQDDy) >> qEdge.fCurveShift >= SK_Fixed1;
1010 }
1011 return SkAbs32(nextEdge->fDX - thisEdge->fDX) <= SK_Fixed1 && // DDx should be small
1012 nextEdge->fLowerY - nextEdge->fUpperY >= SK_Fixed1; // Dy should be large
1013}
SkFixed fCDDy
Definition: SkEdge.h:85
SkFixed fCDx
Definition: SkEdge.h:84
SkFixed fCDy
Definition: SkEdge.h:84
SkFixed fCDDx
Definition: SkEdge.h:85
uint8_t fCurveShift
Definition: SkEdge.h:43
SkFixed fQDx
Definition: SkEdge.h:73
SkFixed fQDDx
Definition: SkEdge.h:74
SkFixed fQDy
Definition: SkEdge.h:73
SkFixed fQDDy
Definition: SkEdge.h:74

◆ operator<()

static bool operator< ( const SkAnalyticEdge a,
const SkAnalyticEdge b 
)
static

Definition at line 949 of file SkScan_AAAPath.cpp.

949 {
950 int valuea = a.fUpperY;
951 int valueb = b.fUpperY;
952
953 if (valuea == valueb) {
954 valuea = a.fX;
955 valueb = b.fX;
956 }
957
958 if (valuea == valueb) {
959 valuea = a.fDX;
960 valueb = b.fDX;
961 }
962
963 return valuea < valueb;
964}
static bool b
struct MyStruct a[10]

◆ partial_triangle_to_alpha()

static SkAlpha partial_triangle_to_alpha ( SkFixed  a,
SkFixed  b 
)
static

Definition at line 542 of file SkScan_AAAPath.cpp.

542 {
543 SkASSERT(a <= SK_Fixed1);
544#if 0
545 // TODO(mtklein): skia:8877
546 SkASSERT(b <= SK_Fixed1);
547#endif
548
549 // Approximating...
550 // SkFixed area = SkFixedMul(a, SkFixedMul(a,b)) / 2;
551 SkFixed area = (a >> 11) * (a >> 11) * (b >> 11);
552
553#if 0
554 // TODO(mtklein): skia:8877
555 return SkTo<SkAlpha>(area >> 8);
556#else
557 return SkTo<SkAlpha>((area >> 8) & 0xFF);
558#endif
559}

◆ safely_add_alpha()

static void safely_add_alpha ( SkAlpha alpha,
SkAlpha  delta 
)
static

Definition at line 96 of file SkScan_AAAPath.cpp.

96 {
97 *alpha = std::min(0xFF, *alpha + delta);
98}

◆ sort_edges()

static SkAnalyticEdge * sort_edges ( SkAnalyticEdge list[],
int  count,
SkAnalyticEdge **  last 
)
static

Definition at line 966 of file SkScan_AAAPath.cpp.

966 {
967 SkTQSort(list, list + count);
968
969 // now make the edges linked in sorted order
970 for (int i = 1; i < count; ++i) {
971 list[i - 1]->fNext = list[i];
972 list[i]->fPrev = list[i - 1];
973 }
974
975 *last = list[count - 1];
976 return list[0];
977}
void SkTQSort(T *begin, T *end, const C &lessThan)
Definition: SkTSort.h:194

◆ trapezoid_to_alpha()

static SkAlpha trapezoid_to_alpha ( SkFixed  l1,
SkFixed  l2 
)
static

Definition at line 535 of file SkScan_AAAPath.cpp.

535 {
536 SkASSERT(l1 >= 0 && l2 >= 0);
537 SkFixed area = (l1 + l2) / 2;
538 return SkTo<SkAlpha>(area >> 8);
539}

◆ try_blit_fat_anti_rect()

static bool try_blit_fat_anti_rect ( SkBlitter blitter,
const SkPath path,
const SkIRect clip 
)
inlinestatic

Definition at line 1710 of file SkScan_AAAPath.cpp.

1712 {
1713 SkRect rect;
1714 if (!path.isRect(&rect)) {
1715 return false; // not rect
1716 }
1717 if (!rect.intersect(SkRect::Make(clip))) {
1718 return true; // The intersection is empty. Hence consider it done.
1719 }
1720 SkIRect bounds = rect.roundOut();
1721 if (bounds.width() < 3) {
1722 return false; // not fat
1723 }
1724 blitter->blitFatAntiRect(rect);
1725 return true;
1726}
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
void blitFatAntiRect(const SkRect &rect)
Definition: SkBlitter.cpp:67
Optional< SkRect > bounds
Definition: SkRecords.h:189
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669

◆ update_next_next_y()

static void update_next_next_y ( SkFixed  y,
SkFixed  nextY,
SkFixed nextNextY 
)
static

Definition at line 1311 of file SkScan_AAAPath.cpp.

1311 {
1312 *nextNextY = y > nextY && y < *nextNextY ? y : *nextNextY;
1313}

◆ validate_edges_for_y()

static void validate_edges_for_y ( const SkAnalyticEdge edge,
SkFixed  y 
)
static

Definition at line 1370 of file SkScan_AAAPath.cpp.

1370 {
1371#ifdef SK_DEBUG
1372 while (edge->fUpperY <= y) {
1373 SkASSERT(edge->fPrev && edge->fNext);
1374 SkASSERT(edge->fPrev->fNext == edge);
1375 SkASSERT(edge->fNext->fPrev == edge);
1376 SkASSERT(edge->fUpperY <= edge->fLowerY);
1377 SkASSERT(edge->fPrev->fPrev == nullptr || edge->fPrev->fX <= edge->fX);
1378 edge = edge->fNext;
1379 }
1380#endif
1381}

◆ validate_sort()

static void validate_sort ( const SkAnalyticEdge edge)
static

Definition at line 979 of file SkScan_AAAPath.cpp.

979 {
980#ifdef SK_DEBUG
981 SkFixed y = SkIntToFixed(-32768);
982
983 while (edge->fUpperY != SK_MaxS32) {
984 edge->validate();
985 SkASSERT(y <= edge->fUpperY);
986
987 y = edge->fUpperY;
988 edge = (SkAnalyticEdge*)edge->fNext;
989 }
990#endif
991}