Flutter Engine
The Flutter Engine
Functions | Variables
SkBitmapProcState_matrixProcs.cpp File Reference
#include "include/core/SkMatrix.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkCPUTypes.h"
#include "include/private/base/SkFixed.h"
#include "include/private/base/SkMath.h"
#include "include/private/base/SkTFitsIn.h"
#include "include/private/base/SkTPin.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkBitmapProcState.h"
#include "src/core/SkMemset.h"
#include <cstdint>
#include <cstring>

Go to the source code of this file.

Functions

static bool can_truncate_to_fixed_for_decal (SkFixed fx, SkFixed dx, int count, unsigned max)
 
static void decal_nofilter_scale (uint32_t dst[], SkFixed fx, SkFixed dx, int count)
 
template<unsigned(*)(SkFixed, int) tilex, unsigned(*)(SkFixed, int) tiley, bool tryDecal>
static void nofilter_scale (const SkBitmapProcState &s, uint32_t xy[], int count, int x, int y)
 
template<unsigned(*)(SkFixed, int) tilex, unsigned(*)(SkFixed, int) tiley>
static void nofilter_affine (const SkBitmapProcState &s, uint32_t xy[], int count, int x, int y)
 
static unsigned extract_low_bits_clamp_clamp (SkFixed fx, int)
 
static unsigned extract_low_bits_general (SkFixed fx, int max)
 
template<unsigned(*)(SkFixed, int) tile, unsigned(*)(SkFixed, int) extract_low_bits>
static uint32_t pack (SkFixed f, unsigned max, SkFixed one)
 
template<unsigned(*)(SkFixed, int) tilex, unsigned(*)(SkFixed, int) tiley, unsigned(*)(SkFixed, int) extract_low_bits, bool tryDecal>
static void filter_scale (const SkBitmapProcState &s, uint32_t xy[], int count, int x, int y)
 
template<unsigned(*)(SkFixed, int) tilex, unsigned(*)(SkFixed, int) tiley, unsigned(*)(SkFixed, int) extract_low_bits>
static void filter_affine (const SkBitmapProcState &s, uint32_t xy[], int count, int x, int y)
 
static unsigned SK_USHIFT16 (unsigned x)
 
static unsigned repeat (SkFixed fx, int max)
 
static unsigned mirror (SkFixed fx, int max)
 
static unsigned clamp (SkFixed fx, int max)
 
static U16CPU int_clamp (int x, int n)
 
static int sk_int_mod (int x, int n)
 
static U16CPU int_repeat (int x, int n)
 
static U16CPU int_mirror (int x, int n)
 
static void fill_sequential (uint16_t xptr[], int pos, int count)
 
static void fill_backwards (uint16_t xptr[], int pos, int count)
 
template<U16CPU(tiley)(int x, int n) >
static void clampx_nofilter_trans (const SkBitmapProcState &s, uint32_t xy[], int count, int x, int y)
 
template<U16CPU(tiley)(int x, int n) >
static void repeatx_nofilter_trans (const SkBitmapProcState &s, uint32_t xy[], int count, int x, int y)
 
template<U16CPU(tiley)(int x, int n) >
static void mirrorx_nofilter_trans (const SkBitmapProcState &s, uint32_t xy[], int count, int x, int y)
 

Variables

static const SkBitmapProcState::MatrixProc ClampX_ClampY_Procs []
 
static const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs []
 
static const SkBitmapProcState::MatrixProc MirrorX_MirrorY_Procs []
 

Function Documentation

◆ can_truncate_to_fixed_for_decal()

static bool can_truncate_to_fixed_for_decal ( SkFixed  fx,
SkFixed  dx,
int  count,
unsigned  max 
)
inlinestatic

Definition at line 34 of file SkBitmapProcState_matrixProcs.cpp.

