Flutter Engine
The Flutter Engine
Macros | Typedefs | Functions
SkScan_Hairline.cpp File Reference
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRegion.h"
#include "include/core/SkScalar.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkFixed.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkMath.h"
#include "include/private/base/SkSafe32.h"
#include "src/base/SkMathPriv.h"
#include "src/base/SkUtils.h"
#include "src/base/SkVx.h"
#include "src/core/SkBlitter.h"
#include "src/core/SkFDot6.h"
#include "src/core/SkGeometry.h"
#include "src/core/SkLineClipper.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkRasterClip.h"
#include "src/core/SkScan.h"
#include <algorithm>
#include <array>
#include <cstdint>
#include <cstring>

Go to the source code of this file.

Macros

#define kMaxCubicSubdivideLevel   9
 
#define kMaxQuadSubdivideLevel   5
 

Typedefs

using float2 = skvx::float2
 
using mask2 = skvx::Vec< 2, uint32_t >
 

Functions

static void horiline (int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter *blitter)
 
static void vertline (int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter *blitter)
 
static uint32_t compute_int_quad_dist (const SkPoint pts[3])
 
static void hair_quad (const SkPoint pts[3], const SkRegion *clip, SkBlitter *blitter, int level, SkScan::HairRgnProc lineproc)
 
static SkRect compute_nocheck_quad_bounds (const SkPoint pts[3])
 
static bool is_inverted (const SkRect &r)
 
static bool geometric_overlap (const SkRect &a, const SkRect &b)
 
static bool geometric_contains (const SkRect &outer, const SkRect &inner)
 
static void hairquad (const SkPoint pts[3], const SkRegion *clip, const SkRect *insetClip, const SkRect *outsetClip, SkBlitter *blitter, int level, SkScan::HairRgnProc lineproc)
 
static SkScalar max_component (const float2 &value)
 
static int compute_cubic_segs (const SkPoint pts[4])
 
static bool lt_90 (SkPoint p0, SkPoint pivot, SkPoint p2)
 
static bool quick_cubic_niceness_check (const SkPoint pts[4])
 
static mask2 float2_is_finite (const float2 &x)
 
static void hair_cubic (const SkPoint pts[4], const SkRegion *clip, SkBlitter *blitter, SkScan::HairRgnProc lineproc)
 
static SkRect compute_nocheck_cubic_bounds (const SkPoint pts[4])
 
static void haircubic (const SkPoint pts[4], const SkRegion *clip, const SkRect *insetClip, const SkRect *outsetClip, SkBlitter *blitter, int level, SkScan::HairRgnProc lineproc)
 
static int compute_quad_level (const SkPoint pts[3])
 
template<SkPaint::Cap capStyle>
void extend_pts (SkPath::Verb prevVerb, SkPath::Verb nextVerb, SkPoint *pts, int ptCount)
 
template<SkPaint::Cap capStyle>
void hair_path (const SkPath &path, const SkRasterClip &rclip, SkBlitter *blitter, SkScan::HairRgnProc lineproc)
 

Macro Definition Documentation

◆ kMaxCubicSubdivideLevel

#define kMaxCubicSubdivideLevel   9

Definition at line 231 of file SkScan_Hairline.cpp.

◆ kMaxQuadSubdivideLevel

#define kMaxQuadSubdivideLevel   5

Definition at line 232 of file SkScan_Hairline.cpp.

Typedef Documentation

◆ float2

Definition at line 234 of file SkScan_Hairline.cpp.

◆ mask2

using mask2 = skvx::Vec<2, uint32_t>

Definition at line 372 of file SkScan_Hairline.cpp.

Function Documentation

◆ compute_cubic_segs()

static int compute_cubic_segs ( const SkPoint  pts[4])
inlinestatic

Definition at line 336 of file SkScan_Hairline.cpp.

