Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Macros | Typedefs | Functions
SkScan_Antihair.cpp File Reference
#include "include/core/SkColorPriv.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/SkCPUTypes.h"
#include "include/private/base/SkFixed.h"
#include "include/private/base/SkMath.h"
#include "include/private/base/SkPoint_impl.h"
#include "include/private/base/SkSafe32.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkBlitter.h"
#include "src/core/SkFDot6.h"
#include "src/core/SkLineClipper.h"
#include "src/core/SkRasterClip.h"
#include "src/core/SkScan.h"
#include <algorithm>
#include <cstdint>

Go to the source code of this file.

Classes

class  SkAntiHairBlitter
 
class  HLine_SkAntiHairBlitter
 
class  Horish_SkAntiHairBlitter
 
class  VLine_SkAntiHairBlitter
 
class  Vertish_SkAntiHairBlitter
 

Macros

#define OUTSET_BEFORE_CLIP_TEST   true
 
#define HLINE_STACK_BUFFER   100
 
#define ApplyGamma(table, alpha)   SkToU8(alpha)
 
#define SkBITCOUNT(x)   (sizeof(x) << 3)
 
#define SkAlphaMulRound(a, b)   SkMulDiv255Round(a, b)
 

Typedefs

typedef int FDot8
 

Functions

static int SmallDot6Scale (int value, int dot6)
 
static void call_hline_blitter (SkBlitter *blitter, int x, int y, int count, U8CPU alpha)
 
static SkFixed fastfixdiv (SkFDot6 a, SkFDot6 b)
 
static int bad_int (int x)
 
static int any_bad_ints (int a, int b, int c, int d)
 
static int contribution_64 (SkFDot6 ordinate)
 
static void do_anti_hairline (SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, const SkIRect *clip, SkBlitter *blitter)
 
static FDot8 SkFixedToFDot8 (SkFixed x)
 
static void do_scanline (FDot8 L, int top, FDot8 R, U8CPU alpha, SkBlitter *blitter)
 
static void antifilldot8 (FDot8 L, FDot8 T, FDot8 R, FDot8 B, SkBlitter *blitter, bool fillInner)
 
static void antifillrect (const SkXRect &xr, SkBlitter *blitter)
 
static void antifillrect (const SkRect &r, SkBlitter *blitter)
 
static void fillcheckrect (int L, int T, int R, int B, SkBlitter *blitter)
 
static FDot8 SkScalarToFDot8 (SkScalar x)
 
static int FDot8Floor (FDot8 x)
 
static int FDot8Ceil (FDot8 x)
 
static U8CPU InvAlphaMul (U8CPU a, U8CPU b)
 
static void inner_scanline (FDot8 L, int top, FDot8 R, U8CPU alpha, SkBlitter *blitter)
 
static void innerstrokedot8 (FDot8 L, FDot8 T, FDot8 R, FDot8 B, SkBlitter *blitter)
 
static void align_thin_stroke (FDot8 &edge1, FDot8 &edge2)
 

Macro Definition Documentation

◆ ApplyGamma

#define ApplyGamma (   table,
  alpha 
)    SkToU8(alpha)

Definition at line 74 of file SkScan_Antihair.cpp.

◆ HLINE_STACK_BUFFER

#define HLINE_STACK_BUFFER   100

Definition at line 43 of file SkScan_Antihair.cpp.

◆ OUTSET_BEFORE_CLIP_TEST

#define OUTSET_BEFORE_CLIP_TEST   true

Definition at line 41 of file SkScan_Antihair.cpp.

◆ SkAlphaMulRound

#define SkAlphaMulRound (   a,
  b 
)    SkMulDiv255Round(a, b)

Definition at line 833 of file SkScan_Antihair.cpp.

◆ SkBITCOUNT

#define SkBITCOUNT (   x)    (sizeof(x) << 3)

Definition at line 274 of file SkScan_Antihair.cpp.

Typedef Documentation

◆ FDot8

typedef int FDot8

Definition at line 634 of file SkScan_Antihair.cpp.

Function Documentation

◆ align_thin_stroke()

static void align_thin_stroke ( FDot8 edge1,
FDot8 edge2 
)
inlinestatic

Definition at line 926 of file SkScan_Antihair.cpp.

926 {
927 SkASSERT(edge1 <= edge2);
928
929 if (FDot8Floor(edge1) == FDot8Floor(edge2)) {
930 edge2 -= (edge1 & 0xFF);
931 edge1 &= ~0xFF;
932 }
933}
#define SkASSERT(cond)
Definition SkAssert.h:116
static int FDot8Floor(FDot8 x)