36 {
37 SkASSERT(count > 0);
38
39 // if decal_ kept SkFractionalInt precision, this would just be dx <= 0
40 // I just made up the 1/256. Just don't want to perceive accumulated error
41 // if we truncate frDx and lose its low bits.
42 if (dx <= SK_Fixed1 / 256) {
43 return false;
44 }
45
46 // Note: it seems the test should be (fx <= max && lastFx <= max); but
47 // historically it's been a strict inequality check, and changing produces
48 // unexpected diffs. Further investigation is needed.
49
50 // We cast to unsigned so we don't have to check for negative values, which
51 // will now appear as very large positive values, and thus fail our test!
52 if ((unsigned)SkFixedFloorToInt(fx) >= max) {
53 return false;
54 }
55
56 // Promote to 64bit (48.16) to avoid overflow.
57 const uint64_t lastFx = fx + sk_64_mul(dx, count - 1);
58
59 return SkTFitsIn<int32_t>(lastFx) && (unsigned)SkFixedFloorToInt(SkTo<int32_t>(lastFx)) < max;
60}
int count
Definition: FontMgrTest.cpp:50
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SK_Fixed1
Definition: SkFixed.h:26
#define SkFixedFloorToInt(x)
Definition: SkFixed.h:78
static int64_t sk_64_mul(int64_t a, int64_t b)
Definition: SkMath.h:33
static float max(float r, float g, float b)
Definition: hsl.cpp:49
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208

◆ clamp()

static unsigned clamp ( SkFixed  fx,
int  max 
)
static

Definition at line 271 of file SkBitmapProcState_matrixProcs.cpp.

271 {
272 return SkTPin(fx >> 16, 0, max);
273}
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition: SkTPin.h:19

◆ clampx_nofilter_trans()

template<U16CPU(tiley)(int x, int n) >
static void clampx_nofilter_trans ( const SkBitmapProcState s,
uint32_t  xy[],
int  count,
int  x,
int  y 
)
static

Definition at line 343 of file SkBitmapProcState_matrixProcs.cpp.

344 {
345 SkASSERT(s.fInvMatrix.isTranslate());
346
347 const SkBitmapProcStateAutoMapper mapper(s, x, y);
348 *xy++ = tiley(mapper.intY(), s.fPixmap.height());
349 int xpos = mapper.intX();
350
351 const int width = s.fPixmap.width();
352 if (1 == width) {
353 // all of the following X values must be 0
354 memset(xy, 0, count * sizeof(uint16_t));
355 return;
356 }
357
358 uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
359 int n;
360
361 // fill before 0 as needed
362 if (xpos < 0) {
363 n = -xpos;
364 if (n > count) {
365 n = count;
366 }
367 memset(xptr, 0, n * sizeof(uint16_t));
368 count -= n;
369 if (0 == count) {
370 return;
371 }
372 xptr += n;
373 xpos = 0;
374 }
375
376 // fill in 0..width-1 if needed
377 if (xpos < width) {
378 n = width - xpos;
379 if (n > count) {
380 n = count;
381 }
382 fill_sequential(xptr, xpos, n);
383 count -= n;
384 if (0 == count) {
385 return;
386 }
387 xptr += n;
388 }
389
390 // fill the remaining with the max value
391 SkOpts::memset16(xptr, width - 1, count);
392}
static void fill_sequential(uint16_t xptr[], int pos, int count)
struct MyStruct s
double y
double x
void(* memset16)(uint16_t[], uint16_t, int)
int32_t width

◆ decal_nofilter_scale()

static void decal_nofilter_scale ( uint32_t  dst[],
SkFixed  fx,
SkFixed  dx,
int  count 
)
static

Definition at line 67 of file SkBitmapProcState_matrixProcs.cpp.

67 {
68 // can_truncate_to_fixed_for_decal() checked only that stepping fx+=dx count-1
69 // times doesn't overflow fx, so we take unusual care not to step count times.
70 for (; count > 2; count -= 2) {
71 *dst++ = pack_two_shorts( (fx + 0) >> 16,
72 (fx + dx) >> 16);
73 fx += dx+dx;
74 }
75
76 SkASSERT(count <= 2);
77 switch (count) {
78 case 2: ((uint16_t*)dst)[1] = SkToU16((fx + dx) >> 16); [[fallthrough]];
79 case 1: ((uint16_t*)dst)[0] = SkToU16((fx + 0) >> 16);
80 }
81}
#define pack_two_shorts(pri, sec)
constexpr uint16_t SkToU16(S x)
Definition: SkTo.h:24
dst
Definition: cp.py:12