336 {
337 float2 p0 = from_point(pts[0]);
338 float2 p1 = from_point(pts[1]);
339 float2 p2 = from_point(pts[2]);
340 float2 p3 = from_point(pts[3]);
341
342 const float2 oneThird(1.0f / 3.0f);
343 const float2 twoThird(2.0f / 3.0f);
344
345 float2 p13 = oneThird * p3 + twoThird * p0;
346 float2 p23 = oneThird * p0 + twoThird * p3;
347
348 SkScalar diff = max_component(max(abs(p1 - p13), abs(p2 - p23)));
349 SkScalar tol = SK_Scalar1 / 8;
350
351 for (int i = 0; i < kMaxCubicSubdivideLevel; ++i) {
352 if (diff < tol) {
353 return 1 << i;
354 }
355 tol *= 4;
356 }
357 return 1 << kMaxCubicSubdivideLevel;
358}
static skvx::float2 from_point(const SkPoint &point)
Definition: SkGeometry.h:22
#define SK_Scalar1
Definition: SkScalar.h:18
#define kMaxCubicSubdivideLevel
static SkScalar max_component(const float2 &value)
float SkScalar
Definition: extension.cpp:12
static float max(float r, float g, float b)
Definition: hsl.cpp:49
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition: SkVx.h:707
Definition: SkVx.h:83

◆ compute_int_quad_dist()

static uint32_t compute_int_quad_dist ( const SkPoint  pts[3])
static

Definition at line 236 of file SkScan_Hairline.cpp.

236 {
237 // compute the vector between the control point ([1]) and the middle of the
238 // line connecting the start and end ([0] and [2])
239 SkScalar dx = SkScalarHalf(pts[0].fX + pts[2].fX) - pts[1].fX;
240 SkScalar dy = SkScalarHalf(pts[0].fY + pts[2].fY) - pts[1].fY;
241 // we want everyone to be positive
242 dx = SkScalarAbs(dx);
243 dy = SkScalarAbs(dy);
244 // convert to whole pixel values (use ceiling to be conservative).
245 // assign to unsigned so we can safely add 1/2 of the smaller and still fit in
246 // uint32_t, since SkScalarCeilToInt() returns 31 bits at most.
247 uint32_t idx = SkScalarCeilToInt(dx);
248 uint32_t idy = SkScalarCeilToInt(dy);
249 // use the cheap approx for distance
250 if (idx > idy) {
251 return idx + (idy >> 1);
252 } else {
253 return idy + (idx >> 1);
254 }
255}
#define SkScalarHalf(a)
Definition: SkScalar.h:75
#define SkScalarCeilToInt(x)
Definition: SkScalar.h:36
#define SkScalarAbs(x)
Definition: SkScalar.h:39
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ compute_nocheck_cubic_bounds()

static SkRect compute_nocheck_cubic_bounds ( const SkPoint  pts[4])
static

Definition at line 415 of file SkScan_Hairline.cpp.

415 {
416 SkASSERT(SkIsFinite(&pts[0].fX, 8));
417
418 float2 min = float2::Load(pts);
419 float2 max = min;
420 for (int i = 1; i < 4; ++i) {
421 float2 pair = float2::Load(pts+i);
422 min = skvx::min(min, pair);
423 max = skvx::max(max, pair);
424 }
425 return { min[0], min[1], max[0], max[1] };
426}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool SkIsFinite(T x, Pack... values)
static float min(float r, float g, float b)
Definition: hsl.cpp:48
SIT T max(const Vec< 1, T > &x)
Definition: SkVx.h:641
SIT T min(const Vec< 1, T > &x)
Definition: SkVx.h:640
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
Definition: SkVx.h:109

◆ compute_nocheck_quad_bounds()

static SkRect compute_nocheck_quad_bounds ( const SkPoint  pts[3])
static

Definition at line 282 of file SkScan_Hairline.cpp.

282 {
283 SkASSERT(SkIsFinite(&pts[0].fX, 6));
284
285 float2 min = float2::Load(pts);
286 float2 max = min;
287 for (int i = 1; i < 3; ++i) {
288 float2 pair = float2::Load(pts+i);
289 min = skvx::min(min, pair);
290 max = skvx::max(max, pair);
291 }
292 return { min[0], min[1], max[0], max[1] };
293}

◆ compute_quad_level()

