• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkTypes_DEFINED
9 #define SkTypes_DEFINED
10 
11 /** \file SkTypes.h
12 */
13 
14 // Pre-SkUserConfig.h setup.
15 
16 // Allows embedders that want to disable macros that take arguments to just
17 // define that symbol to be one of these
18 #define SK_NOTHING_ARG1(arg1)
19 #define SK_NOTHING_ARG2(arg1, arg2)
20 #define SK_NOTHING_ARG3(arg1, arg2, arg3)
21 
22 #if !defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_WIN) && \
23     !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC)
24 
25     #ifdef __APPLE__
26         #include "TargetConditionals.h"
27     #endif
28 
29     #if defined(_WIN32) || defined(__SYMBIAN32__)
30         #define SK_BUILD_FOR_WIN
31     #elif defined(ANDROID) || defined(__ANDROID__)
32         #define SK_BUILD_FOR_ANDROID
33     #elif defined(linux) || defined(__linux) || defined(__FreeBSD__) || \
34           defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__) || \
35           defined(__DragonFly__) || defined(__Fuchsia__) || \
36           defined(__GLIBC__) || defined(__GNU__) || defined(__unix__)
37         #define SK_BUILD_FOR_UNIX
38     #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
39         #define SK_BUILD_FOR_IOS
40     #else
41         #define SK_BUILD_FOR_MAC
42     #endif
43 
44 #endif
45 
46 #if defined(SK_BUILD_FOR_WIN) && !defined(__clang__)
47     #if !defined(SK_RESTRICT)
48         #define SK_RESTRICT __restrict
49     #endif
50     #if !defined(SK_WARN_UNUSED_RESULT)
51         #define SK_WARN_UNUSED_RESULT
52     #endif
53 #endif
54 
55 #if !defined(SK_RESTRICT)
56     #define SK_RESTRICT __restrict__
57 #endif
58 
59 #if !defined(SK_WARN_UNUSED_RESULT)
60     #define SK_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
61 #endif
62 
63 #if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN)
64     #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
65         #define SK_CPU_BENDIAN
66     #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
67         #define SK_CPU_LENDIAN
68     #elif defined(__sparc) || defined(__sparc__) || \
69       defined(_POWER) || defined(__powerpc__) || \
70       defined(__ppc__) || defined(__hppa) || \
71       defined(__PPC__) || defined(__PPC64__) || \
72       defined(_MIPSEB) || defined(__ARMEB__) || \
73       defined(__s390__) || \
74       (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
75       (defined(__ia64) && defined(__BIG_ENDIAN__))
76          #define SK_CPU_BENDIAN
77     #else
78         #define SK_CPU_LENDIAN
79     #endif
80 #endif
81 
82 #if defined(__i386) || defined(_M_IX86) ||  defined(__x86_64__) || defined(_M_X64)
83   #define SK_CPU_X86 1
84 #endif
85 
86 /**
87  *  SK_CPU_SSE_LEVEL
88  *
89  *  If defined, SK_CPU_SSE_LEVEL should be set to the highest supported level.
90  *  On non-intel CPU this should be undefined.
91  */
92 #define SK_CPU_SSE_LEVEL_SSE1     10
93 #define SK_CPU_SSE_LEVEL_SSE2     20
94 #define SK_CPU_SSE_LEVEL_SSE3     30
95 #define SK_CPU_SSE_LEVEL_SSSE3    31
96 #define SK_CPU_SSE_LEVEL_SSE41    41
97 #define SK_CPU_SSE_LEVEL_SSE42    42
98 #define SK_CPU_SSE_LEVEL_AVX      51
99 #define SK_CPU_SSE_LEVEL_AVX2     52
100 #define SK_CPU_SSE_LEVEL_AVX512   60
101 
102 // When targetting iOS and using gyp to generate the build files, it is not
103 // possible to select files to build depending on the architecture (i.e. it
104 // is not possible to use hand optimized assembly implementation). In that
105 // configuration SK_BUILD_NO_OPTS is defined. Remove optimisation then.
106 #ifdef SK_BUILD_NO_OPTS
107     #define SK_CPU_SSE_LEVEL 0
108 #endif
109 
110 // Are we in GCC/Clang?
111 #ifndef SK_CPU_SSE_LEVEL
112     // These checks must be done in descending order to ensure we set the highest
113     // available SSE level.
114     #if defined(__AVX512F__)
115         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_AVX512
116     #elif defined(__AVX2__)
117         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_AVX2
118     #elif defined(__AVX__)
119         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_AVX
120     #elif defined(__SSE4_2__)
121         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE42
122     #elif defined(__SSE4_1__)
123         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE41
124     #elif defined(__SSSE3__)
125         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSSE3
126     #elif defined(__SSE3__)
127         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE3
128     #elif defined(__SSE2__)
129         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE2
130     #endif
131 #endif
132 
133 // Are we in VisualStudio?
134 #ifndef SK_CPU_SSE_LEVEL
135     // These checks must be done in descending order to ensure we set the highest
136     // available SSE level. 64-bit intel guarantees at least SSE2 support.
137     #if defined(__AVX2__)
138         #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_AVX2
139     #elif defined(__AVX__)
140         #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_AVX
141     #elif defined(_M_X64) || defined(_M_AMD64)
142         #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_SSE2
143     #elif defined(_M_IX86_FP)
144         #if _M_IX86_FP >= 2
145             #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE2
146         #elif _M_IX86_FP == 1
147             #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE1
148         #endif
149     #endif
150 #endif
151 
152 // ARM defines
153 #if defined(__arm__) && (!defined(__APPLE__) || !TARGET_IPHONE_SIMULATOR)
154     #define SK_CPU_ARM32
155 #elif defined(__aarch64__) && !defined(SK_BUILD_NO_OPTS)
156     #define SK_CPU_ARM64
157 #endif
158 
159 // All 64-bit ARM chips have NEON.  Many 32-bit ARM chips do too.
160 #if !defined(SK_ARM_HAS_NEON) && !defined(SK_BUILD_NO_OPTS) && defined(__ARM_NEON)
161     #define SK_ARM_HAS_NEON
162 #endif
163 
164 // Really this __APPLE__ check shouldn't be necessary, but it seems that Apple's Clang defines
165 // __ARM_FEATURE_CRC32 for -arch arm64, even though their chips don't support those instructions!
166 #if defined(__ARM_FEATURE_CRC32) && !defined(__APPLE__)
167     #define SK_ARM_HAS_CRC32
168 #endif
169 
170 
171 // DLL/.so exports.
172 #if !defined(SKIA_IMPLEMENTATION)
173     #define SKIA_IMPLEMENTATION 0
174 #endif
175 #if !defined(SK_API)
176     #if defined(SKIA_DLL)
177         #if defined(_MSC_VER)
178             #if SKIA_IMPLEMENTATION
179                 #define SK_API __declspec(dllexport)
180             #else
181                 #define SK_API __declspec(dllimport)
182             #endif
183         #else
184             #define SK_API __attribute__((visibility("default")))
185         #endif
186     #else
187         #define SK_API
188     #endif
189 #endif
190 
191 // SK_SPI is functionally identical to SK_API, but used within src to clarify that it's less stable
192 #if !defined(SK_SPI)
193     #define SK_SPI SK_API
194 #endif
195 
196 // IWYU pragma: begin_exports
197 #if defined (SK_USER_CONFIG_HEADER)
198     #include SK_USER_CONFIG_HEADER
199 #else
200     #include "include/config/SkUserConfig.h"
201 #endif
202 #include <stddef.h>
203 #include <stdint.h>
204 // IWYU pragma: end_exports
205 
206 // Post SkUserConfig.h checks and such.
207 #if !defined(SK_DEBUG) && !defined(SK_RELEASE)
208     #ifdef NDEBUG
209         #define SK_RELEASE
210     #else
211         #define SK_DEBUG
212     #endif
213 #endif
214 
215 #if defined(SK_DEBUG) && defined(SK_RELEASE)
216 #  error "cannot define both SK_DEBUG and SK_RELEASE"
217 #elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
218 #  error "must define either SK_DEBUG or SK_RELEASE"
219 #endif
220 
221 #if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
222 #  error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN"
223 #elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
224 #  error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN"
225 #endif
226 
227 #if defined(SK_CPU_BENDIAN) && !defined(I_ACKNOWLEDGE_SKIA_DOES_NOT_SUPPORT_BIG_ENDIAN)
228     #error "The Skia team is not endian-savvy enough to support big-endian CPUs."
229     #error "If you still want to use Skia,"
230     #error "please define I_ACKNOWLEDGE_SKIA_DOES_NOT_SUPPORT_BIG_ENDIAN."
231 #endif
232 
233 #if !defined(SK_ATTRIBUTE)
234 #  if defined(__clang__) || defined(__GNUC__)
235 #    define SK_ATTRIBUTE(attr) __attribute__((attr))
236 #  else
237 #    define SK_ATTRIBUTE(attr)
238 #  endif
239 #endif
240 
241 #if !defined(SK_SUPPORT_GPU)
242 #  define SK_SUPPORT_GPU 1
243 #endif
244 
245 /**
246  * If GPU is enabled but no GPU backends are enabled then enable GL by default.
247  * Traditionally clients have relied on Skia always building with the GL backend
248  * and opting in to additional backends. TODO: Require explicit opt in for GL.
249  */
250 #if SK_SUPPORT_GPU
251 #  if !defined(SK_GL) && !defined(SK_VULKAN) && !defined(SK_METAL)
252 #    define SK_GL
253 #  endif
254 #endif
255 
256 #if !defined(SK_SUPPORT_ATLAS_TEXT)
257 #  define SK_SUPPORT_ATLAS_TEXT 0
258 #elif SK_SUPPORT_ATLAS_TEXT && !SK_SUPPORT_GPU
259 #  error "SK_SUPPORT_ATLAS_TEXT requires SK_SUPPORT_GPU"
260 #endif
261 
262 #if !defined(SkUNREACHABLE)
263 #  if defined(_MSC_VER) && !defined(__clang__)
264 #    define SkUNREACHABLE __assume(false)
265 #  else
266 #    define SkUNREACHABLE __builtin_unreachable()
267 #  endif
268 #endif
269 
270 #if defined(SK_BUILD_FOR_GOOGLE3)
271     void SkDebugfForDumpStackTrace(const char* data, void* unused);
272     void DumpStackTrace(int skip_count, void w(const char*, void*), void* arg);
273 #  define SK_DUMP_GOOGLE3_STACK() DumpStackTrace(0, SkDebugfForDumpStackTrace, nullptr)
274 #else
275 #  define SK_DUMP_GOOGLE3_STACK()
276 #endif
277 
278 #ifdef SK_BUILD_FOR_WIN
279     // Lets visual studio follow error back to source
280     #define SK_DUMP_LINE_FORMAT(message) \
281         SkDebugf("%s(%d): fatal error: \"%s\"\n", __FILE__, __LINE__, message)
282 #else
283     #define SK_DUMP_LINE_FORMAT(message) \
284         SkDebugf("%s:%d: fatal error: \"%s\"\n", __FILE__, __LINE__, message)
285 #endif
286 
287 #ifndef SK_ABORT
288 #  define SK_ABORT(message) \
289     do { \
290        SK_DUMP_LINE_FORMAT(message); \
291        SK_DUMP_GOOGLE3_STACK(); \
292        sk_abort_no_print(); \
293        SkUNREACHABLE; \
294     } while (false)
295 #endif
296 
297 // If SK_R32_SHIFT is set, we'll use that to choose RGBA or BGRA.
298 // If not, we'll default to RGBA everywhere except BGRA on Windows.
299 #if defined(SK_R32_SHIFT)
300     static_assert(SK_R32_SHIFT == 0 || SK_R32_SHIFT == 16, "");
301 #elif defined(SK_BUILD_FOR_WIN)
302     #define SK_R32_SHIFT 16
303 #else
304     #define SK_R32_SHIFT 0
305 #endif
306 
307 #if defined(SK_B32_SHIFT)
308     static_assert(SK_B32_SHIFT == (16-SK_R32_SHIFT), "");
309 #else
310     #define SK_B32_SHIFT (16-SK_R32_SHIFT)
311 #endif
312 
313 #define SK_G32_SHIFT 8
314 #define SK_A32_SHIFT 24
315 
316 
317 /**
318  * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time. The
319  * relationship between the byte order and shift values depends on machine endianness. If the shift
320  * order is R=0, G=8, B=16, A=24 then ((char*)&pmcolor)[0] will produce the R channel on a little
321  * endian machine and the A channel on a big endian machine. Thus, given those shifts values,
322  * SK_PMCOLOR_BYTE_ORDER(R,G,B,A) will be true on a little endian machine and
323  * SK_PMCOLOR_BYTE_ORDER(A,B,G,R) will be true on a big endian machine.
324  */
325 #ifdef SK_CPU_BENDIAN
326 #  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \
327         (SK_ ## C3 ## 32_SHIFT == 0  &&             \
328          SK_ ## C2 ## 32_SHIFT == 8  &&             \
329          SK_ ## C1 ## 32_SHIFT == 16 &&             \
330          SK_ ## C0 ## 32_SHIFT == 24)
331 #else
332 #  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \
333         (SK_ ## C0 ## 32_SHIFT == 0  &&             \
334          SK_ ## C1 ## 32_SHIFT == 8  &&             \
335          SK_ ## C2 ## 32_SHIFT == 16 &&             \
336          SK_ ## C3 ## 32_SHIFT == 24)
337 #endif
338 
339 #if defined SK_DEBUG && defined SK_BUILD_FOR_WIN
340     #ifdef free
341         #undef free
342     #endif
343     #include <crtdbg.h>
344     #undef free
345 #endif
346 
347 #if !defined(SK_UNUSED)
348 #  if !defined(__clang__) && defined(_MSC_VER)
349 #    define SK_UNUSED __pragma(warning(suppress:4189))
350 #  else
351 #    define SK_UNUSED SK_ATTRIBUTE(unused)
352 #  endif
353 #endif
354 
355 /**
356  * If your judgment is better than the compiler's (i.e. you've profiled it),
357  * you can use SK_ALWAYS_INLINE to force inlining. E.g.
358  *     inline void someMethod() { ... }             // may not be inlined
359  *     SK_ALWAYS_INLINE void someMethod() { ... }   // should always be inlined
360  */
361 #if !defined(SK_ALWAYS_INLINE)
362 #  if defined(SK_BUILD_FOR_WIN)
363 #    define SK_ALWAYS_INLINE __forceinline
364 #  else
365 #    define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline
366 #  endif
367 #endif
368 
369 /**
370  * If your judgment is better than the compiler's (i.e. you've profiled it),
371  * you can use SK_NEVER_INLINE to prevent inlining.
372  */
373 #if !defined(SK_NEVER_INLINE)
374 #  if defined(SK_BUILD_FOR_WIN)
375 #    define SK_NEVER_INLINE __declspec(noinline)
376 #  else
377 #    define SK_NEVER_INLINE SK_ATTRIBUTE(noinline)
378 #  endif
379 #endif
380 
381 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
382     #define SK_PREFETCH(ptr) _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)
383 #elif defined(__GNUC__)
384     #define SK_PREFETCH(ptr) __builtin_prefetch(ptr)
385 #else
386     #define SK_PREFETCH(ptr)
387 #endif
388 
389 #ifndef SK_PRINTF_LIKE
390 #  if defined(__clang__) || defined(__GNUC__)
391 #    define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
392 #  else
393 #    define SK_PRINTF_LIKE(A, B)
394 #  endif
395 #endif
396 
397 #ifndef SK_SIZE_T_SPECIFIER
398 #  if defined(_MSC_VER) && !defined(__clang__)
399 #    define SK_SIZE_T_SPECIFIER "%Iu"
400 #  else
401 #    define SK_SIZE_T_SPECIFIER "%zu"
402 #  endif
403 #endif
404 
405 #ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
406     #define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
407 #endif
408 
409 #if !defined(SK_GAMMA_EXPONENT)
410     #define SK_GAMMA_EXPONENT (0.0f)  // SRGB
411 #endif
412 
413 #ifndef GR_TEST_UTILS
414 #  define GR_TEST_UTILS 0
415 #endif
416 
417 #if defined(SK_HISTOGRAM_ENUMERATION) && defined(SK_HISTOGRAM_BOOLEAN)
418 #  define SK_HISTOGRAMS_ENABLED 1
419 #else
420 #  define SK_HISTOGRAMS_ENABLED 0
421 #endif
422 
423 #ifndef SK_HISTOGRAM_BOOLEAN
424 #  define SK_HISTOGRAM_BOOLEAN(name, value)
425 #endif
426 
427 #ifndef SK_HISTOGRAM_ENUMERATION
428 #  define SK_HISTOGRAM_ENUMERATION(name, value, boundary_value)
429 #endif
430 
431 #ifndef SK_DISABLE_LEGACY_SHADERCONTEXT
432 #define SK_ENABLE_LEGACY_SHADERCONTEXT
433 #endif
434 
435 /** Called internally if we hit an unrecoverable error.
436     The platform implementation must not return, but should either throw
437     an exception or otherwise exit.
438 */
439 SK_API extern void sk_abort_no_print(void);
440 
441 #ifndef SkDebugf
442     SK_API void SkDebugf(const char format[], ...);
443 #endif
444 
445 // SkASSERT, SkASSERTF and SkASSERT_RELEASE can be used as stand alone assertion expressions, e.g.
446 //    uint32_t foo(int x) {
447 //        SkASSERT(x > 4);
448 //        return x - 4;
449 //    }
450 // and are also written to be compatible with constexpr functions:
451 //    constexpr uint32_t foo(int x) {
452 //        return SkASSERT(x > 4),
453 //               x - 4;
454 //    }
455 #define SkASSERT_RELEASE(cond) \
456         static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT("assert(" #cond ")"); }() )
457 
458 #ifdef SK_DEBUG
459     #define SkASSERT(cond) SkASSERT_RELEASE(cond)
460     #define SkASSERTF(cond, fmt, ...) static_cast<void>( (cond) ? (void)0 : [&]{ \
461                                           SkDebugf(fmt"\n", __VA_ARGS__);        \
462                                           SK_ABORT("assert(" #cond ")");         \
463                                       }() )
464     #define SkDEBUGFAIL(message)        SK_ABORT(message)
465     #define SkDEBUGFAILF(fmt, ...)      SkASSERTF(false, fmt, ##__VA_ARGS__)
466     #define SkDEBUGCODE(...)            __VA_ARGS__
467     #define SkDEBUGF(...)               SkDebugf(__VA_ARGS__)
468     #define SkAssertResult(cond)        SkASSERT(cond)
469 #else
470     #define SkASSERT(cond)            static_cast<void>(0)
471     #define SkASSERTF(cond, fmt, ...) static_cast<void>(0)
472     #define SkDEBUGFAIL(message)
473     #define SkDEBUGFAILF(fmt, ...)
474     #define SkDEBUGCODE(...)
475     #define SkDEBUGF(...)
476 
477     // unlike SkASSERT, this macro executes its condition in the non-debug build.
478     // The if is present so that this can be used with functions marked SK_WARN_UNUSED_RESULT.
479     #define SkAssertResult(cond)         if (cond) {} do {} while(false)
480 #endif
481 
482 ////////////////////////////////////////////////////////////////////////////////
483 
484 /** Fast type for unsigned 8 bits. Use for parameter passing and local
485     variables, not for storage
486 */
487 typedef unsigned U8CPU;
488 
489 /** Fast type for unsigned 16 bits. Use for parameter passing and local
490     variables, not for storage
491 */
492 typedef unsigned U16CPU;
493 
494 /** @return false or true based on the condition
495 */
SkToBool(const T & x)496 template <typename T> static constexpr bool SkToBool(const T& x) { return 0 != x; }
497 
498 static constexpr int16_t SK_MaxS16 = INT16_MAX;
499 static constexpr int16_t SK_MinS16 = -SK_MaxS16;
500 
501 static constexpr int32_t SK_MaxS32 = INT32_MAX;
502 static constexpr int32_t SK_MinS32 = -SK_MaxS32;
503 static constexpr int32_t SK_NaN32  = INT32_MIN;
504 
505 static constexpr int64_t SK_MaxS64 = INT64_MAX;
506 static constexpr int64_t SK_MinS64 = -SK_MaxS64;
507 
SkLeftShift(int32_t value,int32_t shift)508 static inline constexpr int32_t SkLeftShift(int32_t value, int32_t shift) {
509     return (int32_t) ((uint32_t) value << shift);
510 }
511 
SkLeftShift(int64_t value,int32_t shift)512 static inline constexpr int64_t SkLeftShift(int64_t value, int32_t shift) {
513     return (int64_t) ((uint64_t) value << shift);
514 }
515 
516 ////////////////////////////////////////////////////////////////////////////////
517 
518 /** @return the number of entries in an array (not a pointer)
519 */
520 template <typename T, size_t N> char (&SkArrayCountHelper(T (&array)[N]))[N];
521 #define SK_ARRAY_COUNT(array) (sizeof(SkArrayCountHelper(array)))
522 
523 ////////////////////////////////////////////////////////////////////////////////
524 
SkAlign2(T x)525 template <typename T> static constexpr T SkAlign2(T x) { return (x + 1) >> 1 << 1; }
SkAlign4(T x)526 template <typename T> static constexpr T SkAlign4(T x) { return (x + 3) >> 2 << 2; }
SkAlign8(T x)527 template <typename T> static constexpr T SkAlign8(T x) { return (x + 7) >> 3 << 3; }
528 
SkIsAlign2(T x)529 template <typename T> static constexpr bool SkIsAlign2(T x) { return 0 == (x & 1); }
SkIsAlign4(T x)530 template <typename T> static constexpr bool SkIsAlign4(T x) { return 0 == (x & 3); }
SkIsAlign8(T x)531 template <typename T> static constexpr bool SkIsAlign8(T x) { return 0 == (x & 7); }
532 
SkAlignPtr(T x)533 template <typename T> static constexpr T SkAlignPtr(T x) {
534     return sizeof(void*) == 8 ? SkAlign8(x) : SkAlign4(x);
535 }
SkIsAlignPtr(T x)536 template <typename T> static constexpr bool SkIsAlignPtr(T x) {
537     return sizeof(void*) == 8 ? SkIsAlign8(x) : SkIsAlign4(x);
538 }
539 
540 typedef uint32_t SkFourByteTag;
SkSetFourByteTag(char a,char b,char c,char d)541 static inline constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d) {
542     return (((uint8_t)a << 24) | ((uint8_t)b << 16) | ((uint8_t)c << 8) | (uint8_t)d);
543 }
544 
545 ////////////////////////////////////////////////////////////////////////////////
546 
547 /** 32 bit integer to hold a unicode value
548 */
549 typedef int32_t SkUnichar;
550 
551 /** 16 bit unsigned integer to hold a glyph index
552 */
553 typedef uint16_t SkGlyphID;
554 
555 /** 32 bit value to hold a millisecond duration
556     Note that SK_MSecMax is about 25 days.
557 */
558 typedef uint32_t SkMSec;
559 
560 /** Maximum representable milliseconds; 24d 20h 31m 23.647s.
561 */
562 static constexpr SkMSec SK_MSecMax = INT32_MAX;
563 
564 /** The generation IDs in Skia reserve 0 has an invalid marker.
565 */
566 static constexpr uint32_t SK_InvalidGenID = 0;
567 
568 /** The unique IDs in Skia reserve 0 has an invalid marker.
569 */
570 static constexpr uint32_t SK_InvalidUniqueID = 0;
571 
SkAbs32(int32_t value)572 static inline int32_t SkAbs32(int32_t value) {
573     SkASSERT(value != SK_NaN32);  // The most negative int32_t can't be negated.
574     if (value < 0) {
575         value = -value;
576     }
577     return value;
578 }
579 
SkTAbs(T value)580 template <typename T> static inline T SkTAbs(T value) {
581     if (value < 0) {
582         value = -value;
583     }
584     return value;
585 }
586 
587 /** @return value pinned (clamped) between min and max, inclusively.
588 
589     NOTE: Unlike std::clamp, SkTPin has well-defined behavior if 'value' is a
590           floating point NaN. In that case, 'max' is returned.
591 */
SkTPin(const T & value,const T & min,const T & max)592 template <typename T> static constexpr const T& SkTPin(const T& value, const T& min, const T& max) {
593     return value < min ? min : (value < max ? value : max);
594 }
595 
596 ////////////////////////////////////////////////////////////////////////////////
597 
598 /** Indicates whether an allocation should count against a cache budget.
599 */
600 enum class SkBudgeted : bool {
601     kNo  = false,
602     kYes = true
603 };
604 
605 /** Indicates whether a backing store needs to be an exact match or can be
606     larger than is strictly necessary
607 */
608 enum class SkBackingFit {
609     kApprox,
610     kExact
611 };
612 
613 #endif
614