1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/core/SkScanPriv.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 11cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 12cb93a386Sopenharmony_ci#include "include/core/SkRegion.h" 13cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 14cb93a386Sopenharmony_ci#include "src/core/SkAntiRun.h" 15cb93a386Sopenharmony_ci#include "src/core/SkBlitter.h" 16cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci#ifdef SK_ENABLE_PATH_COMPLEXITY_DFX 19cb93a386Sopenharmony_ci#include "src/core/SkPathComplexityDfx.h" 20cb93a386Sopenharmony_ci#endif 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ci#define SHIFT SK_SUPERSAMPLE_SHIFT 23cb93a386Sopenharmony_ci#define SCALE (1 << SHIFT) 24cb93a386Sopenharmony_ci#define MASK (SCALE - 1) 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci/** @file 27cb93a386Sopenharmony_ci We have two techniques for capturing the output of the supersampler: 28cb93a386Sopenharmony_ci - SUPERMASK, which records a large mask-bitmap 29cb93a386Sopenharmony_ci this is often faster for small, complex objects 30cb93a386Sopenharmony_ci - RLE, which records a rle-encoded scanline 31cb93a386Sopenharmony_ci this is often faster for large objects with big spans 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci These blitters use two coordinate systems: 34cb93a386Sopenharmony_ci - destination coordinates, scale equal to the output - often 35cb93a386Sopenharmony_ci abbreviated with 'i' or 'I' in variable names 36cb93a386Sopenharmony_ci - supersampled coordinates, scale equal to the output * SCALE 37cb93a386Sopenharmony_ci */ 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci//#define FORCE_SUPERMASK 40cb93a386Sopenharmony_ci//#define FORCE_RLE 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci/// Base class for a single-pass supersampled blitter. 45cb93a386Sopenharmony_ciclass BaseSuperBlitter : public SkBlitter { 46cb93a386Sopenharmony_cipublic: 47cb93a386Sopenharmony_ci BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, 48cb93a386Sopenharmony_ci const SkIRect& clipBounds, bool isInverse); 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci /// Must be explicitly defined on subclasses. 51cb93a386Sopenharmony_ci void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override { 52cb93a386Sopenharmony_ci SkDEBUGFAIL("How did I get here?"); 53cb93a386Sopenharmony_ci } 54cb93a386Sopenharmony_ci /// May not be called on BaseSuperBlitter because it blits out of order. 55cb93a386Sopenharmony_ci void blitV(int x, int y, int height, SkAlpha alpha) override { 56cb93a386Sopenharmony_ci SkDEBUGFAIL("How did I get here?"); 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ciprotected: 60cb93a386Sopenharmony_ci SkBlitter* fRealBlitter; 61cb93a386Sopenharmony_ci /// Current y coordinate, in destination coordinates. 62cb93a386Sopenharmony_ci int fCurrIY; 63cb93a386Sopenharmony_ci /// Widest row of region to be blitted, in destination coordinates. 64cb93a386Sopenharmony_ci int fWidth; 65cb93a386Sopenharmony_ci /// Leftmost x coordinate in any row, in destination coordinates. 66cb93a386Sopenharmony_ci int fLeft; 67cb93a386Sopenharmony_ci /// Leftmost x coordinate in any row, in supersampled coordinates. 68cb93a386Sopenharmony_ci int fSuperLeft; 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci SkDEBUGCODE(int fCurrX;) 71cb93a386Sopenharmony_ci /// Current y coordinate in supersampled coordinates. 72cb93a386Sopenharmony_ci int fCurrY; 73cb93a386Sopenharmony_ci /// Initial y coordinate (top of bounds). 74cb93a386Sopenharmony_ci int fTop; 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci SkIRect fSectBounds; 77cb93a386Sopenharmony_ci}; 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ciBaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlit, const SkIRect& ir, 80cb93a386Sopenharmony_ci const SkIRect& clipBounds, bool isInverse) { 81cb93a386Sopenharmony_ci fRealBlitter = realBlit; 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci SkIRect sectBounds; 84cb93a386Sopenharmony_ci if (isInverse) { 85cb93a386Sopenharmony_ci // We use the clip bounds instead of the ir, since we may be asked to 86cb93a386Sopenharmony_ci //draw outside of the rect when we're a inverse filltype 87cb93a386Sopenharmony_ci sectBounds = clipBounds; 88cb93a386Sopenharmony_ci } else { 89cb93a386Sopenharmony_ci if (!sectBounds.intersect(ir, clipBounds)) { 90cb93a386Sopenharmony_ci sectBounds.setEmpty(); 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci const int left = sectBounds.left(); 95cb93a386Sopenharmony_ci const int right = sectBounds.right(); 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci fLeft = left; 98cb93a386Sopenharmony_ci fSuperLeft = SkLeftShift(left, SHIFT); 99cb93a386Sopenharmony_ci fWidth = right - left; 100cb93a386Sopenharmony_ci fTop = sectBounds.top(); 101cb93a386Sopenharmony_ci fCurrIY = fTop - 1; 102cb93a386Sopenharmony_ci fCurrY = SkLeftShift(fTop, SHIFT) - 1; 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci SkDEBUGCODE(fCurrX = -1;) 105cb93a386Sopenharmony_ci} 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci/// Run-length-encoded supersampling antialiased blitter. 108cb93a386Sopenharmony_ciclass SuperBlitter : public BaseSuperBlitter { 109cb93a386Sopenharmony_cipublic: 110cb93a386Sopenharmony_ci SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds, 111cb93a386Sopenharmony_ci bool isInverse); 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci ~SuperBlitter() override { 114cb93a386Sopenharmony_ci this->flush(); 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci /// Once fRuns contains a complete supersampled row, flush() blits 118cb93a386Sopenharmony_ci /// it out through the wrapped blitter. 119cb93a386Sopenharmony_ci void flush(); 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci /// Blits a row of pixels, with location and width specified 122cb93a386Sopenharmony_ci /// in supersampled coordinates. 123cb93a386Sopenharmony_ci void blitH(int x, int y, int width) override; 124cb93a386Sopenharmony_ci /// Blits a rectangle of pixels, with location and size specified 125cb93a386Sopenharmony_ci /// in supersampled coordinates. 126cb93a386Sopenharmony_ci void blitRect(int x, int y, int width, int height) override; 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ciprivate: 129cb93a386Sopenharmony_ci // The next three variables are used to track a circular buffer that 130cb93a386Sopenharmony_ci // contains the values used in SkAlphaRuns. These variables should only 131cb93a386Sopenharmony_ci // ever be updated in advanceRuns(), and fRuns should always point to 132cb93a386Sopenharmony_ci // a valid SkAlphaRuns... 133cb93a386Sopenharmony_ci int fRunsToBuffer; 134cb93a386Sopenharmony_ci void* fRunsBuffer; 135cb93a386Sopenharmony_ci int fCurrentRun; 136cb93a386Sopenharmony_ci SkAlphaRuns fRuns; 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci // extra one to store the zero at the end 139cb93a386Sopenharmony_ci int getRunsSz() const { return (fWidth + 1 + (fWidth + 2)/2) * sizeof(int16_t); } 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci // This function updates the fRuns variable to point to the next buffer space 142cb93a386Sopenharmony_ci // with adequate storage for a SkAlphaRuns. It mostly just advances fCurrentRun 143cb93a386Sopenharmony_ci // and resets fRuns to point to an empty scanline. 144cb93a386Sopenharmony_ci void advanceRuns() { 145cb93a386Sopenharmony_ci const size_t kRunsSz = this->getRunsSz(); 146cb93a386Sopenharmony_ci fCurrentRun = (fCurrentRun + 1) % fRunsToBuffer; 147cb93a386Sopenharmony_ci fRuns.fRuns = reinterpret_cast<int16_t*>( 148cb93a386Sopenharmony_ci reinterpret_cast<uint8_t*>(fRunsBuffer) + fCurrentRun * kRunsSz); 149cb93a386Sopenharmony_ci fRuns.fAlpha = reinterpret_cast<SkAlpha*>(fRuns.fRuns + fWidth + 1); 150cb93a386Sopenharmony_ci fRuns.reset(fWidth); 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci int fOffsetX; 154cb93a386Sopenharmony_ci}; 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ciSuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds, 157cb93a386Sopenharmony_ci bool isInverse) 158cb93a386Sopenharmony_ci : BaseSuperBlitter(realBlitter, ir, clipBounds, isInverse) 159cb93a386Sopenharmony_ci{ 160cb93a386Sopenharmony_ci fRunsToBuffer = realBlitter->requestRowsPreserved(); 161cb93a386Sopenharmony_ci fRunsBuffer = realBlitter->allocBlitMemory(fRunsToBuffer * this->getRunsSz()); 162cb93a386Sopenharmony_ci fCurrentRun = -1; 163cb93a386Sopenharmony_ci 164cb93a386Sopenharmony_ci this->advanceRuns(); 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci fOffsetX = 0; 167cb93a386Sopenharmony_ci} 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_civoid SuperBlitter::flush() { 170cb93a386Sopenharmony_ci if (fCurrIY >= fTop) { 171cb93a386Sopenharmony_ci 172cb93a386Sopenharmony_ci SkASSERT(fCurrentRun < fRunsToBuffer); 173cb93a386Sopenharmony_ci if (!fRuns.empty()) { 174cb93a386Sopenharmony_ci // SkDEBUGCODE(fRuns.dump();) 175cb93a386Sopenharmony_ci fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns); 176cb93a386Sopenharmony_ci this->advanceRuns(); 177cb93a386Sopenharmony_ci fOffsetX = 0; 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci fCurrIY = fTop - 1; 181cb93a386Sopenharmony_ci SkDEBUGCODE(fCurrX = -1;) 182cb93a386Sopenharmony_ci } 183cb93a386Sopenharmony_ci} 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci/** coverage_to_partial_alpha() is being used by SkAlphaRuns, which 186cb93a386Sopenharmony_ci *accumulates* SCALE pixels worth of "alpha" in [0,(256/SCALE)] 187cb93a386Sopenharmony_ci to produce a final value in [0, 255] and handles clamping 256->255 188cb93a386Sopenharmony_ci itself, with the same (alpha - (alpha >> 8)) correction as 189cb93a386Sopenharmony_ci coverage_to_exact_alpha(). 190cb93a386Sopenharmony_ci*/ 191cb93a386Sopenharmony_cistatic inline int coverage_to_partial_alpha(int aa) { 192cb93a386Sopenharmony_ci aa <<= 8 - 2*SHIFT; 193cb93a386Sopenharmony_ci return aa; 194cb93a386Sopenharmony_ci} 195cb93a386Sopenharmony_ci 196cb93a386Sopenharmony_ci/** coverage_to_exact_alpha() is being used by our blitter, which wants 197cb93a386Sopenharmony_ci a final value in [0, 255]. 198cb93a386Sopenharmony_ci*/ 199cb93a386Sopenharmony_cistatic inline int coverage_to_exact_alpha(int aa) { 200cb93a386Sopenharmony_ci int alpha = (256 >> SHIFT) * aa; 201cb93a386Sopenharmony_ci // clamp 256->255 202cb93a386Sopenharmony_ci return alpha - (alpha >> 8); 203cb93a386Sopenharmony_ci} 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_civoid SuperBlitter::blitH(int x, int y, int width) { 206cb93a386Sopenharmony_ci SkASSERT(width > 0); 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci int iy = y >> SHIFT; 209cb93a386Sopenharmony_ci SkASSERT(iy >= fCurrIY); 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci x -= fSuperLeft; 212cb93a386Sopenharmony_ci // hack, until I figure out why my cubics (I think) go beyond the bounds 213cb93a386Sopenharmony_ci if (x < 0) { 214cb93a386Sopenharmony_ci width += x; 215cb93a386Sopenharmony_ci x = 0; 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci#ifdef SK_DEBUG 219cb93a386Sopenharmony_ci SkASSERT(y != fCurrY || x >= fCurrX); 220cb93a386Sopenharmony_ci#endif 221cb93a386Sopenharmony_ci SkASSERT(y >= fCurrY); 222cb93a386Sopenharmony_ci if (fCurrY != y) { 223cb93a386Sopenharmony_ci fOffsetX = 0; 224cb93a386Sopenharmony_ci fCurrY = y; 225cb93a386Sopenharmony_ci } 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci if (iy != fCurrIY) { // new scanline 228cb93a386Sopenharmony_ci this->flush(); 229cb93a386Sopenharmony_ci fCurrIY = iy; 230cb93a386Sopenharmony_ci } 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_ci int start = x; 233cb93a386Sopenharmony_ci int stop = x + width; 234cb93a386Sopenharmony_ci 235cb93a386Sopenharmony_ci SkASSERT(start >= 0 && stop > start); 236cb93a386Sopenharmony_ci // integer-pixel-aligned ends of blit, rounded out 237cb93a386Sopenharmony_ci int fb = start & MASK; 238cb93a386Sopenharmony_ci int fe = stop & MASK; 239cb93a386Sopenharmony_ci int n = (stop >> SHIFT) - (start >> SHIFT) - 1; 240cb93a386Sopenharmony_ci 241cb93a386Sopenharmony_ci if (n < 0) { 242cb93a386Sopenharmony_ci fb = fe - fb; 243cb93a386Sopenharmony_ci n = 0; 244cb93a386Sopenharmony_ci fe = 0; 245cb93a386Sopenharmony_ci } else { 246cb93a386Sopenharmony_ci if (fb == 0) { 247cb93a386Sopenharmony_ci n += 1; 248cb93a386Sopenharmony_ci } else { 249cb93a386Sopenharmony_ci fb = SCALE - fb; 250cb93a386Sopenharmony_ci } 251cb93a386Sopenharmony_ci } 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci fOffsetX = fRuns.add(x >> SHIFT, coverage_to_partial_alpha(fb), 254cb93a386Sopenharmony_ci n, coverage_to_partial_alpha(fe), 255cb93a386Sopenharmony_ci (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT), 256cb93a386Sopenharmony_ci fOffsetX); 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci#ifdef SK_DEBUG 259cb93a386Sopenharmony_ci fRuns.assertValid(y & MASK, (1 << (8 - SHIFT))); 260cb93a386Sopenharmony_ci fCurrX = x + width; 261cb93a386Sopenharmony_ci#endif 262cb93a386Sopenharmony_ci} 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ci#if 0 // UNUSED 265cb93a386Sopenharmony_cistatic void set_left_rite_runs(SkAlphaRuns& runs, int ileft, U8CPU leftA, 266cb93a386Sopenharmony_ci int n, U8CPU riteA) { 267cb93a386Sopenharmony_ci SkASSERT(leftA <= 0xFF); 268cb93a386Sopenharmony_ci SkASSERT(riteA <= 0xFF); 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_ci int16_t* run = runs.fRuns; 271cb93a386Sopenharmony_ci uint8_t* aa = runs.fAlpha; 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_ci if (ileft > 0) { 274cb93a386Sopenharmony_ci run[0] = ileft; 275cb93a386Sopenharmony_ci aa[0] = 0; 276cb93a386Sopenharmony_ci run += ileft; 277cb93a386Sopenharmony_ci aa += ileft; 278cb93a386Sopenharmony_ci } 279cb93a386Sopenharmony_ci 280cb93a386Sopenharmony_ci SkASSERT(leftA < 0xFF); 281cb93a386Sopenharmony_ci if (leftA > 0) { 282cb93a386Sopenharmony_ci *run++ = 1; 283cb93a386Sopenharmony_ci *aa++ = leftA; 284cb93a386Sopenharmony_ci } 285cb93a386Sopenharmony_ci 286cb93a386Sopenharmony_ci if (n > 0) { 287cb93a386Sopenharmony_ci run[0] = n; 288cb93a386Sopenharmony_ci aa[0] = 0xFF; 289cb93a386Sopenharmony_ci run += n; 290cb93a386Sopenharmony_ci aa += n; 291cb93a386Sopenharmony_ci } 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_ci SkASSERT(riteA < 0xFF); 294cb93a386Sopenharmony_ci if (riteA > 0) { 295cb93a386Sopenharmony_ci *run++ = 1; 296cb93a386Sopenharmony_ci *aa++ = riteA; 297cb93a386Sopenharmony_ci } 298cb93a386Sopenharmony_ci run[0] = 0; 299cb93a386Sopenharmony_ci} 300cb93a386Sopenharmony_ci#endif 301cb93a386Sopenharmony_ci 302cb93a386Sopenharmony_civoid SuperBlitter::blitRect(int x, int y, int width, int height) { 303cb93a386Sopenharmony_ci SkASSERT(width > 0); 304cb93a386Sopenharmony_ci SkASSERT(height > 0); 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_ci // blit leading rows 307cb93a386Sopenharmony_ci while ((y & MASK)) { 308cb93a386Sopenharmony_ci this->blitH(x, y++, width); 309cb93a386Sopenharmony_ci if (--height <= 0) { 310cb93a386Sopenharmony_ci return; 311cb93a386Sopenharmony_ci } 312cb93a386Sopenharmony_ci } 313cb93a386Sopenharmony_ci SkASSERT(height > 0); 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_ci // Since this is a rect, instead of blitting supersampled rows one at a 316cb93a386Sopenharmony_ci // time and then resolving to the destination canvas, we can blit 317cb93a386Sopenharmony_ci // directly to the destintion canvas one row per SCALE supersampled rows. 318cb93a386Sopenharmony_ci int start_y = y >> SHIFT; 319cb93a386Sopenharmony_ci int stop_y = (y + height) >> SHIFT; 320cb93a386Sopenharmony_ci int count = stop_y - start_y; 321cb93a386Sopenharmony_ci if (count > 0) { 322cb93a386Sopenharmony_ci y += count << SHIFT; 323cb93a386Sopenharmony_ci height -= count << SHIFT; 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_ci // save original X for our tail blitH() loop at the bottom 326cb93a386Sopenharmony_ci int origX = x; 327cb93a386Sopenharmony_ci 328cb93a386Sopenharmony_ci x -= fSuperLeft; 329cb93a386Sopenharmony_ci // hack, until I figure out why my cubics (I think) go beyond the bounds 330cb93a386Sopenharmony_ci if (x < 0) { 331cb93a386Sopenharmony_ci width += x; 332cb93a386Sopenharmony_ci x = 0; 333cb93a386Sopenharmony_ci } 334cb93a386Sopenharmony_ci 335cb93a386Sopenharmony_ci // There is always a left column, a middle, and a right column. 336cb93a386Sopenharmony_ci // ileft is the destination x of the first pixel of the entire rect. 337cb93a386Sopenharmony_ci // xleft is (SCALE - # of covered supersampled pixels) in that 338cb93a386Sopenharmony_ci // destination pixel. 339cb93a386Sopenharmony_ci int ileft = x >> SHIFT; 340cb93a386Sopenharmony_ci int xleft = x & MASK; 341cb93a386Sopenharmony_ci // irite is the destination x of the last pixel of the OPAQUE section. 342cb93a386Sopenharmony_ci // xrite is the number of supersampled pixels extending beyond irite; 343cb93a386Sopenharmony_ci // xrite/SCALE should give us alpha. 344cb93a386Sopenharmony_ci int irite = (x + width) >> SHIFT; 345cb93a386Sopenharmony_ci int xrite = (x + width) & MASK; 346cb93a386Sopenharmony_ci if (!xrite) { 347cb93a386Sopenharmony_ci xrite = SCALE; 348cb93a386Sopenharmony_ci irite--; 349cb93a386Sopenharmony_ci } 350cb93a386Sopenharmony_ci 351cb93a386Sopenharmony_ci // Need to call flush() to clean up pending draws before we 352cb93a386Sopenharmony_ci // even consider blitV(), since otherwise it can look nonmonotonic. 353cb93a386Sopenharmony_ci SkASSERT(start_y > fCurrIY); 354cb93a386Sopenharmony_ci this->flush(); 355cb93a386Sopenharmony_ci 356cb93a386Sopenharmony_ci int n = irite - ileft - 1; 357cb93a386Sopenharmony_ci if (n < 0) { 358cb93a386Sopenharmony_ci // If n < 0, we'll only have a single partially-transparent column 359cb93a386Sopenharmony_ci // of pixels to render. 360cb93a386Sopenharmony_ci xleft = xrite - xleft; 361cb93a386Sopenharmony_ci SkASSERT(xleft <= SCALE); 362cb93a386Sopenharmony_ci SkASSERT(xleft > 0); 363cb93a386Sopenharmony_ci fRealBlitter->blitV(ileft + fLeft, start_y, count, 364cb93a386Sopenharmony_ci coverage_to_exact_alpha(xleft)); 365cb93a386Sopenharmony_ci } else { 366cb93a386Sopenharmony_ci // With n = 0, we have two possibly-transparent columns of pixels 367cb93a386Sopenharmony_ci // to render; with n > 0, we have opaque columns between them. 368cb93a386Sopenharmony_ci 369cb93a386Sopenharmony_ci xleft = SCALE - xleft; 370cb93a386Sopenharmony_ci 371cb93a386Sopenharmony_ci // Using coverage_to_exact_alpha is not consistent with blitH() 372cb93a386Sopenharmony_ci const int coverageL = coverage_to_exact_alpha(xleft); 373cb93a386Sopenharmony_ci const int coverageR = coverage_to_exact_alpha(xrite); 374cb93a386Sopenharmony_ci 375cb93a386Sopenharmony_ci SkASSERT(coverageL > 0 || n > 0 || coverageR > 0); 376cb93a386Sopenharmony_ci SkASSERT((coverageL != 0) + n + (coverageR != 0) <= fWidth); 377cb93a386Sopenharmony_ci 378cb93a386Sopenharmony_ci fRealBlitter->blitAntiRect(ileft + fLeft, start_y, n, count, 379cb93a386Sopenharmony_ci coverageL, coverageR); 380cb93a386Sopenharmony_ci } 381cb93a386Sopenharmony_ci 382cb93a386Sopenharmony_ci // preamble for our next call to blitH() 383cb93a386Sopenharmony_ci fCurrIY = stop_y - 1; 384cb93a386Sopenharmony_ci fOffsetX = 0; 385cb93a386Sopenharmony_ci fCurrY = y - 1; 386cb93a386Sopenharmony_ci fRuns.reset(fWidth); 387cb93a386Sopenharmony_ci x = origX; 388cb93a386Sopenharmony_ci } 389cb93a386Sopenharmony_ci 390cb93a386Sopenharmony_ci // catch any remaining few rows 391cb93a386Sopenharmony_ci SkASSERT(height <= MASK); 392cb93a386Sopenharmony_ci while (--height >= 0) { 393cb93a386Sopenharmony_ci this->blitH(x, y++, width); 394cb93a386Sopenharmony_ci } 395cb93a386Sopenharmony_ci} 396cb93a386Sopenharmony_ci 397cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 398cb93a386Sopenharmony_ci 399cb93a386Sopenharmony_ci/// Masked supersampling antialiased blitter. 400cb93a386Sopenharmony_ciclass MaskSuperBlitter : public BaseSuperBlitter { 401cb93a386Sopenharmony_cipublic: 402cb93a386Sopenharmony_ci MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect&, bool isInverse); 403cb93a386Sopenharmony_ci ~MaskSuperBlitter() override { 404cb93a386Sopenharmony_ci fRealBlitter->blitMask(fMask, fClipRect); 405cb93a386Sopenharmony_ci } 406cb93a386Sopenharmony_ci 407cb93a386Sopenharmony_ci void blitH(int x, int y, int width) override; 408cb93a386Sopenharmony_ci 409cb93a386Sopenharmony_ci static bool CanHandleRect(const SkIRect& bounds) { 410cb93a386Sopenharmony_ci#ifdef FORCE_RLE 411cb93a386Sopenharmony_ci return false; 412cb93a386Sopenharmony_ci#endif 413cb93a386Sopenharmony_ci int width = bounds.width(); 414cb93a386Sopenharmony_ci int64_t rb = SkAlign4(width); 415cb93a386Sopenharmony_ci // use 64bits to detect overflow 416cb93a386Sopenharmony_ci int64_t storage = rb * bounds.height(); 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ci return (width <= MaskSuperBlitter::kMAX_WIDTH) && 419cb93a386Sopenharmony_ci (storage <= MaskSuperBlitter::kMAX_STORAGE); 420cb93a386Sopenharmony_ci } 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ciprivate: 423cb93a386Sopenharmony_ci enum { 424cb93a386Sopenharmony_ci#ifdef FORCE_SUPERMASK 425cb93a386Sopenharmony_ci kMAX_WIDTH = 2048, 426cb93a386Sopenharmony_ci kMAX_STORAGE = 1024 * 1024 * 2 427cb93a386Sopenharmony_ci#else 428cb93a386Sopenharmony_ci kMAX_WIDTH = 32, // so we don't try to do very wide things, where the RLE blitter would be faster 429cb93a386Sopenharmony_ci kMAX_STORAGE = 1024 430cb93a386Sopenharmony_ci#endif 431cb93a386Sopenharmony_ci }; 432cb93a386Sopenharmony_ci 433cb93a386Sopenharmony_ci SkMask fMask; 434cb93a386Sopenharmony_ci SkIRect fClipRect; 435cb93a386Sopenharmony_ci // we add 1 because add_aa_span can write (unchanged) 1 extra byte at the end, rather than 436cb93a386Sopenharmony_ci // perform a test to see if stopAlpha != 0 437cb93a386Sopenharmony_ci uint32_t fStorage[(kMAX_STORAGE >> 2) + 1]; 438cb93a386Sopenharmony_ci}; 439cb93a386Sopenharmony_ci 440cb93a386Sopenharmony_ciMaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, 441cb93a386Sopenharmony_ci const SkIRect& clipBounds, bool isInverse) 442cb93a386Sopenharmony_ci : BaseSuperBlitter(realBlitter, ir, clipBounds, isInverse) 443cb93a386Sopenharmony_ci{ 444cb93a386Sopenharmony_ci SkASSERT(CanHandleRect(ir)); 445cb93a386Sopenharmony_ci SkASSERT(!isInverse); 446cb93a386Sopenharmony_ci 447cb93a386Sopenharmony_ci fMask.fImage = (uint8_t*)fStorage; 448cb93a386Sopenharmony_ci fMask.fBounds = ir; 449cb93a386Sopenharmony_ci fMask.fRowBytes = ir.width(); 450cb93a386Sopenharmony_ci fMask.fFormat = SkMask::kA8_Format; 451cb93a386Sopenharmony_ci 452cb93a386Sopenharmony_ci fClipRect = ir; 453cb93a386Sopenharmony_ci if (!fClipRect.intersect(clipBounds)) { 454cb93a386Sopenharmony_ci SkASSERT(0); 455cb93a386Sopenharmony_ci fClipRect.setEmpty(); 456cb93a386Sopenharmony_ci } 457cb93a386Sopenharmony_ci 458cb93a386Sopenharmony_ci // For valgrind, write 1 extra byte at the end so we don't read 459cb93a386Sopenharmony_ci // uninitialized memory. See comment in add_aa_span and fStorage[]. 460cb93a386Sopenharmony_ci memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 1); 461cb93a386Sopenharmony_ci} 462cb93a386Sopenharmony_ci 463cb93a386Sopenharmony_cistatic void add_aa_span(uint8_t* alpha, U8CPU startAlpha) { 464cb93a386Sopenharmony_ci /* I should be able to just add alpha[x] + startAlpha. 465cb93a386Sopenharmony_ci However, if the trailing edge of the previous span and the leading 466cb93a386Sopenharmony_ci edge of the current span round to the same super-sampled x value, 467cb93a386Sopenharmony_ci I might overflow to 256 with this add, hence the funny subtract. 468cb93a386Sopenharmony_ci */ 469cb93a386Sopenharmony_ci unsigned tmp = *alpha + startAlpha; 470cb93a386Sopenharmony_ci SkASSERT(tmp <= 256); 471cb93a386Sopenharmony_ci *alpha = SkToU8(tmp - (tmp >> 8)); 472cb93a386Sopenharmony_ci} 473cb93a386Sopenharmony_ci 474cb93a386Sopenharmony_cistatic inline uint32_t quadplicate_byte(U8CPU value) { 475cb93a386Sopenharmony_ci uint32_t pair = (value << 8) | value; 476cb93a386Sopenharmony_ci return (pair << 16) | pair; 477cb93a386Sopenharmony_ci} 478cb93a386Sopenharmony_ci 479cb93a386Sopenharmony_ci// Perform this tricky subtract, to avoid overflowing to 256. Our caller should 480cb93a386Sopenharmony_ci// only ever call us with at most enough to hit 256 (never larger), so it is 481cb93a386Sopenharmony_ci// enough to just subtract the high-bit. Actually clamping with a branch would 482cb93a386Sopenharmony_ci// be slower (e.g. if (tmp > 255) tmp = 255;) 483cb93a386Sopenharmony_ci// 484cb93a386Sopenharmony_cistatic inline void saturated_add(uint8_t* ptr, U8CPU add) { 485cb93a386Sopenharmony_ci unsigned tmp = *ptr + add; 486cb93a386Sopenharmony_ci SkASSERT(tmp <= 256); 487cb93a386Sopenharmony_ci *ptr = SkToU8(tmp - (tmp >> 8)); 488cb93a386Sopenharmony_ci} 489cb93a386Sopenharmony_ci 490cb93a386Sopenharmony_ci// minimum count before we want to setup an inner loop, adding 4-at-a-time 491cb93a386Sopenharmony_ci#define MIN_COUNT_FOR_QUAD_LOOP 16 492cb93a386Sopenharmony_ci 493cb93a386Sopenharmony_cistatic void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, 494cb93a386Sopenharmony_ci U8CPU stopAlpha, U8CPU maxValue) { 495cb93a386Sopenharmony_ci SkASSERT(middleCount >= 0); 496cb93a386Sopenharmony_ci 497cb93a386Sopenharmony_ci saturated_add(alpha, startAlpha); 498cb93a386Sopenharmony_ci alpha += 1; 499cb93a386Sopenharmony_ci 500cb93a386Sopenharmony_ci if (middleCount >= MIN_COUNT_FOR_QUAD_LOOP) { 501cb93a386Sopenharmony_ci // loop until we're quad-byte aligned 502cb93a386Sopenharmony_ci while (reinterpret_cast<intptr_t>(alpha) & 0x3) { 503cb93a386Sopenharmony_ci alpha[0] = SkToU8(alpha[0] + maxValue); 504cb93a386Sopenharmony_ci alpha += 1; 505cb93a386Sopenharmony_ci middleCount -= 1; 506cb93a386Sopenharmony_ci } 507cb93a386Sopenharmony_ci 508cb93a386Sopenharmony_ci int bigCount = middleCount >> 2; 509cb93a386Sopenharmony_ci uint32_t* qptr = reinterpret_cast<uint32_t*>(alpha); 510cb93a386Sopenharmony_ci uint32_t qval = quadplicate_byte(maxValue); 511cb93a386Sopenharmony_ci do { 512cb93a386Sopenharmony_ci *qptr++ += qval; 513cb93a386Sopenharmony_ci } while (--bigCount > 0); 514cb93a386Sopenharmony_ci 515cb93a386Sopenharmony_ci middleCount &= 3; 516cb93a386Sopenharmony_ci alpha = reinterpret_cast<uint8_t*> (qptr); 517cb93a386Sopenharmony_ci // fall through to the following while-loop 518cb93a386Sopenharmony_ci } 519cb93a386Sopenharmony_ci 520cb93a386Sopenharmony_ci while (--middleCount >= 0) { 521cb93a386Sopenharmony_ci alpha[0] = SkToU8(alpha[0] + maxValue); 522cb93a386Sopenharmony_ci alpha += 1; 523cb93a386Sopenharmony_ci } 524cb93a386Sopenharmony_ci 525cb93a386Sopenharmony_ci // potentially this can be off the end of our "legal" alpha values, but that 526cb93a386Sopenharmony_ci // only happens if stopAlpha is also 0. Rather than test for stopAlpha != 0 527cb93a386Sopenharmony_ci // every time (slow), we just do it, and ensure that we've allocated extra space 528cb93a386Sopenharmony_ci // (see the + 1 comment in fStorage[] 529cb93a386Sopenharmony_ci saturated_add(alpha, stopAlpha); 530cb93a386Sopenharmony_ci} 531cb93a386Sopenharmony_ci 532cb93a386Sopenharmony_civoid MaskSuperBlitter::blitH(int x, int y, int width) { 533cb93a386Sopenharmony_ci int iy = (y >> SHIFT); 534cb93a386Sopenharmony_ci 535cb93a386Sopenharmony_ci SkASSERT(iy >= fMask.fBounds.fTop && iy < fMask.fBounds.fBottom); 536cb93a386Sopenharmony_ci iy -= fMask.fBounds.fTop; // make it relative to 0 537cb93a386Sopenharmony_ci 538cb93a386Sopenharmony_ci // This should never happen, but it does. Until the true cause is 539cb93a386Sopenharmony_ci // discovered, let's skip this span instead of crashing. 540cb93a386Sopenharmony_ci // See http://crbug.com/17569. 541cb93a386Sopenharmony_ci if (iy < 0) { 542cb93a386Sopenharmony_ci return; 543cb93a386Sopenharmony_ci } 544cb93a386Sopenharmony_ci 545cb93a386Sopenharmony_ci#ifdef SK_DEBUG 546cb93a386Sopenharmony_ci { 547cb93a386Sopenharmony_ci int ix = x >> SHIFT; 548cb93a386Sopenharmony_ci SkASSERT(ix >= fMask.fBounds.fLeft && ix < fMask.fBounds.fRight); 549cb93a386Sopenharmony_ci } 550cb93a386Sopenharmony_ci#endif 551cb93a386Sopenharmony_ci 552cb93a386Sopenharmony_ci x -= SkLeftShift(fMask.fBounds.fLeft, SHIFT); 553cb93a386Sopenharmony_ci 554cb93a386Sopenharmony_ci // hack, until I figure out why my cubics (I think) go beyond the bounds 555cb93a386Sopenharmony_ci if (x < 0) { 556cb93a386Sopenharmony_ci width += x; 557cb93a386Sopenharmony_ci x = 0; 558cb93a386Sopenharmony_ci } 559cb93a386Sopenharmony_ci 560cb93a386Sopenharmony_ci uint8_t* row = fMask.fImage + iy * fMask.fRowBytes + (x >> SHIFT); 561cb93a386Sopenharmony_ci 562cb93a386Sopenharmony_ci int start = x; 563cb93a386Sopenharmony_ci int stop = x + width; 564cb93a386Sopenharmony_ci 565cb93a386Sopenharmony_ci SkASSERT(start >= 0 && stop > start); 566cb93a386Sopenharmony_ci int fb = start & MASK; 567cb93a386Sopenharmony_ci int fe = stop & MASK; 568cb93a386Sopenharmony_ci int n = (stop >> SHIFT) - (start >> SHIFT) - 1; 569cb93a386Sopenharmony_ci 570cb93a386Sopenharmony_ci 571cb93a386Sopenharmony_ci if (n < 0) { 572cb93a386Sopenharmony_ci SkASSERT(row >= fMask.fImage); 573cb93a386Sopenharmony_ci SkASSERT(row < fMask.fImage + kMAX_STORAGE + 1); 574cb93a386Sopenharmony_ci add_aa_span(row, coverage_to_partial_alpha(fe - fb)); 575cb93a386Sopenharmony_ci } else { 576cb93a386Sopenharmony_ci fb = SCALE - fb; 577cb93a386Sopenharmony_ci SkASSERT(row >= fMask.fImage); 578cb93a386Sopenharmony_ci SkASSERT(row + n + 1 < fMask.fImage + kMAX_STORAGE + 1); 579cb93a386Sopenharmony_ci add_aa_span(row, coverage_to_partial_alpha(fb), 580cb93a386Sopenharmony_ci n, coverage_to_partial_alpha(fe), 581cb93a386Sopenharmony_ci (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT)); 582cb93a386Sopenharmony_ci } 583cb93a386Sopenharmony_ci 584cb93a386Sopenharmony_ci#ifdef SK_DEBUG 585cb93a386Sopenharmony_ci fCurrX = x + width; 586cb93a386Sopenharmony_ci#endif 587cb93a386Sopenharmony_ci} 588cb93a386Sopenharmony_ci 589cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 590cb93a386Sopenharmony_ci 591cb93a386Sopenharmony_cistatic SkIRect safeRoundOut(const SkRect& src) { 592cb93a386Sopenharmony_ci // roundOut will pin huge floats to max/min int 593cb93a386Sopenharmony_ci SkIRect dst = src.roundOut(); 594cb93a386Sopenharmony_ci 595cb93a386Sopenharmony_ci // intersect with a smaller huge rect, so the rect will not be considered empty for being 596cb93a386Sopenharmony_ci // too large. e.g. { -SK_MaxS32 ... SK_MaxS32 } is considered empty because its width 597cb93a386Sopenharmony_ci // exceeds signed 32bit. 598cb93a386Sopenharmony_ci const int32_t limit = SK_MaxS32 >> SK_SUPERSAMPLE_SHIFT; 599cb93a386Sopenharmony_ci (void)dst.intersect({ -limit, -limit, limit, limit}); 600cb93a386Sopenharmony_ci 601cb93a386Sopenharmony_ci return dst; 602cb93a386Sopenharmony_ci} 603cb93a386Sopenharmony_ci 604cb93a386Sopenharmony_ciconstexpr int kSampleSize = 8; 605cb93a386Sopenharmony_ci#if !defined(SK_DISABLE_AAA) 606cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_OHOS 607cb93a386Sopenharmony_ci constexpr SkScalar kComplexityThreshold = 8.0; 608cb93a386Sopenharmony_ci#else 609cb93a386Sopenharmony_ci constexpr SkScalar kComplexityThreshold = 0.25; 610cb93a386Sopenharmony_ci#endif 611cb93a386Sopenharmony_ci#endif 612cb93a386Sopenharmony_ci 613cb93a386Sopenharmony_civoid compute_complexity(const SkPath& path, SkScalar& avgLength, SkScalar& complexity) { 614cb93a386Sopenharmony_ci int n = path.countPoints(); 615cb93a386Sopenharmony_ci if (n < kSampleSize || path.getBounds().isEmpty()) { 616cb93a386Sopenharmony_ci // set to invalid value to indicate that we failed to compute 617cb93a386Sopenharmony_ci avgLength = complexity = -1; 618cb93a386Sopenharmony_ci return; 619cb93a386Sopenharmony_ci } 620cb93a386Sopenharmony_ci 621cb93a386Sopenharmony_ci SkScalar sumLength = 0; 622cb93a386Sopenharmony_ci SkPoint lastPoint = path.getPoint(0); 623cb93a386Sopenharmony_ci for(int i = 1; i < kSampleSize; ++i) { 624cb93a386Sopenharmony_ci SkPoint point = path.getPoint(i); 625cb93a386Sopenharmony_ci sumLength += SkPoint::Distance(lastPoint, point); 626cb93a386Sopenharmony_ci lastPoint = point; 627cb93a386Sopenharmony_ci } 628cb93a386Sopenharmony_ci avgLength = sumLength / (kSampleSize - 1); 629cb93a386Sopenharmony_ci 630cb93a386Sopenharmony_ci auto sqr = [](SkScalar x) { return x*x; }; 631cb93a386Sopenharmony_ci 632cb93a386Sopenharmony_ci SkScalar diagonalSqr = sqr(path.getBounds().width()) + sqr(path.getBounds().height()); 633cb93a386Sopenharmony_ci 634cb93a386Sopenharmony_ci // If the path consists of random line segments, the number of intersections should be 635cb93a386Sopenharmony_ci // proportional to this. 636cb93a386Sopenharmony_ci SkScalar intersections = sk_ieee_float_divide(sqr(n) * sqr(avgLength), diagonalSqr); 637cb93a386Sopenharmony_ci 638cb93a386Sopenharmony_ci // The number of intersections per scanline should be proportional to this number. 639cb93a386Sopenharmony_ci complexity = sk_ieee_float_divide(intersections, path.getBounds().height()); 640cb93a386Sopenharmony_ci 641cb93a386Sopenharmony_ci if (sk_float_isnan(complexity)) { // it may be possible to have 0.0 / 0.0; inf is fine for us. 642cb93a386Sopenharmony_ci complexity = -1; 643cb93a386Sopenharmony_ci } 644cb93a386Sopenharmony_ci} 645cb93a386Sopenharmony_ci 646cb93a386Sopenharmony_cistatic bool ShouldUseAAA(const SkPath& path, SkScalar avgLength, SkScalar complexity) { 647cb93a386Sopenharmony_ci#if defined(SK_DISABLE_AAA) 648cb93a386Sopenharmony_ci return false; 649cb93a386Sopenharmony_ci#else 650cb93a386Sopenharmony_ci if (gSkForceAnalyticAA) { 651cb93a386Sopenharmony_ci return true; 652cb93a386Sopenharmony_ci } 653cb93a386Sopenharmony_ci if (!gSkUseAnalyticAA) { 654cb93a386Sopenharmony_ci return false; 655cb93a386Sopenharmony_ci } 656cb93a386Sopenharmony_ci if (path.isRect(nullptr)) { 657cb93a386Sopenharmony_ci return true; 658cb93a386Sopenharmony_ci } 659cb93a386Sopenharmony_ci 660cb93a386Sopenharmony_ci #ifdef SK_SUPPORT_LEGACY_AAA_CHOICE 661cb93a386Sopenharmony_ci const SkRect& bounds = path.getBounds(); 662cb93a386Sopenharmony_ci // When the path have so many points compared to the size of its 663cb93a386Sopenharmony_ci // bounds/resolution, it indicates that the path is not quite smooth in 664cb93a386Sopenharmony_ci // the current resolution: the expected number of turning points in 665cb93a386Sopenharmony_ci // every pixel row/column is significantly greater than zero. Hence 666cb93a386Sopenharmony_ci // Aanlytic AA is not likely to produce visible quality improvements, 667cb93a386Sopenharmony_ci // and Analytic AA might be slower than supersampling. 668cb93a386Sopenharmony_ci return path.countPoints() < std::max(bounds.width(), bounds.height()) / 2 - 10; 669cb93a386Sopenharmony_ci #else 670cb93a386Sopenharmony_ci#ifndef SK_BUILD_FOR_OHOS 671cb93a386Sopenharmony_ci if (path.countPoints() >= path.getBounds().height()) { 672cb93a386Sopenharmony_ci // SAA is faster than AAA in this case even if there are no 673cb93a386Sopenharmony_ci // intersections because AAA will have too many scan lines. See 674cb93a386Sopenharmony_ci // skbug.com/8272 675cb93a386Sopenharmony_ci return false; 676cb93a386Sopenharmony_ci } 677cb93a386Sopenharmony_ci#endif 678cb93a386Sopenharmony_ci#ifdef SK_ENABLE_PATH_COMPLEXITY_DFX 679cb93a386Sopenharmony_ci SkPathComplexityDfx::AddPathComplexityTrace(complexity); 680cb93a386Sopenharmony_ci#endif 681cb93a386Sopenharmony_ci // We will use AAA if the number of verbs < kSampleSize and therefore complexity < 0 682cb93a386Sopenharmony_ci return complexity < kComplexityThreshold; 683cb93a386Sopenharmony_ci #endif 684cb93a386Sopenharmony_ci#endif 685cb93a386Sopenharmony_ci} 686cb93a386Sopenharmony_ci 687cb93a386Sopenharmony_civoid SkScan::SAAFillPath(const SkPath& path, SkBlitter* blitter, const SkIRect& ir, 688cb93a386Sopenharmony_ci const SkIRect& clipBounds, bool forceRLE) { 689cb93a386Sopenharmony_ci bool containedInClip = clipBounds.contains(ir); 690cb93a386Sopenharmony_ci bool isInverse = path.isInverseFillType(); 691cb93a386Sopenharmony_ci 692cb93a386Sopenharmony_ci // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it 693cb93a386Sopenharmony_ci // if we're an inverse filltype 694cb93a386Sopenharmony_ci if (!isInverse && MaskSuperBlitter::CanHandleRect(ir) && !forceRLE) { 695cb93a386Sopenharmony_ci MaskSuperBlitter superBlit(blitter, ir, clipBounds, isInverse); 696cb93a386Sopenharmony_ci SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); 697cb93a386Sopenharmony_ci sk_fill_path(path, clipBounds, &superBlit, ir.fTop, ir.fBottom, SHIFT, containedInClip); 698cb93a386Sopenharmony_ci } else { 699cb93a386Sopenharmony_ci SuperBlitter superBlit(blitter, ir, clipBounds, isInverse); 700cb93a386Sopenharmony_ci sk_fill_path(path, clipBounds, &superBlit, ir.fTop, ir.fBottom, SHIFT, containedInClip); 701cb93a386Sopenharmony_ci } 702cb93a386Sopenharmony_ci} 703cb93a386Sopenharmony_ci 704cb93a386Sopenharmony_cistatic int overflows_short_shift(int value, int shift) { 705cb93a386Sopenharmony_ci const int s = 16 + shift; 706cb93a386Sopenharmony_ci return (SkLeftShift(value, s) >> s) - value; 707cb93a386Sopenharmony_ci} 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_ci/** 710cb93a386Sopenharmony_ci Would any of the coordinates of this rectangle not fit in a short, 711cb93a386Sopenharmony_ci when left-shifted by shift? 712cb93a386Sopenharmony_ci*/ 713cb93a386Sopenharmony_cistatic int rect_overflows_short_shift(SkIRect rect, int shift) { 714cb93a386Sopenharmony_ci SkASSERT(!overflows_short_shift(8191, shift)); 715cb93a386Sopenharmony_ci SkASSERT(overflows_short_shift(8192, shift)); 716cb93a386Sopenharmony_ci SkASSERT(!overflows_short_shift(32767, 0)); 717cb93a386Sopenharmony_ci SkASSERT(overflows_short_shift(32768, 0)); 718cb93a386Sopenharmony_ci 719cb93a386Sopenharmony_ci // Since we expect these to succeed, we bit-or together 720cb93a386Sopenharmony_ci // for a tiny extra bit of speed. 721cb93a386Sopenharmony_ci return overflows_short_shift(rect.fLeft, shift) | 722cb93a386Sopenharmony_ci overflows_short_shift(rect.fRight, shift) | 723cb93a386Sopenharmony_ci overflows_short_shift(rect.fTop, shift) | 724cb93a386Sopenharmony_ci overflows_short_shift(rect.fBottom, shift); 725cb93a386Sopenharmony_ci} 726cb93a386Sopenharmony_ci 727cb93a386Sopenharmony_civoid SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip, 728cb93a386Sopenharmony_ci SkBlitter* blitter, bool forceRLE) { 729cb93a386Sopenharmony_ci if (origClip.isEmpty()) { 730cb93a386Sopenharmony_ci return; 731cb93a386Sopenharmony_ci } 732cb93a386Sopenharmony_ci 733cb93a386Sopenharmony_ci const bool isInverse = path.isInverseFillType(); 734cb93a386Sopenharmony_ci SkIRect ir = safeRoundOut(path.getBounds()); 735cb93a386Sopenharmony_ci if (ir.isEmpty()) { 736cb93a386Sopenharmony_ci if (isInverse) { 737cb93a386Sopenharmony_ci blitter->blitRegion(origClip); 738cb93a386Sopenharmony_ci } 739cb93a386Sopenharmony_ci return; 740cb93a386Sopenharmony_ci } 741cb93a386Sopenharmony_ci 742cb93a386Sopenharmony_ci // If the intersection of the path bounds and the clip bounds 743cb93a386Sopenharmony_ci // will overflow 32767 when << by SHIFT, we can't supersample, 744cb93a386Sopenharmony_ci // so draw without antialiasing. 745cb93a386Sopenharmony_ci SkIRect clippedIR; 746cb93a386Sopenharmony_ci if (isInverse) { 747cb93a386Sopenharmony_ci // If the path is an inverse fill, it's going to fill the entire 748cb93a386Sopenharmony_ci // clip, and we care whether the entire clip exceeds our limits. 749cb93a386Sopenharmony_ci clippedIR = origClip.getBounds(); 750cb93a386Sopenharmony_ci } else { 751cb93a386Sopenharmony_ci if (!clippedIR.intersect(ir, origClip.getBounds())) { 752cb93a386Sopenharmony_ci return; 753cb93a386Sopenharmony_ci } 754cb93a386Sopenharmony_ci } 755cb93a386Sopenharmony_ci if (rect_overflows_short_shift(clippedIR, SHIFT)) { 756cb93a386Sopenharmony_ci SkScan::FillPath(path, origClip, blitter); 757cb93a386Sopenharmony_ci return; 758cb93a386Sopenharmony_ci } 759cb93a386Sopenharmony_ci 760cb93a386Sopenharmony_ci // Our antialiasing can't handle a clip larger than 32767, so we restrict 761cb93a386Sopenharmony_ci // the clip to that limit here. (the runs[] uses int16_t for its index). 762cb93a386Sopenharmony_ci // 763cb93a386Sopenharmony_ci // A more general solution (one that could also eliminate the need to 764cb93a386Sopenharmony_ci // disable aa based on ir bounds (see overflows_short_shift) would be 765cb93a386Sopenharmony_ci // to tile the clip/target... 766cb93a386Sopenharmony_ci SkRegion tmpClipStorage; 767cb93a386Sopenharmony_ci const SkRegion* clipRgn = &origClip; 768cb93a386Sopenharmony_ci { 769cb93a386Sopenharmony_ci static const int32_t kMaxClipCoord = 32767; 770cb93a386Sopenharmony_ci const SkIRect& bounds = origClip.getBounds(); 771cb93a386Sopenharmony_ci if (bounds.fRight > kMaxClipCoord || bounds.fBottom > kMaxClipCoord) { 772cb93a386Sopenharmony_ci SkIRect limit = { 0, 0, kMaxClipCoord, kMaxClipCoord }; 773cb93a386Sopenharmony_ci tmpClipStorage.op(origClip, limit, SkRegion::kIntersect_Op); 774cb93a386Sopenharmony_ci clipRgn = &tmpClipStorage; 775cb93a386Sopenharmony_ci } 776cb93a386Sopenharmony_ci } 777cb93a386Sopenharmony_ci // for here down, use clipRgn, not origClip 778cb93a386Sopenharmony_ci 779cb93a386Sopenharmony_ci SkScanClipper clipper(blitter, clipRgn, ir); 780cb93a386Sopenharmony_ci 781cb93a386Sopenharmony_ci if (clipper.getBlitter() == nullptr) { // clipped out 782cb93a386Sopenharmony_ci if (isInverse) { 783cb93a386Sopenharmony_ci blitter->blitRegion(*clipRgn); 784cb93a386Sopenharmony_ci } 785cb93a386Sopenharmony_ci return; 786cb93a386Sopenharmony_ci } 787cb93a386Sopenharmony_ci 788cb93a386Sopenharmony_ci SkASSERT(clipper.getClipRect() == nullptr || 789cb93a386Sopenharmony_ci *clipper.getClipRect() == clipRgn->getBounds()); 790cb93a386Sopenharmony_ci 791cb93a386Sopenharmony_ci // now use the (possibly wrapped) blitter 792cb93a386Sopenharmony_ci blitter = clipper.getBlitter(); 793cb93a386Sopenharmony_ci 794cb93a386Sopenharmony_ci if (isInverse) { 795cb93a386Sopenharmony_ci sk_blit_above(blitter, ir, *clipRgn); 796cb93a386Sopenharmony_ci } 797cb93a386Sopenharmony_ci 798cb93a386Sopenharmony_ci SkScalar avgLength, complexity; 799cb93a386Sopenharmony_ci compute_complexity(path, avgLength, complexity); 800cb93a386Sopenharmony_ci 801cb93a386Sopenharmony_ci if (ShouldUseAAA(path, avgLength, complexity)) { 802cb93a386Sopenharmony_ci // Do not use AAA if path is too complicated: 803cb93a386Sopenharmony_ci // there won't be any speedup or significant visual improvement. 804cb93a386Sopenharmony_ci SkScan::AAAFillPath(path, blitter, ir, clipRgn->getBounds(), forceRLE); 805cb93a386Sopenharmony_ci } else { 806cb93a386Sopenharmony_ci SkScan::SAAFillPath(path, blitter, ir, clipRgn->getBounds(), forceRLE); 807cb93a386Sopenharmony_ci } 808cb93a386Sopenharmony_ci 809cb93a386Sopenharmony_ci if (isInverse) { 810cb93a386Sopenharmony_ci sk_blit_below(blitter, ir, *clipRgn); 811cb93a386Sopenharmony_ci } 812cb93a386Sopenharmony_ci} 813cb93a386Sopenharmony_ci 814cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 815cb93a386Sopenharmony_ci 816cb93a386Sopenharmony_ci#include "src/core/SkRasterClip.h" 817cb93a386Sopenharmony_ci 818cb93a386Sopenharmony_civoid SkScan::FillPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* blitter) { 819cb93a386Sopenharmony_ci if (clip.isEmpty() || !path.isFinite()) { 820cb93a386Sopenharmony_ci return; 821cb93a386Sopenharmony_ci } 822cb93a386Sopenharmony_ci 823cb93a386Sopenharmony_ci if (clip.isBW()) { 824cb93a386Sopenharmony_ci FillPath(path, clip.bwRgn(), blitter); 825cb93a386Sopenharmony_ci } else { 826cb93a386Sopenharmony_ci SkRegion tmp; 827cb93a386Sopenharmony_ci SkAAClipBlitter aaBlitter; 828cb93a386Sopenharmony_ci 829cb93a386Sopenharmony_ci tmp.setRect(clip.getBounds()); 830cb93a386Sopenharmony_ci aaBlitter.init(blitter, &clip.aaRgn()); 831cb93a386Sopenharmony_ci SkScan::FillPath(path, tmp, &aaBlitter); 832cb93a386Sopenharmony_ci } 833cb93a386Sopenharmony_ci} 834cb93a386Sopenharmony_ci 835cb93a386Sopenharmony_civoid SkScan::AntiFillPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* blitter) { 836cb93a386Sopenharmony_ci if (clip.isEmpty() || !path.isFinite()) { 837cb93a386Sopenharmony_ci return; 838cb93a386Sopenharmony_ci } 839cb93a386Sopenharmony_ci 840cb93a386Sopenharmony_ci if (clip.isBW()) { 841cb93a386Sopenharmony_ci AntiFillPath(path, clip.bwRgn(), blitter, false); 842cb93a386Sopenharmony_ci } else { 843cb93a386Sopenharmony_ci SkRegion tmp; 844cb93a386Sopenharmony_ci SkAAClipBlitter aaBlitter; 845cb93a386Sopenharmony_ci 846cb93a386Sopenharmony_ci tmp.setRect(clip.getBounds()); 847cb93a386Sopenharmony_ci aaBlitter.init(blitter, &clip.aaRgn()); 848cb93a386Sopenharmony_ci AntiFillPath(path, tmp, &aaBlitter, true); // SkAAClipBlitter can blitMask, why forceRLE? 849cb93a386Sopenharmony_ci } 850cb93a386Sopenharmony_ci} 851