static int compute_quad_level ( const SkPoint  pts[3])
static

Definition at line 453 of file SkScan_Hairline.cpp.

453 {
454 uint32_t d = compute_int_quad_dist(pts);
455 /* quadratics approach the line connecting their start and end points
456 4x closer with each subdivision, so we compute the number of
457 subdivisions to be the minimum need to get that distance to be less
458 than a pixel.
459 */
460 int level = (33 - SkCLZ(d)) >> 1;
461 // safety check on level (from the previous version)
464 }
465 return level;
466}
static int SkCLZ(uint32_t mask)
Definition: SkMathPriv.h:186
#define kMaxQuadSubdivideLevel
static uint32_t compute_int_quad_dist(const SkPoint pts[3])
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19

◆ extend_pts()

template<SkPaint::Cap capStyle>
void extend_pts ( SkPath::Verb  prevVerb,
SkPath::Verb  nextVerb,
SkPoint pts,
int  ptCount 
)

Definition at line 473 of file SkScan_Hairline.cpp.

473 {
474 SkASSERT(SkPaint::kSquare_Cap == capStyle || SkPaint::kRound_Cap == capStyle);
475 // The area of a circle is PI*R*R. For a unit circle, R=1/2, and the cap covers half of that.
476 const SkScalar capOutset = SkPaint::kSquare_Cap == capStyle ? 0.5f : SK_ScalarPI / 8;
477 if (SkPath::kMove_Verb == prevVerb) {
478 SkPoint* first = pts;
479 SkPoint* ctrl = first;
480 int controls = ptCount - 1;
481 SkVector tangent;
482 do {
483 tangent = *first - *++ctrl;
484 } while (tangent.isZero() && --controls > 0);
485 if (tangent.isZero()) {
486 tangent.set(1, 0);
487 controls = ptCount - 1; // If all points are equal, move all but one
488 } else {
489 tangent.normalize();
490 }
491 do { // If the end point and control points are equal, loop to move them in tandem.
492 first->fX += tangent.fX * capOutset;
493 first->fY += tangent.fY * capOutset;
494 ++first;
495 } while (++controls < ptCount);
496 }
497 if (SkPath::kMove_Verb == nextVerb || SkPath::kDone_Verb == nextVerb
498 || SkPath::kClose_Verb == nextVerb) {
499 SkPoint* last = &pts[ptCount - 1];
500 SkPoint* ctrl = last;
501 int controls = ptCount - 1;
502 SkVector tangent;
503 do {
504 tangent = *last - *--ctrl;
505 } while (tangent.isZero() && --controls > 0);
506 if (tangent.isZero()) {
507 tangent.set(-1, 0);
508 controls = ptCount - 1;
509 } else {
510 tangent.normalize();
511 }
512 do {
513 last->fX += tangent.fX * capOutset;
514 last->fY += tangent.fY * capOutset;
515 --last;
516 } while (++controls < ptCount);
517 }
518}
#define SK_ScalarPI
Definition: SkScalar.h:21
@ kRound_Cap
adds circle
Definition: SkPaint.h:335
@ kSquare_Cap
adds square
Definition: SkPaint.h:336
@ kClose_Verb
Definition: SkPath.h:1471
@ kMove_Verb
Definition: SkPath.h:1466
@ kDone_Verb
Definition: SkPath.h:1472
bool isZero() const
Definition: SkPoint_impl.h:193
void set(float x, float y)
Definition: SkPoint_impl.h:200
bool normalize()
Definition: SkPoint.cpp:22

◆ float2_is_finite()

static mask2 float2_is_finite ( const float2 x)
inlinestatic

Definition at line 374 of file SkScan_Hairline.cpp.

374 {
375 const mask2 exp_mask = mask2(0xFF << 23);
376 return (sk_bit_cast<mask2>(x) & exp_mask) != exp_mask;
377}
skvx::Vec< 2, uint32_t > mask2
double x

◆ geometric_contains()

static bool geometric_contains ( const SkRect outer,
const SkRect inner 
)
static

Definition at line 309 of file SkScan_Hairline.cpp.