◆ antifilldot8()

static void antifilldot8 ( FDot8  L,
FDot8  T,
FDot8  R,
FDot8  B,
SkBlitter blitter,
bool  fillInner 
)
static

Definition at line 666 of file SkScan_Antihair.cpp.

667 {
668 // check for empty now that we're in our reduced precision space
669 if (L >= R || T >= B) {
670 return;
671 }
672 int top = T >> 8;
673 if (top == ((B - 1) >> 8)) { // just one scanline high
674 do_scanline(L, top, R, B - T - 1, blitter);
675 return;
676 }
677
678 if (T & 0xFF) {
679 do_scanline(L, top, R, 256 - (T & 0xFF), blitter);
680 top += 1;
681 }
682
683 int bot = B >> 8;
684 int height = bot - top;
685 if (height > 0) {
686 int left = L >> 8;
687 if (left == ((R - 1) >> 8)) { // just 1-pixel wide
688 blitter->blitV(left, top, height, R - L - 1);
689 } else {
690 if (L & 0xFF) {
691 blitter->blitV(left, top, height, 256 - (L & 0xFF));
692 left += 1;
693 }
694 int rite = R >> 8;
695 int width = rite - left;
696 if (width > 0 && fillInner) {
697 blitter->blitRect(left, top, width, height);
698 }
699 if (R & 0xFF) {
700 blitter->blitV(rite, top, height, R & 0xFF);
701 }
702 }
703 }
704
705 if (B & 0xFF) {
706 do_scanline(L, bot, R, B & 0xFF, blitter);
707 }
708}
static bool left(const SkPoint &p0, const SkPoint &p1)
static void do_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, SkBlitter *blitter)
virtual void blitV(int x, int y, int height, SkAlpha alpha)
Blit a vertical run of pixels with a constant alpha value.
virtual void blitRect(int x, int y, int width, int height)
Blit a solid rectangle one or more pixels wide.
#define R(r)
#define T
int32_t height
int32_t width

◆ antifillrect() [1/2]

static void antifillrect ( const SkRect r,
SkBlitter blitter 
)
static

Definition at line 778 of file SkScan_Antihair.cpp.

778 {
779 SkXRect xr;
780
781 XRect_set(&xr, r);
782 antifillrect(xr, blitter);
783}
static void XRect_set(SkXRect *xr, const SkIRect &src)
Definition SkScan.h:98
static void antifillrect(const SkXRect &xr, SkBlitter *blitter)

◆ antifillrect() [2/2]

static void antifillrect ( const SkXRect xr,
SkBlitter blitter 
)
static

Definition at line 710 of file SkScan_Antihair.cpp.

710 {
713 blitter, true);
714}
static void antifilldot8(FDot8 L, FDot8 T, FDot8 R, FDot8 B, SkBlitter *blitter, bool fillInner)
static FDot8 SkFixedToFDot8(SkFixed x)
int32_t fBottom
larger y-axis bounds
Definition SkRect.h:36
int32_t fTop
smaller y-axis bounds
Definition SkRect.h:34
int32_t fLeft
smaller x-axis bounds
Definition SkRect.h:33
int32_t fRight
larger x-axis bounds
Definition SkRect.h:35

◆ any_bad_ints()

static int any_bad_ints ( int  a,
int  b,
int  c,
int  d 
)
static

Definition at line 282 of file SkScan_Antihair.cpp.

282 {
283 return (bad_int(a) | bad_int(b) | bad_int(c) | bad_int(d)) >> (SkBITCOUNT(int) - 1);
284}
static int bad_int(int x)
#define SkBITCOUNT(x)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
static bool b
struct MyStruct a[10]

◆ bad_int()

static int bad_int ( int  x)
inlinestatic

Definition at line 278 of file SkScan_Antihair.cpp.

278 {
279 return x & -x;
280}
double x

◆ call_hline_blitter()

static void call_hline_blitter ( SkBlitter blitter,
int  x,
int  y,
int  count,
U8CPU  alpha 
)
static

Definition at line 79 of file SkScan_Antihair.cpp.