◆ extract_low_bits_clamp_clamp()

static unsigned extract_low_bits_clamp_clamp ( SkFixed  fx,
int   
)
static

Definition at line 154 of file SkBitmapProcState_matrixProcs.cpp.

154 {
155 // If we're already scaled up to by max like clamp/decal,
156 // just grab the high four fractional bits.
157 return (fx >> 12) & 0xf;
158}

◆ extract_low_bits_general()

static unsigned extract_low_bits_general ( SkFixed  fx,
int  max 
)
static

Definition at line 161 of file SkBitmapProcState_matrixProcs.cpp.

161 {
162 // In repeat or mirror fx is in [0,1], so scale up by max first.
163 // TODO: remove the +1 here and the -1 at the call sites...
164 return extract_low_bits_clamp_clamp((fx & 0xffff) * (max+1), max);
165}
static unsigned extract_low_bits_clamp_clamp(SkFixed fx, int)

◆ fill_backwards()

static void fill_backwards ( uint16_t  xptr[],
int  pos,
int  count 
)
static

Definition at line 335 of file SkBitmapProcState_matrixProcs.cpp.

335 {
336 while (count --> 0) {
337 SkASSERT(pos >= 0);
338 *xptr++ = pos--;
339 }
340}
SkPoint pos

◆ fill_sequential()

static void fill_sequential ( uint16_t  xptr[],
int  pos,
int  count 
)
static

Definition at line 329 of file SkBitmapProcState_matrixProcs.cpp.

329 {
330 while (count --> 0) {
331 *xptr++ = pos++;
332 }
333}

◆ filter_affine()

template<unsigned(*)(SkFixed, int) tilex, unsigned(*)(SkFixed, int) tiley, unsigned(*)(SkFixed, int) extract_low_bits>
static void filter_affine ( const SkBitmapProcState s,
uint32_t  xy[],
int  count,
int  x,
int  y 
)
static

Definition at line 228 of file SkBitmapProcState_matrixProcs.cpp.

229 {
230 SkASSERT(!s.fInvMatrix.hasPerspective());
231
232 const SkBitmapProcStateAutoMapper mapper(s, x, y);
233
234 SkFixed oneX = s.fFilterOneX,
235 oneY = s.fFilterOneY;
236
237 SkFractionalInt fx = mapper.fractionalIntX(),
238 fy = mapper.fractionalIntY(),
239 dx = s.fInvSxFractionalInt,
240 dy = s.fInvKyFractionalInt;
241 unsigned maxX = s.fPixmap.width () - 1,
242 maxY = s.fPixmap.height() - 1;
243 while (count --> 0) {
244 *xy++ = pack<tiley, extract_low_bits>(SkFractionalIntToFixed(fy), maxY, oneY);
245 *xy++ = pack<tilex, extract_low_bits>(SkFractionalIntToFixed(fx), maxX, oneX);
246
247 fy += dy;
248 fx += dx;
249 }
250}
SkFixed3232 SkFractionalInt
#define SkFractionalIntToFixed(x)
int32_t SkFixed
Definition: SkFixed.h:25

◆ filter_scale()

template<unsigned(*)(SkFixed, int) tilex, unsigned(*)(SkFixed, int) tiley, unsigned(*)(SkFixed, int) extract_low_bits, bool tryDecal>
static void filter_scale ( const SkBitmapProcState s,
uint32_t  xy[],
int  count,
int  x,
int  y 
)
static

Definition at line 191 of file SkBitmapProcState_matrixProcs.cpp.