309 {
310 SkASSERT(!is_inverted(outer) && !is_inverted(inner));
311 return inner.fRight <= outer.fRight && inner.fLeft >= outer.fLeft &&
312 inner.fBottom <= outer.fBottom && inner.fTop >= outer.fTop;
313}
static bool is_inverted(const SkRect &r)
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15

◆ geometric_overlap()

static bool geometric_overlap ( const SkRect a,
const SkRect b 
)
static

Definition at line 301 of file SkScan_Hairline.cpp.

301 {
303 return a.fLeft < b.fRight && b.fLeft < a.fRight &&
304 a.fTop < b.fBottom && b.fTop < a.fBottom;
305}
static bool b
struct MyStruct a[10]

◆ hair_cubic()

static void hair_cubic ( const SkPoint  pts[4],
const SkRegion clip,
SkBlitter blitter,
SkScan::HairRgnProc  lineproc 
)
static

Definition at line 379 of file SkScan_Hairline.cpp.

380 {
381 const int lines = compute_cubic_segs(pts);
382 SkASSERT(lines > 0);
383 if (1 == lines) {
384 SkPoint tmp[2] = { pts[0], pts[3] };
385 lineproc(tmp, 2, clip, blitter);
386 return;
387 }
388
389 SkCubicCoeff coeff(pts);
390
391 const float2 dt(SK_Scalar1 / lines);
392 float2 t(0);
393
394 SkPoint tmp[(1 << kMaxCubicSubdivideLevel) + 1];
395 SkASSERT((unsigned)lines < std::size(tmp));
396
397 tmp[0] = pts[0];
398 float2 A = coeff.fA;
399 float2 B = coeff.fB;
400 float2 C = coeff.fC;
401 float2 D = coeff.fD;
402 mask2 is_finite(~0); // start out as true
403 for (int i = 1; i < lines; ++i) {
404 t = t + dt;
405 float2 p = ((A * t + B) * t + C) * t + D;
406 is_finite &= float2_is_finite(p);
407 p.store(&tmp[i]);
408 }
409 if (all(is_finite)) {
410 tmp[lines] = pts[3];
411 lineproc(tmp, lines + 1, clip, blitter);
412 } // else some point(s) are non-finite, so don't draw
413}
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
static int compute_cubic_segs(const SkPoint pts[4])
static mask2 float2_is_finite(const float2 &x)
#define B
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
SIT bool all(const Vec< 1, T > &x)
Definition: SkVx.h:582

◆ hair_path()

template<SkPaint::Cap capStyle>
void hair_path ( const SkPath path,
const SkRasterClip rclip,
SkBlitter blitter,
SkScan::HairRgnProc  lineproc 
)

Definition at line 521 of file SkScan_Hairline.cpp.