80 {
81 SkASSERT(count > 0);
82
83 int16_t runs[HLINE_STACK_BUFFER + 1];
84 uint8_t aa[HLINE_STACK_BUFFER];
85
86 do {
87 // In theory, we should be able to just do this once (outside of the loop),
88 // since aa[] and runs[] are supposed" to be const when we call the blitter.
89 // In reality, some wrapper-blitters (e.g. SkRgnClipBlitter) cast away that
90 // constness, and modify the buffers in-place. Hence the need to be defensive
91 // here and reseed the aa value.
92 aa[0] = ApplyGamma(gGammaTable, alpha);
93
94 int n = count;
95 if (n > HLINE_STACK_BUFFER) {
97 }
98 runs[0] = SkToS16(n);
99 runs[n] = 0;
100 blitter->blitAntiH(x, y, aa, runs);
101 x += n;
102 count -= n;
103 } while (count > 0);
104}
int count
#define ApplyGamma(table, alpha)
#define HLINE_STACK_BUFFER
constexpr int16_t SkToS16(S x)
Definition SkTo.h:23
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])=0
double y

◆ contribution_64()

static int contribution_64 ( SkFDot6  ordinate)
static

Definition at line 308 of file SkScan_Antihair.cpp.

308 {
309#if 0
310 int result = ordinate & 63;
311 if (0 == result) {
312 result = 64;
313 }
314#else
315 int result = ((ordinate - 1) & 63) + 1;
316#endif
317 SkASSERT(result > 0 && result <= 64);
318 return result;
319}
GAsyncResult * result

◆ do_anti_hairline()

static void do_anti_hairline ( SkFDot6  x0,
SkFDot6  y0,
SkFDot6  x1,
SkFDot6  y1,
const SkIRect clip,
SkBlitter blitter 
)
static

Definition at line 321 of file SkScan_Antihair.cpp.

