• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright 2006 The Android Open Source Project
3   *
4   * Use of this source code is governed by a BSD-style license that can be
5   * found in the LICENSE file.
6   */
7  
8  #include "include/core/SkPath.h"
9  #include "include/core/SkRegion.h"
10  #include "include/private/SkMacros.h"
11  #include "include/private/SkSafe32.h"
12  #include "include/private/SkTemplates.h"
13  #include "src/core/SkBlitter.h"
14  #include "src/core/SkEdge.h"
15  #include "src/core/SkEdgeBuilder.h"
16  #include "src/core/SkGeometry.h"
17  #include "src/core/SkQuadClipper.h"
18  #include "src/core/SkRasterClip.h"
19  #include "src/core/SkRectPriv.h"
20  #include "src/core/SkScanPriv.h"
21  #include "src/core/SkTSort.h"
22  
23  #include <utility>
24  
25  #define kEDGE_HEAD_Y    SK_MinS32
26  #define kEDGE_TAIL_Y    SK_MaxS32
27  
28  #ifdef SK_DEBUG
validate_sort(const SkEdge * edge)29      static void validate_sort(const SkEdge* edge) {
30          int y = kEDGE_HEAD_Y;
31  
32          while (edge->fFirstY != SK_MaxS32) {
33              edge->validate();
34              SkASSERT(y <= edge->fFirstY);
35  
36              y = edge->fFirstY;
37              edge = edge->fNext;
38          }
39      }
40  #else
41      #define validate_sort(edge)
42  #endif
43  
insert_new_edges(SkEdge * newEdge,int curr_y)44  static void insert_new_edges(SkEdge* newEdge, int curr_y) {
45      if (newEdge->fFirstY != curr_y) {
46          return;
47      }
48      SkEdge* prev = newEdge->fPrev;
49      if (prev->fX <= newEdge->fX) {
50          return;
51      }
52      // find first x pos to insert
53      SkEdge* start = backward_insert_start(prev, newEdge->fX);
54      // insert the lot, fixing up the links as we go
55      do {
56          SkEdge* next = newEdge->fNext;
57          do {
58              if (start->fNext == newEdge) {
59                  goto nextEdge;
60              }
61              SkEdge* after = start->fNext;
62              if (after->fX >= newEdge->fX) {
63                  break;
64              }
65              start = after;
66          } while (true);
67          remove_edge(newEdge);
68          insert_edge_after(newEdge, start);
69  nextEdge:
70          start = newEdge;
71          newEdge = next;
72      } while (newEdge->fFirstY == curr_y);
73  }
74  
75  #ifdef SK_DEBUG
validate_edges_for_y(const SkEdge * edge,int curr_y)76  static void validate_edges_for_y(const SkEdge* edge, int curr_y) {
77      while (edge->fFirstY <= curr_y) {
78          SkASSERT(edge->fPrev && edge->fNext);
79          SkASSERT(edge->fPrev->fNext == edge);
80          SkASSERT(edge->fNext->fPrev == edge);
81          SkASSERT(edge->fFirstY <= edge->fLastY);
82  
83          SkASSERT(edge->fPrev->fX <= edge->fX);
84          edge = edge->fNext;
85      }
86  }
87  #else
88      #define validate_edges_for_y(edge, curr_y)
89  #endif
90  
91  #if defined _WIN32  // disable warning : local variable used without having been initialized
92  #pragma warning ( push )
93  #pragma warning ( disable : 4701 )
94  #endif
95  
96  typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline);
97  #define PREPOST_START   true
98  #define PREPOST_END     false
99  
walk_edges(SkEdge * prevHead,SkPathFillType fillType,SkBlitter * blitter,int start_y,int stop_y,PrePostProc proc,int rightClip)100  static void walk_edges(SkEdge* prevHead, SkPathFillType fillType,
101                         SkBlitter* blitter, int start_y, int stop_y,
102                         PrePostProc proc, int rightClip) {
103      validate_sort(prevHead->fNext);
104  
105      int curr_y = start_y;
106      int windingMask = SkPathFillType_IsEvenOdd(fillType) ? 1 : -1;
107  
108      for (;;) {
109          int     w = 0;
110          int     left SK_INIT_TO_AVOID_WARNING;
111          SkEdge* currE = prevHead->fNext;
112          SkFixed prevX = prevHead->fX;
113  
114          validate_edges_for_y(currE, curr_y);
115  
116          if (proc) {
117              proc(blitter, curr_y, PREPOST_START);    // pre-proc
118          }
119  
120          while (currE->fFirstY <= curr_y) {
121              SkASSERT(currE->fLastY >= curr_y);
122  
123              int x = SkFixedRoundToInt(currE->fX);
124  
125              if ((w & windingMask) == 0) { // we're starting interval
126                  left = x;
127              }
128  
129              w += currE->fWinding;
130  
131              if ((w & windingMask) == 0) { // we finished an interval
132                  int width = x - left;
133                  SkASSERT(width >= 0);
134                  if (width > 0) {
135                      blitter->blitH(left, curr_y, width);
136                  }
137              }
138  
139              SkEdge* next = currE->fNext;
140              SkFixed newX;
141  
142              if (currE->fLastY == curr_y) {    // are we done with this edge?
143                  if (currE->fCurveCount > 0) {
144                      if (((SkQuadraticEdge*)currE)->updateQuadratic()) {
145                          newX = currE->fX;
146                          goto NEXT_X;
147                      }
148                  } else if (currE->fCurveCount < 0) {
149                      if (((SkCubicEdge*)currE)->updateCubic()) {
150                          SkASSERT(currE->fFirstY == curr_y + 1);
151  
152                          newX = currE->fX;
153                          goto NEXT_X;
154                      }
155                  }
156                  remove_edge(currE);
157              } else {
158                  SkASSERT(currE->fLastY > curr_y);
159                  newX = currE->fX + currE->fDX;
160                  currE->fX = newX;
161              NEXT_X:
162                  if (newX < prevX) { // ripple currE backwards until it is x-sorted
163                      backward_insert_edge_based_on_x(currE);
164                  } else {
165                      prevX = newX;
166                  }
167              }
168              currE = next;
169              SkASSERT(currE);
170          }
171  
172          if ((w & windingMask) != 0) { // was our right-edge culled away?
173              int width = rightClip - left;
174              if (width > 0) {
175                  blitter->blitH(left, curr_y, width);
176              }
177          }
178  
179          if (proc) {
180              proc(blitter, curr_y, PREPOST_END);    // post-proc
181          }
182  
183          curr_y += 1;
184          if (curr_y >= stop_y) {
185              break;
186          }
187          // now currE points to the first edge with a Yint larger than curr_y
188          insert_new_edges(currE, curr_y);
189      }
190  }
191  
192  // return true if we're NOT done with this edge
update_edge(SkEdge * edge,int last_y)193  static bool update_edge(SkEdge* edge, int last_y) {
194      SkASSERT(edge->fLastY >= last_y);
195      if (last_y == edge->fLastY) {
196          if (edge->fCurveCount < 0) {
197              if (((SkCubicEdge*)edge)->updateCubic()) {
198                  SkASSERT(edge->fFirstY == last_y + 1);
199                  return true;
200              }
201          } else if (edge->fCurveCount > 0) {
202              if (((SkQuadraticEdge*)edge)->updateQuadratic()) {
203                  SkASSERT(edge->fFirstY == last_y + 1);
204                  return true;
205              }
206          }
207          return false;
208      }
209      return true;
210  }
211  
212  // Unexpected conditions for which we need to return
213  #define ASSERT_RETURN(cond)                    \
214      do {                                       \
215          if (!(cond)) {                         \
216              SkDEBUGFAILF("assert(%s)", #cond); \
217              return;                            \
218          }                                      \
219      } while (0)
220  
221  // Needs Y to only change once (looser than convex in X)
walk_simple_edges(SkEdge * prevHead,SkBlitter * blitter,int start_y,int stop_y)222  static void walk_simple_edges(SkEdge* prevHead, SkBlitter* blitter, int start_y, int stop_y) {
223      validate_sort(prevHead->fNext);
224  
225      SkEdge* leftE = prevHead->fNext;
226      SkEdge* riteE = leftE->fNext;
227      SkEdge* currE = riteE->fNext;
228  
229      // our edge choppers for curves can result in the initial edges
230      // not lining up, so we take the max.
231      int local_top = std::max(leftE->fFirstY, riteE->fFirstY);
232      ASSERT_RETURN(local_top >= start_y);
233  
234      while (local_top < stop_y) {
235          SkASSERT(leftE->fFirstY <= stop_y);
236          SkASSERT(riteE->fFirstY <= stop_y);
237  
238          int local_bot = std::min(leftE->fLastY, riteE->fLastY);
239          local_bot = std::min(local_bot, stop_y - 1);
240          ASSERT_RETURN(local_top <= local_bot);
241  
242          SkFixed left = leftE->fX;
243          SkFixed dLeft = leftE->fDX;
244          SkFixed rite = riteE->fX;
245          SkFixed dRite = riteE->fDX;
246          int count = local_bot - local_top;
247          ASSERT_RETURN(count >= 0);
248  
249          if (0 == (dLeft | dRite)) {
250              int L = SkFixedRoundToInt(left);
251              int R = SkFixedRoundToInt(rite);
252              if (L > R) {
253                  std::swap(L, R);
254              }
255              if (L < R) {
256                  count += 1;
257                  blitter->blitRect(L, local_top, R - L, count);
258              }
259              local_top = local_bot + 1;
260          } else {
261              do {
262                  int L = SkFixedRoundToInt(left);
263                  int R = SkFixedRoundToInt(rite);
264                  if (L > R) {
265                      std::swap(L, R);
266                  }
267                  if (L < R) {
268                      blitter->blitH(L, local_top, R - L);
269                  }
270                  // Either/both of these might overflow, since we perform this step even if
271                  // (later) we determine that we are done with the edge, and so the computed
272                  // left or rite edge will not be used (see update_edge). Use this helper to
273                  // silence UBSAN when we perform the add.
274                  left = Sk32_can_overflow_add(left, dLeft);
275                  rite = Sk32_can_overflow_add(rite, dRite);
276                  local_top += 1;
277              } while (--count >= 0);
278          }
279  
280          leftE->fX = left;
281          riteE->fX = rite;
282  
283          if (!update_edge(leftE, local_bot)) {
284              if (currE->fFirstY >= stop_y) {
285                  return; // we're done
286              }
287              leftE = currE;
288              currE = currE->fNext;
289              ASSERT_RETURN(leftE->fFirstY == local_top);
290          }
291          if (!update_edge(riteE, local_bot)) {
292              if (currE->fFirstY >= stop_y) {
293                  return; // we're done
294              }
295              riteE = currE;
296              currE = currE->fNext;
297              ASSERT_RETURN(riteE->fFirstY == local_top);
298          }
299      }
300  }
301  
302  ///////////////////////////////////////////////////////////////////////////////
303  
304  // this overrides blitH, and will call its proxy blitter with the inverse
305  // of the spans it is given (clipped to the left/right of the cliprect)
306  //
307  // used to implement inverse filltypes on paths
308  //
309  class InverseBlitter : public SkBlitter {
310  public:
setBlitter(SkBlitter * blitter,const SkIRect & clip,int shift)311      void setBlitter(SkBlitter* blitter, const SkIRect& clip, int shift) {
312          fBlitter = blitter;
313          fFirstX = clip.fLeft << shift;
314          fLastX = clip.fRight << shift;
315      }
prepost(int y,bool isStart)316      void prepost(int y, bool isStart) {
317          if (isStart) {
318              fPrevX = fFirstX;
319          } else {
320              int invWidth = fLastX - fPrevX;
321              if (invWidth > 0) {
322                  fBlitter->blitH(fPrevX, y, invWidth);
323              }
324          }
325      }
326  
327      // overrides
blitH(int x,int y,int width)328      void blitH(int x, int y, int width) override {
329          int invWidth = x - fPrevX;
330          if (invWidth > 0) {
331              fBlitter->blitH(fPrevX, y, invWidth);
332          }
333          fPrevX = x + width;
334      }
335  
336      // we do not expect to get called with these entrypoints
blitAntiH(int,int,const SkAlpha[],const int16_t runs[])337      void blitAntiH(int, int, const SkAlpha[], const int16_t runs[]) override {
338          SkDEBUGFAIL("blitAntiH unexpected");
339      }
blitV(int x,int y,int height,SkAlpha alpha)340      void blitV(int x, int y, int height, SkAlpha alpha) override {
341          SkDEBUGFAIL("blitV unexpected");
342      }
blitRect(int x,int y,int width,int height)343      void blitRect(int x, int y, int width, int height) override {
344          SkDEBUGFAIL("blitRect unexpected");
345      }
blitMask(const SkMask &,const SkIRect & clip)346      void blitMask(const SkMask&, const SkIRect& clip) override {
347          SkDEBUGFAIL("blitMask unexpected");
348      }
justAnOpaqueColor(uint32_t * value)349      const SkPixmap* justAnOpaqueColor(uint32_t* value) override {
350          SkDEBUGFAIL("justAnOpaqueColor unexpected");
351          return nullptr;
352      }
353  
354  private:
355      SkBlitter*  fBlitter;
356      int         fFirstX, fLastX, fPrevX;
357  };
358  
PrePostInverseBlitterProc(SkBlitter * blitter,int y,bool isStart)359  static void PrePostInverseBlitterProc(SkBlitter* blitter, int y, bool isStart) {
360      ((InverseBlitter*)blitter)->prepost(y, isStart);
361  }
362  
363  ///////////////////////////////////////////////////////////////////////////////
364  
365  #if defined _WIN32
366  #pragma warning ( pop )
367  #endif
368  
operator <(const SkEdge & a,const SkEdge & b)369  static bool operator<(const SkEdge& a, const SkEdge& b) {
370      int valuea = a.fFirstY;
371      int valueb = b.fFirstY;
372  
373      if (valuea == valueb) {
374          valuea = a.fX;
375          valueb = b.fX;
376      }
377  
378      return valuea < valueb;
379  }
380  
sort_edges(SkEdge * list[],int count,SkEdge ** last)381  static SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) {
382      SkTQSort(list, list + count);
383  
384      // now make the edges linked in sorted order
385      for (int i = 1; i < count; i++) {
386          list[i - 1]->fNext = list[i];
387          list[i]->fPrev = list[i - 1];
388      }
389  
390      *last = list[count - 1];
391      return list[0];
392  }
393  
394  // clipRect has not been shifted up
sk_fill_path(const SkPath & path,const SkIRect & clipRect,SkBlitter * blitter,int start_y,int stop_y,int shiftEdgesUp,bool pathContainedInClip)395  void sk_fill_path(const SkPath& path, const SkIRect& clipRect, SkBlitter* blitter,
396                    int start_y, int stop_y, int shiftEdgesUp, bool pathContainedInClip) {
397      SkASSERT(blitter);
398  
399      SkIRect shiftedClip = clipRect;
400      shiftedClip.fLeft = SkLeftShift(shiftedClip.fLeft, shiftEdgesUp);
401      shiftedClip.fRight = SkLeftShift(shiftedClip.fRight, shiftEdgesUp);
402      shiftedClip.fTop = SkLeftShift(shiftedClip.fTop, shiftEdgesUp);
403      shiftedClip.fBottom = SkLeftShift(shiftedClip.fBottom, shiftEdgesUp);
404  
405      SkBasicEdgeBuilder builder(shiftEdgesUp);
406      int count = builder.buildEdges(path, pathContainedInClip ? nullptr : &shiftedClip);
407      SkEdge** list = builder.edgeList();
408  
409      if (0 == count) {
410          if (path.isInverseFillType()) {
411              /*
412               *  Since we are in inverse-fill, our caller has already drawn above
413               *  our top (start_y) and will draw below our bottom (stop_y). Thus
414               *  we need to restrict our drawing to the intersection of the clip
415               *  and those two limits.
416               */
417              SkIRect rect = clipRect;
418              if (rect.fTop < start_y) {
419                  rect.fTop = start_y;
420              }
421              if (rect.fBottom > stop_y) {
422                  rect.fBottom = stop_y;
423              }
424              if (!rect.isEmpty()) {
425                  blitter->blitRect(rect.fLeft << shiftEdgesUp,
426                                    rect.fTop << shiftEdgesUp,
427                                    rect.width() << shiftEdgesUp,
428                                    rect.height() << shiftEdgesUp);
429              }
430          }
431          return;
432      }
433  
434      SkEdge headEdge, tailEdge, *last;
435      // this returns the first and last edge after they're sorted into a dlink list
436      SkEdge* edge = sort_edges(list, count, &last);
437  
438      headEdge.fPrev = nullptr;
439      headEdge.fNext = edge;
440      headEdge.fFirstY = kEDGE_HEAD_Y;
441      headEdge.fX = SK_MinS32;
442      edge->fPrev = &headEdge;
443  
444      tailEdge.fPrev = last;
445      tailEdge.fNext = nullptr;
446      tailEdge.fFirstY = kEDGE_TAIL_Y;
447      last->fNext = &tailEdge;
448  
449      // now edge is the head of the sorted linklist
450  
451      start_y = SkLeftShift(start_y, shiftEdgesUp);
452      stop_y = SkLeftShift(stop_y, shiftEdgesUp);
453      if (!pathContainedInClip && start_y < shiftedClip.fTop) {
454          start_y = shiftedClip.fTop;
455      }
456      if (!pathContainedInClip && stop_y > shiftedClip.fBottom) {
457          stop_y = shiftedClip.fBottom;
458      }
459  
460      InverseBlitter  ib;
461      PrePostProc     proc = nullptr;
462  
463      if (path.isInverseFillType()) {
464          ib.setBlitter(blitter, clipRect, shiftEdgesUp);
465          blitter = &ib;
466          proc = PrePostInverseBlitterProc;
467      }
468  
469      // count >= 2 is required as the convex walker does not handle missing right edges
470      if (path.isConvex() && (nullptr == proc) && count >= 2) {
471          walk_simple_edges(&headEdge, blitter, start_y, stop_y);
472      } else {
473          walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc,
474                     shiftedClip.right());
475      }
476  }
477  
sk_blit_above(SkBlitter * blitter,const SkIRect & ir,const SkRegion & clip)478  void sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) {
479      const SkIRect& cr = clip.getBounds();
480      SkIRect tmp;
481  
482      tmp.fLeft = cr.fLeft;
483      tmp.fRight = cr.fRight;
484      tmp.fTop = cr.fTop;
485      tmp.fBottom = ir.fTop;
486      if (!tmp.isEmpty()) {
487          blitter->blitRectRegion(tmp, clip);
488      }
489  }
490  
sk_blit_below(SkBlitter * blitter,const SkIRect & ir,const SkRegion & clip)491  void sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) {
492      const SkIRect& cr = clip.getBounds();
493      SkIRect tmp;
494  
495      tmp.fLeft = cr.fLeft;
496      tmp.fRight = cr.fRight;
497      tmp.fTop = ir.fBottom;
498      tmp.fBottom = cr.fBottom;
499      if (!tmp.isEmpty()) {
500          blitter->blitRectRegion(tmp, clip);
501      }
502  }
503  
504  ///////////////////////////////////////////////////////////////////////////////
505  
506  /**
507   *  If the caller is drawing an inverse-fill path, then it pass true for
508   *  skipRejectTest, so we don't abort drawing just because the src bounds (ir)
509   *  is outside of the clip.
510   */
SkScanClipper(SkBlitter * blitter,const SkRegion * clip,const SkIRect & ir,bool skipRejectTest,bool irPreClipped)511  SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip,
512                               const SkIRect& ir, bool skipRejectTest, bool irPreClipped) {
513      fBlitter = nullptr;     // null means blit nothing
514      fClipRect = nullptr;
515  
516      if (clip) {
517          fClipRect = &clip->getBounds();
518          if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out
519              return;
520          }
521  
522          if (clip->isRect()) {
523              if (!irPreClipped && fClipRect->contains(ir)) {
524  #ifdef SK_DEBUG
525                  fRectClipCheckBlitter.init(blitter, *fClipRect);
526                  blitter = &fRectClipCheckBlitter;
527  #endif
528                  fClipRect = nullptr;
529              } else {
530                  // only need a wrapper blitter if we're horizontally clipped
531                  if (irPreClipped ||
532                      fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) {
533                      fRectBlitter.init(blitter, *fClipRect);
534                      blitter = &fRectBlitter;
535                  } else {
536  #ifdef SK_DEBUG
537                      fRectClipCheckBlitter.init(blitter, *fClipRect);
538                      blitter = &fRectClipCheckBlitter;
539  #endif
540                  }
541              }
542          } else {
543              fRgnBlitter.init(blitter, clip);
544              blitter = &fRgnBlitter;
545          }
546      }
547      fBlitter = blitter;
548  }
549  
550  ///////////////////////////////////////////////////////////////////////////////
551  
clip_to_limit(const SkRegion & orig,SkRegion * reduced)552  static bool clip_to_limit(const SkRegion& orig, SkRegion* reduced) {
553      // need to limit coordinates such that the width/height of our rect can be represented
554      // in SkFixed (16.16). See skbug.com/7998
555      const int32_t limit = 32767 >> 1;
556  
557      SkIRect limitR;
558      limitR.setLTRB(-limit, -limit, limit, limit);
559      if (limitR.contains(orig.getBounds())) {
560          return false;
561      }
562      reduced->op(orig, limitR, SkRegion::kIntersect_Op);
563      return true;
564  }
565  
566  // Bias used for conservative rounding of float rects to int rects, to nudge the irects a little
567  // larger, so we don't "think" a path's bounds are inside a clip, when (due to numeric drift in
568  // the scan-converter) we might walk beyond the predicted limits.
569  //
570  // This value has been determined trial and error: pick the smallest value (after the 0.5) that
571  // fixes any problematic cases (e.g. crbug.com/844457)
572  // NOTE: cubics appear to be the main reason for needing this slop. If we could (perhaps) have a
573  // more accurate walker for cubics, we may be able to reduce this fudge factor.
574  static const double kConservativeRoundBias = 0.5 + 1.5 / SK_FDot6One;
575  
576  /**
577   *  Round the value down. This is used to round the top and left of a rectangle,
578   *  and corresponds to the way the scan converter treats the top and left edges.
579   *  It has a slight bias to make the "rounded" int smaller than a normal round, to create a more
580   *  conservative int-bounds (larger) from a float rect.
581   */
round_down_to_int(SkScalar x)582  static inline int round_down_to_int(SkScalar x) {
583      double xx = x;
584      xx -= kConservativeRoundBias;
585      return sk_double_saturate2int(ceil(xx));
586  }
587  
588  /**
589   *  Round the value up. This is used to round the right and bottom of a rectangle.
590   *  It has a slight bias to make the "rounded" int smaller than a normal round, to create a more
591   *  conservative int-bounds (larger) from a float rect.
592    */
round_up_to_int(SkScalar x)593  static inline int round_up_to_int(SkScalar x) {
594      double xx = x;
595      xx += kConservativeRoundBias;
596      return sk_double_saturate2int(floor(xx));
597  }
598  
599  /*
600   *  Conservative rounding function, which effectively nudges the int-rect to be slightly larger
601   *  than SkRect::round() might have produced. This is a safety-net for the scan-converter, which
602   *  inspects the returned int-rect, and may disable clipping (for speed) if it thinks all of the
603   *  edges will fit inside the clip's bounds. The scan-converter introduces slight numeric errors
604   *  due to accumulated += of the slope, so this function is used to return a conservatively large
605   *  int-bounds, and thus we will only disable clipping if we're sure the edges will stay in-bounds.
606    */
conservative_round_to_int(const SkRect & src)607  static SkIRect conservative_round_to_int(const SkRect& src) {
608      return {
609          round_down_to_int(src.fLeft),
610          round_down_to_int(src.fTop),
611          round_up_to_int(src.fRight),
612          round_up_to_int(src.fBottom),
613      };
614  }
615  
FillPath(const SkPath & path,const SkRegion & origClip,SkBlitter * blitter)616  void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
617                        SkBlitter* blitter) {
618      if (origClip.isEmpty()) {
619          return;
620      }
621  
622      // Our edges are fixed-point, and don't like the bounds of the clip to
623      // exceed that. Here we trim the clip just so we don't overflow later on
624      const SkRegion* clipPtr = &origClip;
625      SkRegion finiteClip;
626      if (clip_to_limit(origClip, &finiteClip)) {
627          if (finiteClip.isEmpty()) {
628              return;
629          }
630          clipPtr = &finiteClip;
631      }
632      // don't reference "origClip" any more, just use clipPtr
633  
634  
635      SkRect bounds = path.getBounds();
636      bool irPreClipped = false;
637      if (!SkRectPriv::MakeLargeS32().contains(bounds)) {
638          if (!bounds.intersect(SkRectPriv::MakeLargeS32())) {
639              bounds.setEmpty();
640          }
641          irPreClipped = true;
642      }
643  
644      SkIRect ir = conservative_round_to_int(bounds);
645      if (ir.isEmpty()) {
646          if (path.isInverseFillType()) {
647              blitter->blitRegion(*clipPtr);
648          }
649          return;
650      }
651  
652      SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType(), irPreClipped);
653  
654      blitter = clipper.getBlitter();
655      if (blitter) {
656          // we have to keep our calls to blitter in sorted order, so we
657          // must blit the above section first, then the middle, then the bottom.
658          if (path.isInverseFillType()) {
659              sk_blit_above(blitter, ir, *clipPtr);
660          }
661          SkASSERT(clipper.getClipRect() == nullptr ||
662                  *clipper.getClipRect() == clipPtr->getBounds());
663          sk_fill_path(path, clipPtr->getBounds(), blitter, ir.fTop, ir.fBottom,
664                       0, clipper.getClipRect() == nullptr);
665          if (path.isInverseFillType()) {
666              sk_blit_below(blitter, ir, *clipPtr);
667          }
668      } else {
669          // what does it mean to not have a blitter if path.isInverseFillType???
670      }
671  }
672  
FillPath(const SkPath & path,const SkIRect & ir,SkBlitter * blitter)673  void SkScan::FillPath(const SkPath& path, const SkIRect& ir,
674                        SkBlitter* blitter) {
675      SkRegion rgn(ir);
676      FillPath(path, rgn, blitter);
677  }
678  
DowngradeClipAA(const SkIRect & bounds)679  bool SkScan::DowngradeClipAA(const SkIRect& bounds) {
680      SkRegion out;  // ignored
681      return clip_to_limit(SkRegion(bounds), &out);
682  }
683  
684  ///////////////////////////////////////////////////////////////////////////////
685  
build_tri_edges(SkEdge edge[],const SkPoint pts[],const SkIRect * clipRect,SkEdge * list[])686  static int build_tri_edges(SkEdge edge[], const SkPoint pts[],
687                             const SkIRect* clipRect, SkEdge* list[]) {
688      SkEdge** start = list;
689  
690      if (edge->setLine(pts[0], pts[1], clipRect, 0)) {
691          *list++ = edge;
692          edge = (SkEdge*)((char*)edge + sizeof(SkEdge));
693      }
694      if (edge->setLine(pts[1], pts[2], clipRect, 0)) {
695          *list++ = edge;
696          edge = (SkEdge*)((char*)edge + sizeof(SkEdge));
697      }
698      if (edge->setLine(pts[2], pts[0], clipRect, 0)) {
699          *list++ = edge;
700      }
701      return (int)(list - start);
702  }
703  
704  
sk_fill_triangle(const SkPoint pts[],const SkIRect * clipRect,SkBlitter * blitter,const SkIRect & ir)705  static void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect,
706                               SkBlitter* blitter, const SkIRect& ir) {
707      SkASSERT(pts && blitter);
708  
709      SkEdge edgeStorage[3];
710      SkEdge* list[3];
711  
712      int count = build_tri_edges(edgeStorage, pts, clipRect, list);
713      if (count < 2) {
714          return;
715      }
716  
717      SkEdge headEdge, tailEdge, *last;
718  
719      // this returns the first and last edge after they're sorted into a dlink list
720      SkEdge* edge = sort_edges(list, count, &last);
721  
722      headEdge.fPrev = nullptr;
723      headEdge.fNext = edge;
724      headEdge.fFirstY = kEDGE_HEAD_Y;
725      headEdge.fX = SK_MinS32;
726      edge->fPrev = &headEdge;
727  
728      tailEdge.fPrev = last;
729      tailEdge.fNext = nullptr;
730      tailEdge.fFirstY = kEDGE_TAIL_Y;
731      last->fNext = &tailEdge;
732  
733      // now edge is the head of the sorted linklist
734      int stop_y = ir.fBottom;
735      if (clipRect && stop_y > clipRect->fBottom) {
736          stop_y = clipRect->fBottom;
737      }
738      int start_y = ir.fTop;
739      if (clipRect && start_y < clipRect->fTop) {
740          start_y = clipRect->fTop;
741      }
742      walk_simple_edges(&headEdge, blitter, start_y, stop_y);
743  }
744  
FillTriangle(const SkPoint pts[],const SkRasterClip & clip,SkBlitter * blitter)745  void SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip,
746                            SkBlitter* blitter) {
747      if (clip.isEmpty()) {
748          return;
749      }
750  
751      SkRect  r;
752      r.setBounds(pts, 3);
753      // If r is too large (larger than can easily fit in SkFixed) then we need perform geometric
754      // clipping. This is a bit of work, so we just call the general FillPath() to handle it.
755      // Use FixedMax/2 as the limit so we can subtract two edges and still store that in Fixed.
756      const SkScalar limit = SK_MaxS16 >> 1;
757      if (!SkRect::MakeLTRB(-limit, -limit, limit, limit).contains(r)) {
758          SkPath path;
759          path.addPoly(pts, 3, false);
760          FillPath(path, clip, blitter);
761          return;
762      }
763  
764      SkIRect ir = conservative_round_to_int(r);
765      if (ir.isEmpty() || !SkIRect::Intersects(ir, clip.getBounds())) {
766          return;
767      }
768  
769      SkAAClipBlitterWrapper wrap;
770      const SkRegion* clipRgn;
771      if (clip.isBW()) {
772          clipRgn = &clip.bwRgn();
773      } else {
774          wrap.init(clip, blitter);
775          clipRgn = &wrap.getRgn();
776          blitter = wrap.getBlitter();
777      }
778  
779      SkScanClipper clipper(blitter, clipRgn, ir);
780      blitter = clipper.getBlitter();
781      if (blitter) {
782          sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir);
783      }
784  }
785