522 {
523 if (path.isEmpty()) {
524 return;
525 }
526
528 const SkRegion* clip = nullptr;
529 SkRect insetStorage, outsetStorage;
530 const SkRect* insetClip = nullptr;
531 const SkRect* outsetClip = nullptr;
532
533 {
534 const int capOut = SkPaint::kButt_Cap == capStyle ? 1 : 2;
535 const SkIRect ibounds = path.getBounds().roundOut().makeOutset(capOut, capOut);
536 if (rclip.quickReject(ibounds)) {
537 return;
538 }
539 if (!rclip.quickContains(ibounds)) {
540 if (rclip.isBW()) {
541 clip = &rclip.bwRgn();
542 } else {
543 wrap.init(rclip, blitter);
544 blitter = wrap.getBlitter();
545 clip = &wrap.getRgn();
546 }
547
548 /*
549 * We now cache two scalar rects, to use for culling per-segment (e.g. cubic).
550 * Since we're hairlining, the "bounds" of the control points isn't necessairly the
551 * limit of where a segment can draw (it might draw up to 1 pixel beyond in aa-hairs).
552 *
553 * Compute the pt-bounds per segment is easy, so we do that, and then inversely adjust
554 * the culling bounds so we can just do a straight compare per segment.
555 *
556 * insetClip is use for quick-accept (i.e. the segment is not clipped), so we inset
557 * it from the clip-bounds (since segment bounds can be off by 1).
558 *
559 * outsetClip is used for quick-reject (i.e. the segment is entirely outside), so we
560 * outset it from the clip-bounds.
561 */
562 insetStorage.set(clip->getBounds());
563 outsetStorage = insetStorage.makeOutset(1, 1);
564 insetStorage.inset(1, 1);
565 if (is_inverted(insetStorage)) {
566 /*
567 * our bounds checks assume the rects are never inverted. If insetting has
568 * created that, we assume that the area is too small to safely perform a
569 * quick-accept, so we just mark the rect as empty (so the quick-accept check
570 * will always fail.
571 */
572 insetStorage.setEmpty(); // just so we don't pass an inverted rect
573 }
574 if (rclip.isRect()) {
575 insetClip = &insetStorage;
576 }
577 outsetClip = &outsetStorage;
578 }
579 }
580
583 SkPoint pts[4], firstPt, lastPt;
584 SkPath::Verb prevVerb;
586
587 if (SkPaint::kButt_Cap != capStyle) {
588 prevVerb = SkPath::kDone_Verb;
589 }
590 while (iter != end) {
591 auto [pathVerb, pathPts, w] = *iter++;
592 SkPath::Verb verb = (SkPath::Verb)pathVerb;
593 SkPath::Verb nextVerb = (iter != end) ? (SkPath::Verb)iter.peekVerb() : SkPath::kDone_Verb;
594 memcpy(pts, pathPts, SkPathPriv::PtsInIter(verb) * sizeof(SkPoint));
595 switch (verb) {
597 firstPt = lastPt = pts[0];
598 break;
600 if (SkPaint::kButt_Cap != capStyle) {
601 extend_pts<capStyle>(prevVerb, nextVerb, pts, 2);
602 }
603 lineproc(pts, 2, clip, blitter);
604 lastPt = pts[1];
605 break;
607 if (SkPaint::kButt_Cap != capStyle) {
608 extend_pts<capStyle>(prevVerb, nextVerb, pts, 3);
609 }
610 hairquad(pts, clip, insetClip, outsetClip, blitter, compute_quad_level(pts), lineproc);
611 lastPt = pts[2];
612 break;
613 case SkPath::kConic_Verb: {
614 if (SkPaint::kButt_Cap != capStyle) {
615 extend_pts<capStyle>(prevVerb, nextVerb, pts, 3);
616 }
617 // how close should the quads be to the original conic?
618 const SkScalar tol = SK_Scalar1 / 4;
619 const SkPoint* quadPts = converter.computeQuads(pts, *w, tol);
620 for (int i = 0; i < converter.countQuads(); ++i) {
621 int level = compute_quad_level(quadPts);
622 hairquad(quadPts, clip, insetClip, outsetClip, blitter, level, lineproc);
623 quadPts += 2;
624 }
625 lastPt = pts[2];
626 break;
627 }
628 case SkPath::kCubic_Verb: {
629 if (SkPaint::kButt_Cap != capStyle) {
630 extend_pts<capStyle>(prevVerb, nextVerb, pts, 4);
631 }
632 haircubic(pts, clip, insetClip, outsetClip, blitter, kMaxCubicSubdivideLevel, lineproc);
633 lastPt = pts[3];
634 } break;
636 pts[0] = lastPt;
637 pts[1] = firstPt;
638 if (SkPaint::kButt_Cap != capStyle && prevVerb == SkPath::kMove_Verb) {
639 // cap moveTo/close to match svg expectations for degenerate segments
640 extend_pts<capStyle>(prevVerb, nextVerb, pts, 2);
641 }
642 lineproc(pts, 2, clip, blitter);
643 break;
645 break;
646 }
647 if (SkPaint::kButt_Cap != capStyle) {
648 if (prevVerb == SkPath::kMove_Verb &&
649 verb >= SkPath::kLine_Verb && verb <= SkPath::kCubic_Verb) {
650 firstPt = pts[0]; // the curve moved the initial point, so close to it instead
651 }
652 prevVerb = verb;
653 }
654 }
655}
static void haircubic(const SkPoint pts[4], const SkRegion *clip, const SkRect *insetClip, const SkRect *outsetClip, SkBlitter *blitter, int level, SkScan::HairRgnProc lineproc)
static void hairquad(const SkPoint pts[3], const SkRegion *clip, const SkRect *insetClip, const SkRect *outsetClip, SkBlitter *blitter, int level, SkScan::HairRgnProc lineproc)
static int compute_quad_level(const SkPoint pts[3])
void init(const SkRasterClip &, SkBlitter *)
const SkRegion & getRgn() const
Definition: SkRasterClip.h:175
SkBlitter * getBlitter()
Definition: SkRasterClip.h:179
@ kButt_Cap
no stroke extension
Definition: SkPaint.h:334
static int PtsInIter(unsigned verb)
Definition: SkPathPriv.h:305
SkPath::RangeIter RangeIter
Definition: SkPathPriv.h:164
const SkRect & getBounds() const
Definition: SkPath.cpp:430
@ kConic_Verb
Definition: SkPath.h:1469
@ kCubic_Verb
Definition: SkPath.h:1470
@ kQuad_Verb
Definition: SkPath.h:1468
@ kLine_Verb
Definition: SkPath.h:1467
const SkRegion & bwRgn() const
Definition: SkRasterClip.h:44
bool quickContains(const SkIRect &rect) const
Definition: SkRasterClip.h:76
bool isRect() const
Definition: SkRasterClip.h:52
bool isBW() const
Definition: SkRasterClip.h:42
bool quickReject(const SkIRect &rect) const
Definition: SkRasterClip.h:85
glong glong end
string converter
Definition: cacheimages.py:19
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
SkScalar w
Definition: SkRect.h:32
SkPath::RangeIter end()
Definition: SkPathPriv.h:187
SkPath::RangeIter begin()
Definition: SkPathPriv.h:186
void inset(float dx, float dy)
Definition: SkRect.h:1060
SkRect makeOutset(float dx, float dy) const
Definition: SkRect.h:1002
void set(const SkIRect &src)
Definition: SkRect.h:849
void setEmpty()
Definition: SkRect.h:842