322 {
323 // check for integer NaN (0x80000000) which we can't handle (can't negate it)
324 // It appears typically from a huge float (inf or nan) being converted to int.
325 // If we see it, just don't draw.
326 if (any_bad_ints(x0, y0, x1, y1)) {
327 return;
328 }
329
330 // The caller must clip the line to [-32767.0 ... 32767.0] ahead of time
331 // (in dot6 format)
332 SkASSERT(canConvertFDot6ToFixed(x0));
333 SkASSERT(canConvertFDot6ToFixed(y0));
334 SkASSERT(canConvertFDot6ToFixed(x1));
335 SkASSERT(canConvertFDot6ToFixed(y1));
336
337 if (SkAbs32(x1 - x0) > SkIntToFDot6(511) || SkAbs32(y1 - y0) > SkIntToFDot6(511)) {
338 /* instead of (x0 + x1) >> 1, we shift each separately. This is less
339 precise, but avoids overflowing the intermediate result if the
340 values are huge. A better fix might be to clip the original pts
341 directly (i.e. do the divide), so we don't spend time subdividing
342 huge lines at all.
343 */
344 int hx = (x0 >> 1) + (x1 >> 1);
345 int hy = (y0 >> 1) + (y1 >> 1);
346 do_anti_hairline(x0, y0, hx, hy, clip, blitter);
347 do_anti_hairline(hx, hy, x1, y1, clip, blitter);
348 return;
349 }
350
351 int scaleStart, scaleStop;
352 int istart, istop;
353 SkFixed fstart, slope;
354
355 HLine_SkAntiHairBlitter hline_blitter;
356 Horish_SkAntiHairBlitter horish_blitter;
357 VLine_SkAntiHairBlitter vline_blitter;
358 Vertish_SkAntiHairBlitter vertish_blitter;
359 SkAntiHairBlitter* hairBlitter = nullptr;
360
361 if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) { // mostly horizontal
362 if (x0 > x1) { // we want to go left-to-right
363 using std::swap;
364 swap(x0, x1);
365 swap(y0, y1);
366 }
367
368 istart = SkFDot6Floor(x0);
369 istop = SkFDot6Ceil(x1);
370 fstart = SkFDot6ToFixed(y0);
371 if (y0 == y1) { // completely horizontal, take fast case
372 slope = 0;
373 hairBlitter = &hline_blitter;
374 } else {
375 slope = fastfixdiv(y1 - y0, x1 - x0);
376 SkASSERT(slope >= -SK_Fixed1 && slope <= SK_Fixed1);
377 fstart += (slope * (32 - (x0 & 63)) + 32) >> 6;
378 hairBlitter = &horish_blitter;
379 }
380
381 SkASSERT(istop > istart);
382 if (istop - istart == 1) {
383 // we are within a single pixel
384 scaleStart = x1 - x0;
385 SkASSERT(scaleStart >= 0 && scaleStart <= 64);
386 scaleStop = 0;
387 } else {
388 scaleStart = 64 - (x0 & 63);
389 scaleStop = x1 & 63;
390 }
391
392 if (clip){
393 if (istart >= clip->fRight || istop <= clip->fLeft) {
394 return;
395 }
396 if (istart < clip->fLeft) {
397 fstart += slope * (clip->fLeft - istart);
398 istart = clip->fLeft;
399 scaleStart = 64;
400 if (istop - istart == 1) {
401 // we are within a single pixel
402 scaleStart = contribution_64(x1);
403 scaleStop = 0;
404 }
405 }
406 if (istop > clip->fRight) {
407 istop = clip->fRight;
408 scaleStop = 0; // so we don't draw this last column
409 }
410
411 SkASSERT(istart <= istop);
412 if (istart == istop) {
413 return;
414 }
415 // now test if our Y values are completely inside the clip
416 int top, bottom;
417 if (slope >= 0) { // T2B
418 top = SkFixedFloorToInt(fstart - SK_FixedHalf);
419 bottom = SkFixedCeilToInt(fstart + (istop - istart - 1) * slope + SK_FixedHalf);
420 } else { // B2T
421 bottom = SkFixedCeilToInt(fstart + SK_FixedHalf);
422 top = SkFixedFloorToInt(fstart + (istop - istart - 1) * slope - SK_FixedHalf);
423 }
424#ifdef OUTSET_BEFORE_CLIP_TEST
425 top -= 1;
426 bottom += 1;
427#endif
428 if (top >= clip->fBottom || bottom <= clip->fTop) {
429 return;
430 }
431 if (clip->fTop <= top && clip->fBottom >= bottom) {
432 clip = nullptr;
433 }
434 }
435 } else { // mostly vertical
436 if (y0 > y1) { // we want to go top-to-bottom
437 using std::swap;
438 swap(x0, x1);
439 swap(y0, y1);
440 }
441
442 istart = SkFDot6Floor(y0);
443 istop = SkFDot6Ceil(y1);
444 fstart = SkFDot6ToFixed(x0);
445 if (x0 == x1) {
446 if (y0 == y1) { // are we zero length?
447 return; // nothing to do
448 }
449 slope = 0;
450 hairBlitter = &vline_blitter;
451 } else {
452 slope = fastfixdiv(x1 - x0, y1 - y0);
453 SkASSERT(slope <= SK_Fixed1 && slope >= -SK_Fixed1);
454 fstart += (slope * (32 - (y0 & 63)) + 32) >> 6;
455 hairBlitter = &vertish_blitter;
456 }
457
458 SkASSERT(istop > istart);
459 if (istop - istart == 1) {
460 // we are within a single pixel
461 scaleStart = y1 - y0;
462 SkASSERT(scaleStart >= 0 && scaleStart <= 64);
463 scaleStop = 0;
464 } else {
465 scaleStart = 64 - (y0 & 63);
466 scaleStop = y1 & 63;
467 }
468
469 if (clip) {
470 if (istart >= clip->fBottom || istop <= clip->fTop) {
471 return;
472 }
473 if (istart < clip->fTop) {
474 fstart += slope * (clip->fTop - istart);
475 istart = clip->fTop;
476 scaleStart = 64;
477 if (istop - istart == 1) {
478 // we are within a single pixel
479 scaleStart = contribution_64(y1);
480 scaleStop = 0;
481 }
482 }
483 if (istop > clip->fBottom) {
484 istop = clip->fBottom;
485 scaleStop = 0; // so we don't draw this last row
486 }
487
488 SkASSERT(istart <= istop);
489 if (istart == istop)
490 return;
491
492 // now test if our X values are completely inside the clip
493 int left, right;
494 if (slope >= 0) { // L2R
496 right = SkFixedCeilToInt(fstart + (istop - istart - 1) * slope + SK_FixedHalf);
497 } else { // R2L
499 left = SkFixedFloorToInt(fstart + (istop - istart - 1) * slope - SK_FixedHalf);
500 }
501#ifdef OUTSET_BEFORE_CLIP_TEST
502 left -= 1;
503 right += 1;
504#endif
505 if (left >= clip->fRight || right <= clip->fLeft) {
506 return;
507 }
508 if (clip->fLeft <= left && clip->fRight >= right) {
509 clip = nullptr;
510 }
511 }
512 }
513
514 SkRectClipBlitter rectClipper;
515 if (clip) {
516 rectClipper.init(blitter, *clip);
517 blitter = &rectClipper;
518 }
519
520 SkASSERT(hairBlitter);
521 hairBlitter->setup(blitter);
522
523#ifdef SK_DEBUG
524 if (scaleStart > 0 && scaleStop > 0) {
525 // be sure we don't draw twice in the same pixel
526 SkASSERT(istart < istop - 1);
527 }
528#endif
529
530 fstart = hairBlitter->drawCap(istart, fstart, slope, scaleStart);
531 istart += 1;
532 int fullSpans = istop - istart - (scaleStop > 0);
533 if (fullSpans > 0) {
534 fstart = hairBlitter->drawLine(istart, istart + fullSpans, fstart, slope);
535 }
536 if (scaleStop > 0) {
537 hairBlitter->drawCap(istop - 1, fstart, slope, scaleStop);
538 }
539}
#define SkFDot6Ceil(x)
Definition SkFDot6.h:53
#define SkFDot6Floor(x)
Definition SkFDot6.h:52
SkFixed SkFDot6ToFixed(SkFDot6 x)
Definition SkFDot6.h:58
#define SkIntToFDot6(x)
Definition SkFDot6.h:49
#define SkFixedCeilToInt(x)
Definition SkFixed.h:77
int32_t SkFixed
Definition SkFixed.h:25
#define SK_Fixed1
Definition SkFixed.h:26
#define SK_FixedHalf
Definition SkFixed.h:27
#define SkFixedFloorToInt(x)
Definition SkFixed.h:78
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
static bool right(const SkPoint &p0, const SkPoint &p1)
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition SkRefCnt.h:341
static int32_t SkAbs32(int32_t value)
Definition SkSafe32.h:41
static int any_bad_ints(int a, int b, int c, int d)
static SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b)
static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, const SkIRect *clip, SkBlitter *blitter)
static int contribution_64(SkFDot6 ordinate)
virtual SkFixed drawCap(int x, SkFixed fy, SkFixed slope, int mod64)=0
void setup(SkBlitter *blitter)
virtual SkFixed drawLine(int x, int stopx, SkFixed fy, SkFixed slope)=0
void init(SkBlitter *blitter, const SkIRect &clipRect)
Definition SkBlitter.h:183