192 {
193 SkASSERT(s.fInvMatrix.isScaleTranslate());
194
195 const unsigned maxX = s.fPixmap.width() - 1;
196 const SkFractionalInt dx = s.fInvSxFractionalInt;
198 {
199 const SkBitmapProcStateAutoMapper mapper(s, x, y);
200 const unsigned maxY = s.fPixmap.height() - 1;
201 // compute our two Y values up front
202 *xy++ = pack<tiley, extract_low_bits>(mapper.fixedY(), maxY, s.fFilterOneY);
203 // now initialize fx
204 fx = mapper.fractionalIntX();
205 }
206
207 // For historical reasons we check both ends are < maxX rather than <= maxX.
208 // TODO: try changing this? See also can_truncate_to_fixed_for_decal().
209 if (tryDecal &&
210 (unsigned)SkFractionalIntToInt(fx ) < maxX &&
211 (unsigned)SkFractionalIntToInt(fx + dx*(count-1)) < maxX) {
212 while (count --> 0) {
213 SkFixed fixedFx = SkFractionalIntToFixed(fx);
214 SkASSERT((fixedFx >> (16 + 14)) == 0);
215 *xy++ = (fixedFx >> 12 << 14) | ((fixedFx >> 16) + 1);
216 fx += dx;
217 }
218 return;
219 }
220
221 while (count --> 0) {
222 *xy++ = pack<tilex, extract_low_bits>(SkFractionalIntToFixed(fx), maxX, s.fFilterOneX);
223 fx += dx;
224 }
225}
#define SkFractionalIntToInt(x)

◆ int_clamp()

static U16CPU int_clamp ( int  x,
int  n 
)
inlinestatic

Definition at line 292 of file SkBitmapProcState_matrixProcs.cpp.

292 {
293 if (x < 0) { x = 0; }
294 if (x >= n) { x = n - 1; }
295 return x;
296}

◆ int_mirror()

static U16CPU int_mirror ( int  x,
int  n 
)
inlinestatic

Definition at line 321 of file SkBitmapProcState_matrixProcs.cpp.

321 {
322 x = sk_int_mod(x, 2 * n);
323 if (x >= n) {
324 x = n + ~(x - n);
325 }
326 return x;
327}
static int sk_int_mod(int x, int n)

◆ int_repeat()

static U16CPU int_repeat ( int  x,
int  n 
)
inlinestatic

Definition at line 317 of file SkBitmapProcState_matrixProcs.cpp.

317 {
318 return sk_int_mod(x, n);
319}

◆ mirror()

static unsigned mirror ( SkFixed  fx,
int  max 
)
static

Definition at line 262 of file SkBitmapProcState_matrixProcs.cpp.

262 {
263 SkASSERT(max < 65535);
264 // s is 0xFFFFFFFF if we're on an odd interval, or 0 if an even interval
265 SkFixed s = SkLeftShift(fx, 15) >> 31;
266
267 // This should be exactly the same as repeat(fx ^ s, max) from here on.
268 return SK_USHIFT16( ((fx ^ s) & 0xFFFF) * (max + 1) );
269}
static unsigned SK_USHIFT16(unsigned x)
static constexpr int32_t SkLeftShift(int32_t value, int32_t shift)
Definition: SkMath.h:37

◆ mirrorx_nofilter_trans()

template<U16CPU(tiley)(int x, int n) >
static void mirrorx_nofilter_trans ( const SkBitmapProcState s,
uint32_t  xy[],
int  count,
int  x,
int  y 
)
static

Definition at line 432 of file SkBitmapProcState_matrixProcs.cpp.

433 {
434 SkASSERT(s.fInvMatrix.isTranslate());
435
436 const SkBitmapProcStateAutoMapper mapper(s, x, y);
437 *xy++ = tiley(mapper.intY(), s.fPixmap.height());
438 int xpos = mapper.intX();
439
440 const int width = s.fPixmap.width();
441 if (1 == width) {
442 // all of the following X values must be 0
443 memset(xy, 0, count * sizeof(uint16_t));
444 return;
445 }
446
447 uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
448 // need to know our start, and our initial phase (forward or backward)
449 bool forward;
450 int n;
451 int start = sk_int_mod(xpos, 2 * width);
452 if (start >= width) {
453 start = width + ~(start - width);
454 forward = false;
455 n = start + 1; // [start .. 0]
456 } else {
457 forward = true;
458 n = width - start; // [start .. width)
459 }
460 if (n > count) {
461 n = count;
462 }
463 if (forward) {
464 fill_sequential(xptr, start, n);
465 } else {
466 fill_backwards(xptr, start, n);
467 }
468 forward = !forward;
469 xptr += n;
470 count -= n;
471
472 while (count >= width) {
473 if (forward) {
474 fill_sequential(xptr, 0, width);
475 } else {
476 fill_backwards(xptr, width - 1, width);
477 }
478 forward = !forward;
479 xptr += width;
480 count -= width;
481 }
482
483 if (count > 0) {
484 if (forward) {
485 fill_sequential(xptr, 0, count);
486 } else {
487 fill_backwards(xptr, width - 1, count);
488 }
489 }
490}
static void fill_backwards(uint16_t xptr[], int pos, int count)