◆ hair_quad()

static void hair_quad ( const SkPoint  pts[3],
const SkRegion clip,
SkBlitter blitter,
int  level,
SkScan::HairRgnProc  lineproc 
)
static

Definition at line 257 of file SkScan_Hairline.cpp.

258 {
260
261 SkQuadCoeff coeff(pts);
262
263 const int lines = 1 << level;
264 float2 t(0);
265 float2 dt(SK_Scalar1 / lines);
266
267 SkPoint tmp[(1 << kMaxQuadSubdivideLevel) + 1];
268 SkASSERT((unsigned)lines < std::size(tmp));
269
270 tmp[0] = pts[0];
271 float2 A = coeff.fA;
272 float2 B = coeff.fB;
273 float2 C = coeff.fC;
274 for (int i = 1; i < lines; ++i) {
275 t = t + dt;
276 ((A * t + B) * t + C).store(&tmp[i]);
277 }
278 tmp[lines] = pts[2];
279 lineproc(tmp, lines + 1, clip, blitter);
280}

◆ haircubic()

static void haircubic ( const SkPoint  pts[4],
const SkRegion clip,
const SkRect insetClip,
const SkRect outsetClip,
SkBlitter blitter,
int  level,
SkScan::HairRgnProc  lineproc 
)
inlinestatic

Definition at line 428 of file SkScan_Hairline.cpp.