◆ do_scanline()

static void do_scanline ( FDot8  L,
int  top,
FDot8  R,
U8CPU  alpha,
SkBlitter blitter 
)
static

Definition at line 640 of file SkScan_Antihair.cpp.

641 {
642 SkASSERT(L < R);
643
644 if ((L >> 8) == ((R - 1) >> 8)) { // 1x1 pixel
645 blitter->blitV(L >> 8, top, 1, SkAlphaMul(alpha, R - L));
646 return;
647 }
648
649 int left = L >> 8;
650
651 if (L & 0xFF) {
652 blitter->blitV(left, top, 1, SkAlphaMul(alpha, 256 - (L & 0xFF)));
653 left += 1;
654 }
655
656 int rite = R >> 8;
657 int width = rite - left;
658 if (width > 0) {
659 call_hline_blitter(blitter, left, top, width, alpha);
660 }
661 if (R & 0xFF) {
662 blitter->blitV(rite, top, 1, SkAlphaMul(alpha, R & 0xFF));
663 }
664}
#define SkAlphaMul(value, alpha256)
Definition SkColorPriv.h:34
static void call_hline_blitter(SkBlitter *blitter, int x, int y, int count, U8CPU alpha)

◆ fastfixdiv()

static SkFixed fastfixdiv ( SkFDot6  a,
SkFDot6  b 
)
inlinestatic

Definition at line 268 of file SkScan_Antihair.cpp.

268 {
269 SkASSERT((SkLeftShift(a, 16) >> 16) == a);
270 SkASSERT(b != 0);
271 return SkLeftShift(a, 16) / b;
272}
static constexpr int32_t SkLeftShift(int32_t value, int32_t shift)
Definition SkMath.h:37

◆ FDot8Ceil()

static int FDot8Ceil ( FDot8  x)
inlinestatic

Definition at line 850 of file SkScan_Antihair.cpp.

850 {
851 return (x + 0xFF) >> 8;
852}

◆ FDot8Floor()

static int FDot8Floor ( FDot8  x)
inlinestatic

