| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkScanPriv.h" | 8 #include "SkScanPriv.h" |
| 9 #include "SkBlitter.h" | 9 #include "SkBlitter.h" |
| 10 #include "SkEdge.h" | 10 #include "SkEdge.h" |
| 11 #include "SkEdgeBuilder.h" | 11 #include "SkEdgeBuilder.h" |
| 12 #include "SkGeometry.h" | 12 #include "SkGeometry.h" |
| 13 #include "SkPath.h" | 13 #include "SkPath.h" |
| 14 #include "SkQuadClipper.h" | 14 #include "SkQuadClipper.h" |
| 15 #include "SkRasterClip.h" | 15 #include "SkRasterClip.h" |
| 16 #include "SkRegion.h" | 16 #include "SkRegion.h" |
| 17 #include "SkStroke.h" |
| 17 #include "SkTemplates.h" | 18 #include "SkTemplates.h" |
| 18 #include "SkTSort.h" | 19 #include "SkTSort.h" |
| 19 | 20 |
| 21 #include <stdio.h> // FIXME |
| 22 |
| 23 static bool dumping; |
| 24 |
| 20 #define kEDGE_HEAD_Y SK_MinS32 | 25 #define kEDGE_HEAD_Y SK_MinS32 |
| 21 #define kEDGE_TAIL_Y SK_MaxS32 | 26 #define kEDGE_TAIL_Y SK_MaxS32 |
| 22 | 27 |
| 23 #ifdef SK_DEBUG | 28 #ifdef SK_DEBUG |
| 24 static void validate_sort(const SkEdge* edge) { | 29 static void validate_sort(const SkEdge* edge) { |
| 25 int y = kEDGE_HEAD_Y; | 30 int y = kEDGE_HEAD_Y; |
| 26 | 31 |
| 27 while (edge->fFirstY != SK_MaxS32) { | 32 while (edge->fFirstY != SK_MaxS32) { |
| 28 edge->validate(); | 33 edge->validate(); |
| 29 SkASSERT(y <= edge->fFirstY); | 34 SkASSERT(y <= edge->fFirstY); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 41 edge->fNext->fPrev = edge->fPrev; | 46 edge->fNext->fPrev = edge->fPrev; |
| 42 } | 47 } |
| 43 | 48 |
| 44 static inline void insert_edge_after(SkEdge* edge, SkEdge* afterMe) { | 49 static inline void insert_edge_after(SkEdge* edge, SkEdge* afterMe) { |
| 45 edge->fPrev = afterMe; | 50 edge->fPrev = afterMe; |
| 46 edge->fNext = afterMe->fNext; | 51 edge->fNext = afterMe->fNext; |
| 47 afterMe->fNext->fPrev = edge; | 52 afterMe->fNext->fPrev = edge; |
| 48 afterMe->fNext = edge; | 53 afterMe->fNext = edge; |
| 49 } | 54 } |
| 50 | 55 |
| 56 static void emit_wireframe_triangle(SkPoint t[3], SkTDArray<SkPoint>* points) { |
| 57 SkPoint *p = points->append(6); |
| 58 p[0] = t[0]; |
| 59 p[1] = t[1]; |
| 60 p[2] = t[1]; |
| 61 p[3] = t[2]; |
| 62 p[4] = t[2]; |
| 63 p[5] = t[0]; |
| 64 } |
| 65 |
| 66 static void emit_trapezoid(SkEdge* left, SkEdge* right, float top, float bottom,
SkTDArray<SkPoint>* points) |
| 67 { |
| 68 // If this edge was already neutered by its partner, don't emit. |
| 69 if (top > bottom) { |
| 70 return; |
| 71 } |
| 72 |
| 73 if (!left || !right) { |
| 74 return; |
| 75 } |
| 76 |
| 77 float top_left = left->fFirstXf; |
| 78 float top_right = right->fFirstXf; |
| 79 float bottom_left = left->fFirstXf + SkFixedToFloat(left->fDX * (bottom - to
p)); |
| 80 float bottom_right = right->fFirstXf + SkFixedToFloat(right->fDX * (bottom -
top)); |
| 81 if (dumping) { |
| 82 printf("top %g bot %g tl %g tr %g bl %g br %g\n", |
| 83 top, bottom, left->fFirstXf, right->fFirstXf, bottom_left, bottom
_right); |
| 84 } |
| 85 if (SkScan::gWireframe) { |
| 86 if (top_left == top_right) { |
| 87 SkPoint p[3]; |
| 88 p[0] = SkPoint::Make(top_right, top); |
| 89 p[1] = SkPoint::Make(bottom_right, bottom); |
| 90 p[2] = SkPoint::Make(bottom_left , bottom); |
| 91 emit_wireframe_triangle(p, points); |
| 92 } else if (bottom_left == bottom_right) { |
| 93 SkPoint p[3]; |
| 94 p[0] = SkPoint::Make(top_left, top); |
| 95 p[1] = SkPoint::Make(top_right, top); |
| 96 p[2] = SkPoint::Make(bottom_left, bottom); |
| 97 emit_wireframe_triangle(p, points); |
| 98 } else { |
| 99 SkPoint p[3]; |
| 100 p[0] = SkPoint::Make(top_left, top); |
| 101 p[1] = SkPoint::Make(top_right, top); |
| 102 p[2] = SkPoint::Make(bottom_left , bottom); |
| 103 emit_wireframe_triangle(p, points); |
| 104 p[0] = SkPoint::Make(top_right, top); |
| 105 p[1] = SkPoint::Make(bottom_right, bottom); |
| 106 p[2] = SkPoint::Make(bottom_left , bottom); |
| 107 emit_wireframe_triangle(p, points); |
| 108 } |
| 109 } else { |
| 110 if (top_left == top_right) { |
| 111 SkPoint *p = points->append(3); |
| 112 p[0] = SkPoint::Make(top_right, top); |
| 113 p[1] = SkPoint::Make(bottom_right, bottom); |
| 114 p[2] = SkPoint::Make(bottom_left , bottom); |
| 115 } else if (bottom_left == bottom_right) { |
| 116 SkPoint *p = points->append(3); |
| 117 p[0] = SkPoint::Make(top_left, top); |
| 118 p[1] = SkPoint::Make(top_right, top); |
| 119 p[2] = SkPoint::Make(bottom_left, bottom); |
| 120 } else { |
| 121 SkPoint *p = points->append(6); |
| 122 p[0] = SkPoint::Make(top_left, top); |
| 123 p[1] = SkPoint::Make(top_right, top); |
| 124 p[2] = SkPoint::Make(bottom_left , bottom); |
| 125 p[3] = SkPoint::Make(top_right, top); |
| 126 p[4] = SkPoint::Make(bottom_right, bottom); |
| 127 p[5] = SkPoint::Make(bottom_left , bottom); |
| 128 } |
| 129 } |
| 130 left->fFirstXf = bottom_left; |
| 131 left->fFirstYf = bottom; |
| 132 right->fFirstXf = bottom_right; |
| 133 right->fFirstYf = bottom; |
| 134 } |
| 135 |
| 136 static void emit_all_trapezoids(SkEdge* start, int windingMask, int curr_y, SkTD
Array<SkPoint>* points) |
| 137 { |
| 138 int w = 0; |
| 139 SkEdge* left = NULL; |
| 140 for (SkEdge* edge = start; edge != NULL && edge->fFirstY < curr_y && edge->f
FirstYf < curr_y; edge = edge->fNext) { |
| 141 w += edge->fWinding; |
| 142 if ((w & windingMask) == 0) { |
| 143 SkASSERT(left); |
| 144 emit_trapezoid(left, edge, left->fFirstYf, curr_y, points); |
| 145 left = NULL; |
| 146 } else if (!left) { |
| 147 left = edge; |
| 148 } else { |
| 149 edge->fFirstXf += SkFixedToFloat(edge->fDX * (curr_y - edge->fFirstY
f)); |
| 150 edge->fFirstYf = (float) curr_y; |
| 151 } |
| 152 } |
| 153 } |
| 154 |
| 51 static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, cur
r_y)) { | 155 static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, cur
r_y)) { |
| 52 SkFixed x = edge->fX; | 156 SkFixed x = edge->fX; |
| 53 | 157 |
| 54 SkEdge* prev = edge->fPrev; | 158 SkEdge* prev = edge->fPrev; |
| 55 while (prev->fX > x) { | 159 while (prev->fX > x) { |
| 56 prev = prev->fPrev; | 160 prev = prev->fPrev; |
| 57 } | 161 } |
| 58 if (prev->fNext != edge) { | 162 if (prev->fNext != edge) { |
| 59 remove_edge(edge); | 163 remove_edge(edge); |
| 60 insert_edge_after(edge, prev); | 164 insert_edge_after(edge, prev); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 90 #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used
without having been initialized | 194 #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used
without having been initialized |
| 91 #pragma warning ( push ) | 195 #pragma warning ( push ) |
| 92 #pragma warning ( disable : 4701 ) | 196 #pragma warning ( disable : 4701 ) |
| 93 #endif | 197 #endif |
| 94 | 198 |
| 95 typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); | 199 typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); |
| 96 #define PREPOST_START true | 200 #define PREPOST_START true |
| 97 #define PREPOST_END false | 201 #define PREPOST_END false |
| 98 | 202 |
| 99 static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, | 203 static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, |
| 100 SkBlitter* blitter, int start_y, int stop_y, | 204 SkBlitter* blitter, SkTDArray<SkPoint>* points, |
| 101 PrePostProc proc, int rightClip) { | 205 int start_y, int stop_y, PrePostProc proc, int rightClip)
{ |
| 102 validate_sort(prevHead->fNext); | 206 validate_sort(prevHead->fNext); |
| 103 | 207 |
| 104 int curr_y = start_y; | 208 int curr_y = start_y; |
| 105 // returns 1 for evenodd, -1 for winding, regardless of inverse-ness | 209 // returns 1 for evenodd, -1 for winding, regardless of inverse-ness |
| 106 int windingMask = (fillType & 1) ? 1 : -1; | 210 int windingMask = (fillType & 1) ? 1 : -1; |
| 107 | 211 |
| 108 for (;;) { | 212 for (;;) { |
| 109 int w = 0; | 213 int w = 0; |
| 110 int left SK_INIT_TO_AVOID_WARNING; | 214 int left SK_INIT_TO_AVOID_WARNING; |
| 111 bool in_interval = false; | 215 bool in_interval = false; |
| 112 SkEdge* currE = prevHead->fNext; | 216 SkEdge* currE = prevHead->fNext; |
| 113 SkFixed prevX = prevHead->fX; | 217 SkFixed prevX = prevHead->fX; |
| 114 | 218 |
| 115 validate_edges_for_y(currE, curr_y); | 219 validate_edges_for_y(currE, curr_y); |
| 116 | 220 |
| 117 if (proc) { | 221 if (proc && blitter) { |
| 118 proc(blitter, curr_y, PREPOST_START); // pre-proc | 222 proc(blitter, curr_y, PREPOST_START); // pre-proc |
| 119 } | 223 } |
| 120 | 224 |
| 121 while (currE->fFirstY <= curr_y) { | 225 while (currE->fFirstY <= curr_y) { |
| 122 SkASSERT(currE->fLastY >= curr_y); | 226 SkASSERT(currE->fLastY >= curr_y); |
| 123 | 227 |
| 124 int x = SkFixedRoundToInt(currE->fX); | 228 int x = SkFixedRoundToInt(currE->fX); |
| 125 w += currE->fWinding; | 229 w += currE->fWinding; |
| 126 if ((w & windingMask) == 0) { // we finished an interval | 230 if ((w & windingMask) == 0) { // we finished an interval |
| 127 SkASSERT(in_interval); | 231 SkASSERT(in_interval); |
| 128 int width = x - left; | 232 int width = x - left; |
| 129 SkASSERT(width >= 0); | 233 SkASSERT(width >= 0); |
| 130 if (width) | 234 if (width) { |
| 131 blitter->blitH(left, curr_y, width); | 235 if (blitter) { |
| 236 blitter->blitH(left, curr_y, width); |
| 237 } |
| 238 } |
| 132 in_interval = false; | 239 in_interval = false; |
| 133 } else if (!in_interval) { | 240 } else if (!in_interval) { |
| 134 left = x; | 241 left = x; |
| 135 in_interval = true; | 242 in_interval = true; |
| 136 } | 243 } |
| 137 | 244 |
| 138 SkEdge* next = currE->fNext; | 245 SkEdge* next = currE->fNext; |
| 139 SkFixed newX; | 246 SkFixed newX; |
| 140 | 247 |
| 141 if (currE->fLastY == curr_y) { // are we done with this edge? | 248 if (currE->fLastY == curr_y) { // are we done with this edge? |
| 249 if (points) emit_all_trapezoids(prevHead->fNext, windingMask, cu
rr_y + 1, points); |
| 142 if (currE->fCurveCount < 0) { | 250 if (currE->fCurveCount < 0) { |
| 143 if (((SkCubicEdge*)currE)->updateCubic()) { | 251 if (((SkCubicEdge*)currE)->updateCubic()) { |
| 144 SkASSERT(currE->fFirstY == curr_y + 1); | 252 SkASSERT(currE->fFirstY == curr_y + 1); |
| 145 | 253 |
| 146 newX = currE->fX; | 254 newX = currE->fX; |
| 147 goto NEXT_X; | 255 goto NEXT_X; |
| 148 } | 256 } |
| 149 } else if (currE->fCurveCount > 0) { | 257 } else if (currE->fCurveCount > 0) { |
| 150 if (((SkQuadraticEdge*)currE)->updateQuadratic()) { | 258 if (((SkQuadraticEdge*)currE)->updateQuadratic()) { |
| 151 newX = currE->fX; | 259 newX = currE->fX; |
| 152 goto NEXT_X; | 260 goto NEXT_X; |
| 153 } | 261 } |
| 154 } | 262 } |
| 155 remove_edge(currE); | 263 remove_edge(currE); |
| 156 } else { | 264 } else { |
| 157 SkASSERT(currE->fLastY > curr_y); | 265 SkASSERT(currE->fLastY > curr_y); |
| 158 newX = currE->fX + currE->fDX; | 266 newX = currE->fX + currE->fDX; |
| 159 currE->fX = newX; | 267 currE->fX = newX; |
| 160 NEXT_X: | 268 NEXT_X: |
| 161 if (newX < prevX) { // ripple currE backwards until it is x-sort
ed | 269 if (newX < prevX) { // ripple currE backwards until it is x-sort
ed |
| 270 if (points) emit_all_trapezoids(prevHead->fNext, windingMask
, curr_y + 1, points); |
| 162 backward_insert_edge_based_on_x(currE SkPARAM(curr_y)); | 271 backward_insert_edge_based_on_x(currE SkPARAM(curr_y)); |
| 163 } else { | 272 } else { |
| 164 prevX = newX; | 273 prevX = newX; |
| 165 } | 274 } |
| 166 } | 275 } |
| 167 currE = next; | 276 currE = next; |
| 168 SkASSERT(currE); | 277 SkASSERT(currE); |
| 169 } | 278 } |
| 170 | 279 |
| 171 // was our right-edge culled away? | 280 // was our right-edge culled away? |
| 172 if (in_interval) { | 281 if (in_interval && blitter) { |
| 173 int width = rightClip - left; | 282 int width = rightClip - left; |
| 174 if (width > 0) { | 283 if (width > 0) { |
| 175 blitter->blitH(left, curr_y, width); | 284 blitter->blitH(left, curr_y, width); |
| 176 } | 285 } |
| 177 } | 286 } |
| 178 | 287 |
| 179 if (proc) { | 288 if (proc && blitter) { |
| 180 proc(blitter, curr_y, PREPOST_END); // post-proc | 289 proc(blitter, curr_y, PREPOST_END); // post-proc |
| 181 } | 290 } |
| 182 | 291 |
| 183 curr_y += 1; | 292 curr_y += 1; |
| 184 if (curr_y >= stop_y) { | 293 if (curr_y >= stop_y) { |
| 185 break; | 294 break; |
| 186 } | 295 } |
| 296 if (points && currE->fFirstY == curr_y) { |
| 297 emit_all_trapezoids(prevHead->fNext, windingMask, curr_y, points); |
| 298 } |
| 187 // now currE points to the first edge with a Yint larger than curr_y | 299 // now currE points to the first edge with a Yint larger than curr_y |
| 188 insert_new_edges(currE, curr_y); | 300 insert_new_edges(currE, curr_y); |
| 189 } | 301 } |
| 190 } | 302 } |
| 191 | 303 |
| 192 // return true if we're done with this edge | 304 // return true if we're done with this edge |
| 193 static bool update_edge(SkEdge* edge, int last_y) { | 305 static bool update_edge(SkEdge* edge, int last_y) { |
| 194 SkASSERT(edge->fLastY >= last_y); | 306 SkASSERT(edge->fLastY >= last_y); |
| 195 if (last_y == edge->fLastY) { | 307 if (last_y == edge->fLastY) { |
| 196 if (edge->fCurveCount < 0) { | 308 if (edge->fCurveCount < 0) { |
| 197 if (((SkCubicEdge*)edge)->updateCubic()) { | 309 if (((SkCubicEdge*)edge)->updateCubic()) { |
| 198 SkASSERT(edge->fFirstY == last_y + 1); | 310 SkASSERT(edge->fFirstY == last_y + 1); |
| 199 return false; | 311 return false; |
| 200 } | 312 } |
| 201 } else if (edge->fCurveCount > 0) { | 313 } else if (edge->fCurveCount > 0) { |
| 202 if (((SkQuadraticEdge*)edge)->updateQuadratic()) { | 314 if (((SkQuadraticEdge*)edge)->updateQuadratic()) { |
| 203 SkASSERT(edge->fFirstY == last_y + 1); | 315 SkASSERT(edge->fFirstY == last_y + 1); |
| 204 return false; | 316 return false; |
| 205 } | 317 } |
| 206 } | 318 } |
| 207 return true; | 319 return true; |
| 208 } | 320 } |
| 209 return false; | 321 return false; |
| 210 } | 322 } |
| 211 | 323 |
| 212 static void walk_convex_edges(SkEdge* prevHead, SkPath::FillType, | 324 static void walk_convex_edges(SkEdge* prevHead, SkPath::FillType, |
| 213 SkBlitter* blitter, int start_y, int stop_y, | 325 SkBlitter* blitter, SkTDArray<SkPoint>* points, |
| 326 int start_y, int stop_y, |
| 214 PrePostProc proc) { | 327 PrePostProc proc) { |
| 215 validate_sort(prevHead->fNext); | 328 validate_sort(prevHead->fNext); |
| 216 | 329 |
| 217 SkEdge* leftE = prevHead->fNext; | 330 SkEdge* leftE = prevHead->fNext; |
| 218 SkEdge* riteE = leftE->fNext; | 331 SkEdge* riteE = leftE->fNext; |
| 219 SkEdge* currE = riteE->fNext; | 332 SkEdge* currE = riteE->fNext; |
| 220 | 333 |
| 221 #if 0 | 334 #if 0 |
| 222 int local_top = leftE->fFirstY; | 335 int local_top = leftE->fFirstY; |
| 223 SkASSERT(local_top == riteE->fFirstY); | 336 SkASSERT(local_top == riteE->fFirstY); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 240 int local_bot = SkMin32(leftE->fLastY, riteE->fLastY); | 353 int local_bot = SkMin32(leftE->fLastY, riteE->fLastY); |
| 241 local_bot = SkMin32(local_bot, stop_y - 1); | 354 local_bot = SkMin32(local_bot, stop_y - 1); |
| 242 SkASSERT(local_top <= local_bot); | 355 SkASSERT(local_top <= local_bot); |
| 243 | 356 |
| 244 SkFixed left = leftE->fX; | 357 SkFixed left = leftE->fX; |
| 245 SkFixed dLeft = leftE->fDX; | 358 SkFixed dLeft = leftE->fDX; |
| 246 SkFixed rite = riteE->fX; | 359 SkFixed rite = riteE->fX; |
| 247 SkFixed dRite = riteE->fDX; | 360 SkFixed dRite = riteE->fDX; |
| 248 int count = local_bot - local_top; | 361 int count = local_bot - local_top; |
| 249 SkASSERT(count >= 0); | 362 SkASSERT(count >= 0); |
| 250 if (0 == (dLeft | dRite)) { | 363 if (points) { |
| 364 emit_trapezoid(leftE, riteE, (float) local_top, (float) (local_bot +
1), points); |
| 365 if (left < rite) { |
| 366 count += 1; |
| 367 left += count * dLeft; |
| 368 rite += count * dRite; |
| 369 } |
| 370 local_top = local_bot + 1; |
| 371 } else if (0 == (dLeft | dRite)) { |
| 251 int L = SkFixedRoundToInt(left); | 372 int L = SkFixedRoundToInt(left); |
| 252 int R = SkFixedRoundToInt(rite); | 373 int R = SkFixedRoundToInt(rite); |
| 253 if (L < R) { | 374 if (L < R) { |
| 254 count += 1; | 375 count += 1; |
| 255 blitter->blitRect(L, local_top, R - L, count); | 376 blitter->blitRect(L, local_top, R - L, count); |
| 377 left += count * dLeft; |
| 378 rite += count * dRite; |
| 256 } | 379 } |
| 257 local_top = local_bot + 1; | 380 local_top = local_bot + 1; |
| 258 } else { | 381 } else { |
| 259 do { | 382 do { |
| 260 int L = SkFixedRoundToInt(left); | 383 int L = SkFixedRoundToInt(left); |
| 261 int R = SkFixedRoundToInt(rite); | 384 int R = SkFixedRoundToInt(rite); |
| 262 if (L < R) { | 385 if (L < R) { |
| 263 blitter->blitH(L, local_top, R - L); | 386 blitter->blitH(L, local_top, R - L); |
| 264 } | 387 } |
| 265 left += dLeft; | 388 left += dLeft; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 | 510 |
| 388 *last = list[count - 1]; | 511 *last = list[count - 1]; |
| 389 return list[0]; | 512 return list[0]; |
| 390 } | 513 } |
| 391 | 514 |
| 392 // clipRect may be null, even though we always have a clip. This indicates that | 515 // clipRect may be null, even though we always have a clip. This indicates that |
| 393 // the path is contained in the clip, and so we can ignore it during the blit | 516 // the path is contained in the clip, and so we can ignore it during the blit |
| 394 // | 517 // |
| 395 // clipRect (if no null) has already been shifted up | 518 // clipRect (if no null) has already been shifted up |
| 396 // | 519 // |
| 397 void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte
r, | 520 void sk_fill_path(const SkPath& path, const SkIRect* clipRect, |
| 398 int start_y, int stop_y, int shiftEdgesUp, const SkRegion& cli
pRgn) { | 521 SkBlitter* blitter, SkTDArray<SkPoint>* points, |
| 399 SkASSERT(blitter); | 522 int start_y, int stop_y, int shiftEdgesUp, |
| 523 const SkRegion& clipRgn) { |
| 524 SkASSERT(blitter || points); |
| 400 | 525 |
| 401 SkEdgeBuilder builder; | 526 SkEdgeBuilder builder; |
| 402 | 527 |
| 403 // If we're convex, then we need both edges, even the right edge is past the
clip | 528 // If we're convex, then we need both edges, even the right edge is past the
clip |
| 404 const bool canCullToTheRight = !path.isConvex(); | 529 const bool canCullToTheRight = !path.isConvex() && !points; |
| 405 | 530 |
| 406 int count = builder.build(path, clipRect, shiftEdgesUp, canCullToTheRight); | 531 int count = builder.build(path, clipRect, shiftEdgesUp, canCullToTheRight); |
| 407 SkASSERT(count >= 0); | 532 SkASSERT(count >= 0); |
| 408 | 533 |
| 409 SkEdge** list = builder.edgeList(); | 534 SkEdge** list = builder.edgeList(); |
| 410 | 535 |
| 411 if (0 == count) { | 536 if (0 == count) { |
| 412 if (path.isInverseFillType()) { | 537 if (path.isInverseFillType()) { |
| 413 /* | 538 /* |
| 414 * Since we are in inverse-fill, our caller has already drawn above | 539 * Since we are in inverse-fill, our caller has already drawn above |
| 415 * our top (start_y) and will draw below our bottom (stop_y). Thus | 540 * our top (start_y) and will draw below our bottom (stop_y). Thus |
| 416 * we need to restrict our drawing to the intersection of the clip | 541 * we need to restrict our drawing to the intersection of the clip |
| 417 * and those two limits. | 542 * and those two limits. |
| 418 */ | 543 */ |
| 419 SkIRect rect = clipRgn.getBounds(); | 544 SkIRect rect = clipRgn.getBounds(); |
| 420 if (rect.fTop < start_y) { | 545 if (rect.fTop < start_y) { |
| 421 rect.fTop = start_y; | 546 rect.fTop = start_y; |
| 422 } | 547 } |
| 423 if (rect.fBottom > stop_y) { | 548 if (rect.fBottom > stop_y) { |
| 424 rect.fBottom = stop_y; | 549 rect.fBottom = stop_y; |
| 425 } | 550 } |
| 426 if (!rect.isEmpty()) { | 551 if (!rect.isEmpty()) { |
| 427 blitter->blitRect(rect.fLeft << shiftEdgesUp, | 552 if (blitter) { |
| 428 rect.fTop << shiftEdgesUp, | 553 blitter->blitRect(rect.fLeft << shiftEdgesUp, |
| 429 rect.width() << shiftEdgesUp, | 554 rect.fTop << shiftEdgesUp, |
| 430 rect.height() << shiftEdgesUp); | 555 rect.width() << shiftEdgesUp, |
| 556 rect.height() << shiftEdgesUp); |
| 557 } else { |
| 558 SkRect r = SkRect::Make(rect); |
| 559 r.toQuad(points->append(4)); |
| 560 } |
| 431 } | 561 } |
| 432 } | 562 } |
| 563 |
| 433 return; | 564 return; |
| 434 } | 565 } |
| 435 | 566 |
| 436 SkEdge headEdge, tailEdge, *last; | 567 SkEdge headEdge, tailEdge, *last; |
| 437 // this returns the first and last edge after they're sorted into a dlink li
st | 568 // this returns the first and last edge after they're sorted into a dlink li
st |
| 438 SkEdge* edge = sort_edges(list, count, &last); | 569 SkEdge* edge = sort_edges(list, count, &last); |
| 570 if (dumping) { |
| 571 printf("sorted into %d edges:\n", count); |
| 572 SkEdge* e = edge; |
| 573 for (int i = 0; i < count; i++) { |
| 574 printf("edge %p fFirstXf %g fFirstYf %g fLastY %d fDX %g\n", e, e->f
FirstXf, e->fFirstYf, e->fLastY, e->fDX / 65536.0); |
| 575 e = e->fNext; |
| 576 } |
| 577 } |
| 439 | 578 |
| 440 headEdge.fPrev = nullptr; | 579 headEdge.fPrev = nullptr; |
| 441 headEdge.fNext = edge; | 580 headEdge.fNext = edge; |
| 442 headEdge.fFirstY = kEDGE_HEAD_Y; | 581 headEdge.fFirstY = kEDGE_HEAD_Y; |
| 443 headEdge.fX = SK_MinS32; | 582 headEdge.fX = SK_MinS32; |
| 444 edge->fPrev = &headEdge; | 583 edge->fPrev = &headEdge; |
| 445 | 584 |
| 446 tailEdge.fPrev = last; | 585 tailEdge.fPrev = last; |
| 447 tailEdge.fNext = nullptr; | 586 tailEdge.fNext = nullptr; |
| 448 tailEdge.fFirstY = kEDGE_TAIL_Y; | 587 tailEdge.fFirstY = kEDGE_TAIL_Y; |
| 449 last->fNext = &tailEdge; | 588 last->fNext = &tailEdge; |
| 450 | 589 |
| 451 // now edge is the head of the sorted linklist | 590 // now edge is the head of the sorted linklist |
| 452 | 591 |
| 453 start_y <<= shiftEdgesUp; | 592 start_y <<= shiftEdgesUp; |
| 454 stop_y <<= shiftEdgesUp; | 593 stop_y <<= shiftEdgesUp; |
| 455 if (clipRect && start_y < clipRect->fTop) { | 594 if (clipRect && start_y < clipRect->fTop) { |
| 456 start_y = clipRect->fTop; | 595 start_y = clipRect->fTop; |
| 457 } | 596 } |
| 458 if (clipRect && stop_y > clipRect->fBottom) { | 597 if (clipRect && stop_y > clipRect->fBottom) { |
| 459 stop_y = clipRect->fBottom; | 598 stop_y = clipRect->fBottom; |
| 460 } | 599 } |
| 461 | 600 |
| 462 InverseBlitter ib; | 601 InverseBlitter ib; |
| 463 PrePostProc proc = nullptr; | 602 PrePostProc proc = nullptr; |
| 464 | 603 |
| 465 if (path.isInverseFillType()) { | 604 if (path.isInverseFillType() && blitter) { |
| 466 ib.setBlitter(blitter, clipRgn.getBounds(), shiftEdgesUp); | 605 ib.setBlitter(blitter, clipRgn.getBounds(), shiftEdgesUp); |
| 467 blitter = &ib; | 606 blitter = &ib; |
| 468 proc = PrePostInverseBlitterProc; | 607 proc = PrePostInverseBlitterProc; |
| 469 } | 608 } |
| 470 | 609 |
| 471 if (path.isConvex() && (nullptr == proc)) { | 610 if (path.isConvex() && (nullptr == proc) && blitter) { |
| 472 SkASSERT(count >= 2); // convex walker does not handle missing right e
dges | 611 SkASSERT(count >= 2); // convex walker does not handle missing right e
dges |
| 473 walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_
y, nullptr); | 612 walk_convex_edges(&headEdge, path.getFillType(), blitter, points, start_
y, stop_y, NULL); |
| 474 } else { | 613 } else { |
| 475 int rightEdge; | 614 int rightEdge; |
| 476 if (clipRect) { | 615 if (clipRect) { |
| 477 rightEdge = clipRect->right(); | 616 rightEdge = clipRect->right(); |
| 478 } else { | 617 } else { |
| 479 rightEdge = SkScalarRoundToInt(path.getBounds().right()) << shiftEdg
esUp; | 618 rightEdge = SkScalarRoundToInt(path.getBounds().right()) << shiftEdg
esUp; |
| 480 } | 619 } |
| 481 | 620 |
| 482 walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc
, rightEdge); | 621 walk_edges(&headEdge, path.getFillType(), blitter, points, start_y, stop
_y, proc, rightEdge); |
| 483 } | 622 } |
| 484 } | 623 } |
| 485 | 624 |
| 486 void sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip)
{ | 625 void sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip)
{ |
| 487 const SkIRect& cr = clip.getBounds(); | 626 const SkIRect& cr = clip.getBounds(); |
| 488 SkIRect tmp; | 627 SkIRect tmp; |
| 489 | 628 |
| 490 tmp.fLeft = cr.fLeft; | 629 tmp.fLeft = cr.fLeft; |
| 491 tmp.fRight = cr.fRight; | 630 tmp.fRight = cr.fRight; |
| 492 tmp.fTop = cr.fTop; | 631 tmp.fTop = cr.fTop; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 | 731 |
| 593 SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType()); | 732 SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType()); |
| 594 | 733 |
| 595 blitter = clipper.getBlitter(); | 734 blitter = clipper.getBlitter(); |
| 596 if (blitter) { | 735 if (blitter) { |
| 597 // we have to keep our calls to blitter in sorted order, so we | 736 // we have to keep our calls to blitter in sorted order, so we |
| 598 // must blit the above section first, then the middle, then the bottom. | 737 // must blit the above section first, then the middle, then the bottom. |
| 599 if (path.isInverseFillType()) { | 738 if (path.isInverseFillType()) { |
| 600 sk_blit_above(blitter, ir, *clipPtr); | 739 sk_blit_above(blitter, ir, *clipPtr); |
| 601 } | 740 } |
| 602 sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom, | 741 sk_fill_path(path, clipper.getClipRect(), blitter, NULL, ir.fTop, ir.fBo
ttom, |
| 603 0, *clipPtr); | 742 0, *clipPtr); |
| 604 if (path.isInverseFillType()) { | 743 if (path.isInverseFillType()) { |
| 605 sk_blit_below(blitter, ir, *clipPtr); | 744 sk_blit_below(blitter, ir, *clipPtr); |
| 606 } | 745 } |
| 607 } else { | 746 } else { |
| 608 // what does it mean to not have a blitter if path.isInverseFillType??? | 747 // what does it mean to not have a blitter if path.isInverseFillType??? |
| 609 } | 748 } |
| 610 } | 749 } |
| 611 | 750 |
| 612 void SkScan::FillPath(const SkPath& path, const SkIRect& ir, | 751 void SkScan::FillPath(const SkPath& path, const SkIRect& ir, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 | 805 |
| 667 // now edge is the head of the sorted linklist | 806 // now edge is the head of the sorted linklist |
| 668 int stop_y = ir.fBottom; | 807 int stop_y = ir.fBottom; |
| 669 if (clipRect && stop_y > clipRect->fBottom) { | 808 if (clipRect && stop_y > clipRect->fBottom) { |
| 670 stop_y = clipRect->fBottom; | 809 stop_y = clipRect->fBottom; |
| 671 } | 810 } |
| 672 int start_y = ir.fTop; | 811 int start_y = ir.fTop; |
| 673 if (clipRect && start_y < clipRect->fTop) { | 812 if (clipRect && start_y < clipRect->fTop) { |
| 674 start_y = clipRect->fTop; | 813 start_y = clipRect->fTop; |
| 675 } | 814 } |
| 676 walk_convex_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, st
op_y, nullptr); | 815 walk_convex_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, nullptr, st
art_y, stop_y, nullptr); |
| 677 // walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y,
nullptr); | 816 // walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y,
NULL); |
| 678 } | 817 } |
| 679 | 818 |
| 680 void SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip, | 819 void SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip, |
| 681 SkBlitter* blitter) { | 820 SkBlitter* blitter) { |
| 682 if (clip.isEmpty()) { | 821 if (clip.isEmpty()) { |
| 683 return; | 822 return; |
| 684 } | 823 } |
| 685 | 824 |
| 686 SkRect r; | 825 SkRect r; |
| 687 SkIRect ir; | 826 SkIRect ir; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 700 clipRgn = &wrap.getRgn(); | 839 clipRgn = &wrap.getRgn(); |
| 701 blitter = wrap.getBlitter(); | 840 blitter = wrap.getBlitter(); |
| 702 } | 841 } |
| 703 | 842 |
| 704 SkScanClipper clipper(blitter, clipRgn, ir); | 843 SkScanClipper clipper(blitter, clipRgn, ir); |
| 705 blitter = clipper.getBlitter(); | 844 blitter = clipper.getBlitter(); |
| 706 if (blitter) { | 845 if (blitter) { |
| 707 sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); | 846 sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); |
| 708 } | 847 } |
| 709 } | 848 } |
| 849 |
| 850 void SkScan::PathToTriangles(const SkPath& path, const SkIRect& clipBounds, |
| 851 bool antiAlias, SkTDArray<SkPoint>* points) { |
| 852 // dumping = true; |
| 853 // printf("*** SkScan::PathToTriangles start\n"); |
| 854 points->setReserve(path.countPoints()); |
| 855 SkPath localPath = path; |
| 856 SkIRect localClipBounds = clipBounds; |
| 857 if (antiAlias) { |
| 858 // Stroke 1-pix wide around path. |
| 859 SkStroke stroker; |
| 860 stroker.setJoin(SkPaint::kMiter_Join); |
| 861 stroker.setWidth(5); |
| 862 SkPath strokedPath; |
| 863 // We want even open paths to become closed, so we can fill them. |
| 864 stroker.setAutoClose(true); |
| 865 // Don't reverse the inner path direction, since want the interior to be
filled. |
| 866 stroker.setReverseInner(false); |
| 867 stroker.strokePath(localPath, &strokedPath); |
| 868 localPath = strokedPath; |
| 869 } |
| 870 SkRect pathBounds = localPath.getBounds(); |
| 871 SkRegion clipRgn(localClipBounds); |
| 872 if (localPath.isInverseFillType()) { |
| 873 localPath.addRect(SkRect::Make(localClipBounds), SkPath::kCCW_Direction)
; |
| 874 sk_fill_path(localPath, &localClipBounds, NULL, points, |
| 875 localClipBounds.top(), localClipBounds.bottom(), 0, |
| 876 clipRgn); |
| 877 } else { |
| 878 sk_fill_path(localPath, &localClipBounds, NULL, points, |
| 879 pathBounds.top() - 1, pathBounds.bottom() + 1, 0, |
| 880 clipRgn); |
| 881 } |
| 882 // printf("*** SkScan::PathToTriangles end\n"); |
| 883 // dumping = false; |
| 884 } |
| OLD | NEW |