429 {
430 if (insetClip) {
431 SkASSERT(outsetClip);
433 if (!geometric_overlap(*outsetClip, bounds)) {
434 return;
435 } else if (geometric_contains(*insetClip, bounds)) {
436 clip = nullptr;
437 }
438 }
439
441 hair_cubic(pts, clip, blitter, lineproc);
442 } else {
443 SkPoint tmp[13];
444 SkScalar tValues[3];
445
446 int count = SkChopCubicAtMaxCurvature(pts, tmp, tValues);
447 for (int i = 0; i < count; i++) {
448 hair_cubic(&tmp[i * 3], clip, blitter, lineproc);
449 }
450 }
451}
int count
Definition: FontMgrTest.cpp:50
int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], SkScalar tValues[3])
static bool quick_cubic_niceness_check(const SkPoint pts[4])
static SkRect compute_nocheck_cubic_bounds(const SkPoint pts[4])
static bool geometric_overlap(const SkRect &a, const SkRect &b)
static void hair_cubic(const SkPoint pts[4], const SkRegion *clip, SkBlitter *blitter, SkScan::HairRgnProc lineproc)
static bool geometric_contains(const SkRect &outer, const SkRect &inner)
Optional< SkRect > bounds
Definition: SkRecords.h:189

◆ hairquad()

static void hairquad ( const SkPoint  pts[3],
const SkRegion clip,
const SkRect insetClip,
const SkRect outsetClip,
SkBlitter blitter,
int  level,
SkScan::HairRgnProc  lineproc 
)
inlinestatic

Definition at line 315 of file SkScan_Hairline.cpp.

316 {
317 if (insetClip) {
318 SkASSERT(outsetClip);
320 if (!geometric_overlap(*outsetClip, bounds)) {
321 return;
322 } else if (geometric_contains(*insetClip, bounds)) {
323 clip = nullptr;
324 }
325 }
326
327 hair_quad(pts, clip, blitter, level, lineproc);
328}
static void hair_quad(const SkPoint pts[3], const SkRegion *clip, SkBlitter *blitter, int level, SkScan::HairRgnProc lineproc)
static SkRect compute_nocheck_quad_bounds(const SkPoint pts[3])

◆ horiline()

static void horiline ( int  x,
int  stopx,
SkFixed  fy,
SkFixed  dy,
SkBlitter blitter 
)
static

Definition at line 36 of file SkScan_Hairline.cpp.

37 {
38 SkASSERT(x < stopx);
39
40 do {
41 blitter->blitH(x, fy >> 16, 1);
42 fy += dy;
43 } while (++x < stopx);
44}
virtual void blitH(int x, int y, int width)=0
Blit a horizontal run of one or more pixels.

◆ is_inverted()

static bool is_inverted ( const SkRect r)
static

Definition at line 295 of file SkScan_Hairline.cpp.

295 {
296 return r.fLeft > r.fRight || r.fTop > r.fBottom;
297}

◆ lt_90()

static bool lt_90 ( SkPoint  p0,
SkPoint  pivot,
SkPoint  p2 
)
static

Definition at line 360 of file SkScan_Hairline.cpp.

360 {
361 return SkVector::DotProduct(p0 - pivot, p2 - pivot) >= 0;
362}
static float DotProduct(const SkVector &a, const SkVector &b)
Definition: SkPoint_impl.h:518

◆ max_component()

static SkScalar max_component ( const float2 value)
inlinestatic

Definition at line 330 of file SkScan_Hairline.cpp.

330 {
331 SkScalar components[2];
332 value.store(components);
333 return std::max(components[0], components[1]);
334}
uint8_t value

◆ quick_cubic_niceness_check()

static bool quick_cubic_niceness_check ( const SkPoint  pts[4])
static

Definition at line 365 of file SkScan_Hairline.cpp.

365 {
366 return lt_90(pts[1], pts[0], pts[3]) &&
367 lt_90(pts[2], pts[0], pts[3]) &&
368 lt_90(pts[1], pts[3], pts[0]) &&
369 lt_90(pts[2], pts[3], pts[0]);
370}
static bool lt_90(SkPoint p0, SkPoint pivot, SkPoint p2)

◆ vertline()

static void vertline ( int  y,
int  stopy,
SkFixed  fx,
SkFixed  dx,
SkBlitter blitter 
)
static

Definition at line 46 of file SkScan_Hairline.cpp.

47 {
48 SkASSERT(y < stopy);
49
50 do {
51 blitter->blitH(fx >> 16, y, 1);
52 fx += dx;
53 } while (++y < stopy);
54}
double y