◆ nofilter_affine()

template<unsigned(*)(SkFixed, int) tilex, unsigned(*)(SkFixed, int) tiley>
static void nofilter_affine ( const SkBitmapProcState s,
uint32_t  xy[],
int  count,
int  x,
int  y 
)
static

Definition at line 131 of file SkBitmapProcState_matrixProcs.cpp.

132 {
133 SkASSERT(!s.fInvMatrix.hasPerspective());
134
135 const SkBitmapProcStateAutoMapper mapper(s, x, y);
136
137 SkFractionalInt fx = mapper.fractionalIntX(),
138 fy = mapper.fractionalIntY(),
139 dx = s.fInvSxFractionalInt,
140 dy = s.fInvKyFractionalInt;
141 int maxX = s.fPixmap.width () - 1,
142 maxY = s.fPixmap.height() - 1;
143
144 while (count --> 0) {
145 *xy++ = (tiley(SkFractionalIntToFixed(fy), maxY) << 16)
146 | (tilex(SkFractionalIntToFixed(fx), maxX) );
147 fx += dx;
148 fy += dy;
149 }
150}

◆ nofilter_scale()

template<unsigned(*)(SkFixed, int) tilex, unsigned(*)(SkFixed, int) tiley, bool tryDecal>
static void nofilter_scale ( const SkBitmapProcState s,
uint32_t  xy[],
int  count,
int  x,
int  y 
)
static

Definition at line 85 of file SkBitmapProcState_matrixProcs.cpp.

86 {
87 SkASSERT(s.fInvMatrix.isScaleTranslate());
88
89 // Write out our 32-bit y, and get our intial fx.
91 {
92 const SkBitmapProcStateAutoMapper mapper(s, x, y);
93 *xy++ = tiley(mapper.fixedY(), s.fPixmap.height() - 1);
94 fx = mapper.fractionalIntX();
95 }
96
97 const unsigned maxX = s.fPixmap.width() - 1;
98 if (0 == maxX) {
99 // If width == 1, all the x-values must refer to that pixel, and must be zero.
100 memset(xy, 0, count * sizeof(uint16_t));
101 return;
102 }
103
104 const SkFractionalInt dx = s.fInvSxFractionalInt;
105
106 if (tryDecal) {
107 const SkFixed fixedFx = SkFractionalIntToFixed(fx);
108 const SkFixed fixedDx = SkFractionalIntToFixed(dx);
109
110 if (can_truncate_to_fixed_for_decal(fixedFx, fixedDx, count, maxX)) {
111 decal_nofilter_scale(xy, fixedFx, fixedDx, count);
112 return;
113 }
114 }
115
116 // Remember, each x-coordinate is 16-bit.
117 for (; count >= 2; count -= 2) {
118 *xy++ = pack_two_shorts(tilex(SkFractionalIntToFixed(fx ), maxX),
119 tilex(SkFractionalIntToFixed(fx + dx), maxX));
120 fx += dx+dx;
121 }
122
123 auto xx = (uint16_t*)xy;
124 while (count --> 0) {
125 *xx++ = tilex(SkFractionalIntToFixed(fx), maxX);
126 fx += dx;
127 }
128}
static bool can_truncate_to_fixed_for_decal(SkFixed fx, SkFixed dx, int count, unsigned max)
static void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)

◆ pack()

template<unsigned(*)(SkFixed, int) tile, unsigned(*)(SkFixed, int) extract_low_bits>
static uint32_t pack ( SkFixed  f,
unsigned  max,
SkFixed  one 
)
static