Definition at line 846 of file SkScan_Antihair.cpp.

846 {
847 return x >> 8;
848}

◆ fillcheckrect()

static void fillcheckrect ( int  L,
int  T,
int  R,
int  B,
SkBlitter blitter 
)
static

Definition at line 836 of file SkScan_Antihair.cpp.

836 {
837 if (L < R && T < B) {
838 blitter->blitRect(L, T, R - L, B - T);
839 }
840}

◆ inner_scanline()

static void inner_scanline ( FDot8  L,
int  top,
FDot8  R,
U8CPU  alpha,
SkBlitter blitter 
)
static

Definition at line 861 of file SkScan_Antihair.cpp.

862 {
863 SkASSERT(L < R);
864
865 if ((L >> 8) == ((R - 1) >> 8)) { // 1x1 pixel
866 FDot8 widClamp = R - L;
867 // border case clamp 256 to 255 instead of going through call_hline_blitter
868 // see skbug/4406
869 widClamp = widClamp - (widClamp >> 8);
870 blitter->blitV(L >> 8, top, 1, InvAlphaMul(alpha, widClamp));
871 return;
872 }
873
874 int left = L >> 8;
875 if (L & 0xFF) {
876 blitter->blitV(left, top, 1, InvAlphaMul(alpha, L & 0xFF));
877 left += 1;
878 }
879
880 int rite = R >> 8;
881 int width = rite - left;
882 if (width > 0) {
883 call_hline_blitter(blitter, left, top, width, alpha);
884 }
885
886 if (R & 0xFF) {
887 blitter->blitV(rite, top, 1, InvAlphaMul(alpha, ~R & 0xFF));
888 }
889}
int FDot8
static U8CPU InvAlphaMul(U8CPU a, U8CPU b)

◆ innerstrokedot8()

static void innerstrokedot8 ( FDot8  L,
FDot8  T,
FDot8  R,
FDot8  B,
SkBlitter blitter 
)
static

Definition at line 891 of file SkScan_Antihair.cpp.

892 {
893 SkASSERT(L < R && T < B);
894
895 int top = T >> 8;
896 if (top == ((B - 1) >> 8)) { // just one scanline high
897 // We want the inverse of B-T, since we're the inner-stroke
898 int alpha = 256 - (B - T);
899 if (alpha) {
900 inner_scanline(L, top, R, alpha, blitter);
901 }
902 return;
903 }
904
905 if (T & 0xFF) {
906 inner_scanline(L, top, R, T & 0xFF, blitter);
907 top += 1;
908 }
909
910 int bot = B >> 8;
911 int height = bot - top;
912 if (height > 0) {
913 if (L & 0xFF) {
914 blitter->blitV(L >> 8, top, height, L & 0xFF);
915 }
916 if (R & 0xFF) {
917 blitter->blitV(R >> 8, top, height, ~R & 0xFF);
918 }
919 }
920
921 if (B & 0xFF) {
922 inner_scanline(L, bot, R, ~B & 0xFF, blitter);
923 }
924}
static void inner_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, SkBlitter *blitter)

◆ InvAlphaMul()

static U8CPU InvAlphaMul ( U8CPU  a,
U8CPU  b 
)
inlinestatic

Definition at line 855 of file SkScan_Antihair.cpp.

855 {
856 // need precise rounding (not just SkAlphaMul) so that values like
857 // a=228, b=252 don't overflow the result
858 return SkToU8(a + b - SkAlphaMulRound(a, b));
859}
#define SkAlphaMulRound(a, b)
constexpr uint8_t SkToU8(S x)
Definition SkTo.h:22

◆ SkFixedToFDot8()

static FDot8 SkFixedToFDot8 ( SkFixed  x)
inlinestatic

Definition at line 636 of file SkScan_Antihair.cpp.

636 {
637 return (x + 0x80) >> 8;
638}

◆ SkScalarToFDot8()

static FDot8 SkScalarToFDot8 ( SkScalar  x)
inlinestatic

Definition at line 842 of file SkScan_Antihair.cpp.

842 {
843 return (int)(x * 256);
844}

◆ SmallDot6Scale()

static int SmallDot6Scale ( int  value,
int  dot6 
)
inlinestatic

Definition at line 45 of file SkScan_Antihair.cpp.

45 {
46 SkASSERT((int16_t)value == value);
47 SkASSERT((unsigned)dot6 <= 64);
48 return (value * dot6) >> 6;
49}