Definition at line 183 of file SkBitmapProcState_matrixProcs.cpp.

183 {
184 uint32_t packed = tile(f, max); // low coordinate in high bits
185 packed = (packed << 4) | extract_low_bits(f, max); // (lerp weight _is_ coord fractional part)
186 packed = (packed << 14) | tile((f + one), max); // high coordinate in low bits
187 return packed;
188}

◆ repeat()

static unsigned repeat ( SkFixed  fx,
int  max 
)
static

Definition at line 258 of file SkBitmapProcState_matrixProcs.cpp.

258 {
259 SkASSERT(max < 65535);
260 return SK_USHIFT16((unsigned)(fx & 0xFFFF) * (max + 1));
261}

◆ repeatx_nofilter_trans()

template<U16CPU(tiley)(int x, int n) >
static void repeatx_nofilter_trans ( const SkBitmapProcState s,
uint32_t  xy[],
int  count,
int  x,
int  y 
)
static

Definition at line 395 of file SkBitmapProcState_matrixProcs.cpp.

396 {
397 SkASSERT(s.fInvMatrix.isTranslate());
398
399 const SkBitmapProcStateAutoMapper mapper(s, x, y);
400 *xy++ = tiley(mapper.intY(), s.fPixmap.height());
401 int xpos = mapper.intX();
402
403 const int width = s.fPixmap.width();
404 if (1 == width) {
405 // all of the following X values must be 0
406 memset(xy, 0, count * sizeof(uint16_t));
407 return;
408 }
409
410 uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
411 int start = sk_int_mod(xpos, width);
412 int n = width - start;
413 if (n > count) {
414 n = count;
415 }
416 fill_sequential(xptr, start, n);
417 xptr += n;
418 count -= n;
419
420 while (count >= width) {
421 fill_sequential(xptr, 0, width);
422 xptr += width;
423 count -= width;
424 }
425
426 if (count > 0) {
427 fill_sequential(xptr, 0, count);
428 }
429}

◆ sk_int_mod()

static int sk_int_mod ( int  x,
int  n 
)
inlinestatic

Definition at line 305 of file SkBitmapProcState_matrixProcs.cpp.

305 {
306 SkASSERT(n > 0);
307 if ((unsigned)x >= (unsigned)n) {
308 if (x < 0) {
309 x = n + ~(~x % n);
310 } else {
311 x = x % n;
312 }
313 }
314 return x;
315}

◆ SK_USHIFT16()

static unsigned SK_USHIFT16 ( unsigned  x)
inlinestatic

Definition at line 254 of file SkBitmapProcState_matrixProcs.cpp.

254 {
255 return x >> 16;
256}

Variable Documentation

◆ ClampX_ClampY_Procs

const SkBitmapProcState::MatrixProc ClampX_ClampY_Procs[]
static
Initial value:
= {
nofilter_scale <clamp, clamp, true>, filter_scale <clamp, clamp, extract_low_bits_clamp_clamp, true>,
nofilter_affine<clamp, clamp>, filter_affine<clamp, clamp, extract_low_bits_clamp_clamp>,
}

Definition at line 275 of file SkBitmapProcState_matrixProcs.cpp.

◆ MirrorX_MirrorY_Procs

const SkBitmapProcState::MatrixProc MirrorX_MirrorY_Procs[]
static
Initial value:
= {
nofilter_scale <mirror, mirror, false>, filter_scale <mirror, mirror, extract_low_bits_general, false>,
nofilter_affine<mirror, mirror>, filter_affine<mirror, mirror, extract_low_bits_general>,
}

Definition at line 283 of file SkBitmapProcState_matrixProcs.cpp.

◆ RepeatX_RepeatY_Procs

const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs[]
static
Initial value:
= {
nofilter_scale <repeat, repeat, false>, filter_scale <repeat, repeat, extract_low_bits_general, false>,
nofilter_affine<repeat, repeat>, filter_affine<repeat, repeat, extract_low_bits_general>
}

Definition at line 279 of file SkBitmapProcState_matrixProcs.cpp.