roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
blending.h
Go to the documentation of this file.
1#pragma once
2
3#include <inttypes.h>
4
5#include <cmath>
6#include <type_traits>
7#include <utility>
8
12#include "roo_io/data/byte_order.h"
13#include "roo_logging/stream.h"
14namespace roo_display {
15
16/// Porter-Duff style blending modes.
17enum class BlendingMode {
18
19 /// The new ARGB8888 value completely replaces the old one.
20 kSource,
21
22 /// Source is placed (alpha-blended) over the destination. This is the
23 /// default blending mode.
25
26 /// The source that overlaps the destination, replaces the destination.
28
29 /// Source which overlaps the destination, replaces the destination.
30 /// Destination is placed elsewhere.
32
33 /// Only the destination will be present.
35
36 /// Destination is placed over the source.
38
39 /// Destination which overlaps the source, replaces the source.
41
42 /// Destination which overlaps the source replaces the source. Source is
43 /// placed elsewhere.
45
46 /// No regions are enabled.
47 kClear,
48
49 /// Source is placed, where it falls outside of the destination.
51
52 /// Destination is placed, where it falls outside of the source.
54
55 /// The non-overlapping regions of source and destination are combined.
56 kXor,
57
58 /// Similar to kSourceOver, but assumes that the destination is
59 /// opaque.
60 ///
61 /// Don't use it directly. It is used internally by the framework, as an
62 /// optimization, when it is detected that source-over is performed over an
63 /// opaque background.
65
66 /// Similar to kDestinationOver, but assumes that the source is
67 /// opaque.
69};
70
71[[deprecated("Use `BlendingMode::kSource` instead.")]]
73[[deprecated("Use `BlendingMode::kSourceOver` instead.")]]
75[[deprecated("Use `BlendingMode::kSourceIn` instead.")]]
77[[deprecated("Use `BlendingMode::kSourceAtop` instead.")]]
79[[deprecated("Use `BlendingMode::kDestination` instead.")]]
81[[deprecated("Use `BlendingMode::kDestinationOver` instead.")]]
84[[deprecated("Use `BlendingMode::kDestinationIn` instead.")]]
87[[deprecated("Use `BlendingMode::kDestinationAtop` instead.")]]
90[[deprecated("Use `BlendingMode::kClear` instead.")]]
92[[deprecated("Use `BlendingMode::kSourceOut` instead.")]]
94[[deprecated("Use `BlendingMode::kDestinationOut` instead.")]]
97[[deprecated("Use `BlendingMode::kXor` instead.")]]
99
100roo_logging::Stream& operator<<(roo_logging::Stream& os, BlendingMode mode);
101
102/// Transparency information for a stream or color mode.
104 /// All colors are fully opaque.
105 kNone,
106 /// Colors are either fully opaque or fully transparent.
107 kCrude,
108 /// Colors may include partial transparency (alpha channel).
109 kFull,
110};
111
112[[deprecated("Use `TransparencyMode::kNone` instead.")]]
114[[deprecated("Use `TransparencyMode::kCrude` instead.")]]
116[[deprecated("Use `TransparencyMode::kFull` instead.")]]
118
119roo_logging::Stream& operator<<(roo_logging::Stream& os, TransparencyMode mode);
120
121namespace internal {
122
123// In practice, seems to be measurably faster than actually dividing by 255
124// and counting on the compiler to optimize.
125inline constexpr uint8_t __div_255(uint16_t arg) { return (arg * 257) >> 16; }
126
127inline constexpr uint8_t __div_255_rounded(uint16_t arg) {
128 return __div_255(arg + 128);
129}
130
131inline constexpr uint8_t __div_65280(uint32_t arg) {
132 return ((arg >> 8) + (arg >> 16)) >> 8;
133}
134
135inline constexpr uint8_t __div_65280_rounded(uint32_t arg) {
136 return __div_65280(arg + 32640);
137}
138
139// Helper to minimize the number of similar switch statements in the code below.
140template <typename Functor, typename... Args>
142 -> decltype(std::declval<Functor>()
143 .template operator()<BlendingMode::kSourceOver>(args...)) {
144 Functor functor;
146 return functor.template operator()<BlendingMode::kSource>(
147 std::forward<Args>(args)...);
149 return functor.template operator()<BlendingMode::kSourceOver>(
150 std::forward<Args>(args)...);
152 return functor.template operator()<BlendingMode::kSourceOverOpaque>(
153 std::forward<Args>(args)...);
154 } else {
155 switch (blending_mode) {
157 return functor.template operator()<BlendingMode::kSourceIn>(
158 std::forward<Args>(args)...);
160 return functor.template operator()<BlendingMode::kSourceAtop>(
161 std::forward<Args>(args)...);
163 return functor.template operator()<BlendingMode::kDestination>(
164 std::forward<Args>(args)...);
166 return functor.template operator()<BlendingMode::kDestinationOver>(
167 std::forward<Args>(args)...);
169 return functor
170 .template operator()<BlendingMode::kDestinationOverOpaque>(
171 std::forward<Args>(args)...);
173 return functor.template operator()<BlendingMode::kDestinationIn>(
174 std::forward<Args>(args)...);
176 return functor.template operator()<BlendingMode::kDestinationAtop>(
177 std::forward<Args>(args)...);
179 return functor.template operator()<BlendingMode::kClear>(
180 std::forward<Args>(args)...);
182 return functor.template operator()<BlendingMode::kSourceOut>(
183 std::forward<Args>(args)...);
185 return functor.template operator()<BlendingMode::kDestinationOut>(
186 std::forward<Args>(args)...);
188 return functor.template operator()<BlendingMode::kXor>(
189 std::forward<Args>(args)...);
190 default:
191 return functor.template operator()<BlendingMode::kSourceOver>(
192 std::forward<Args>(args)...);
193 }
194 }
195}
196
197} // namespace internal
198
199template <BlendingMode blending_mode>
200struct BlendOp;
201
202template <>
204 inline Color operator()(Color dst, Color src) const { return src; }
205};
206
207template <>
209 inline Color operator()(Color dst, Color src) const {
210 uint16_t alpha = src.a();
211 uint16_t inv_alpha = alpha ^ 0xFF;
212 uint8_t r = (uint8_t)(internal::__div_255_rounded(alpha * src.r() +
213 inv_alpha * dst.r()));
214 uint8_t g = (uint8_t)(internal::__div_255_rounded(alpha * src.g() +
215 inv_alpha * dst.g()));
216 uint8_t b = (uint8_t)(internal::__div_255_rounded(alpha * src.b() +
217 inv_alpha * dst.b()));
218
219 // https://stackoverflow.com/questions/12011081
220 // The implementation commented out below is slightly faster (14ms vs 16ms
221 // in a microbenchmark) than the implementation above, but it is one-off
222 // for some important cases, like fg = 0x00000000 (transparency), and
223 // bg = 0xFFFFFFFF (white), which should produce white but produces
224 // 0xFFFEFEFE.
225 //
226 // uint16_t alpha = fgc.a() + 1;
227 // uint16_t inv_alpha = 256 - alpha;
228 // uint8_t r = (uint8_t)((alpha * fgc.r() + inv_alpha * bgc.r()) >> 8);
229 // uint8_t g = (uint8_t)((alpha * fgc.g() + inv_alpha * bgc.g()) >> 8);
230 // uint8_t b = (uint8_t)((alpha * fgc.b() + inv_alpha * bgc.b()) >> 8);
231 //
232 return Color(0xFF000000 | r << 16 | g << 8 | b);
233 }
234};
235
236#ifndef ROO_DISPLAY_BLENDING_PRECITION
237#define ROO_DISPLAY_BLENDING_PRECISION 1
238#endif
239
240template <>
242 // Fa = 1; Fb = 1 – αs
243 // co = αs x Cs + αb x Cb x (1 – αs)
244 // αo = αs + αb x (1 – αs)
245
246 inline Color operator()(Color dst, Color src) const {
247 uint16_t src_alpha = src.a();
248 if (src_alpha == 0xFF) {
249 return src;
250 }
251 uint16_t dst_alpha = dst.a();
252 if (dst_alpha == 0xFF) {
254 }
255 if (src_alpha == 0) {
256 return dst;
257 }
258 if (dst_alpha == 0) {
259 return src;
260 }
261
262 // Blends a+b so that, when later applied over c, the result is the same as
263 // if they were applied in succession; e.g. c+(a+b) == (c+a)+b.
264
265#if ROO_DISPLAY_BLENDING_PRECISION == 2
266 // Microbenchmark timing: 24970 us
267 uint32_t a16 =
268 (uint16_t)dst_alpha * 255 + (uint16_t)src_alpha * (255 - dst_alpha);
269 uint8_t alpha = internal::__div_255_rounded(a16);
270 uint16_t cs = (256 * 255 * 255 * src_alpha + a16 / 2 + 1) / a16;
271 uint16_t cd = 256 * 255 - cs;
272 uint8_t r =
273 (uint8_t)(internal::__div_65280_rounded(cs * src.r() + cd * dst.r()));
274 uint8_t g =
275 (uint8_t)(internal::__div_65280_rounded(cs * src.g() + cd * dst.g()));
276 uint8_t b =
277 (uint8_t)(internal::__div_65280_rounded(cs * src.b() + cd * dst.b()));
278
279#elif ROO_DISPLAY_BLENDING_PRECISION == 1
280 // Microbenchmark timing: 22856 us
281 uint16_t tmp = dst_alpha * src_alpha;
282 uint16_t alpha = dst_alpha + src_alpha - internal::__div_255_rounded(tmp);
283 uint16_t cs = (src_alpha * 255) / alpha;
284 uint16_t cd = 255 - cs;
285
286 uint8_t r =
287 (uint8_t)(internal::__div_255_rounded(cs * src.r() + cd * dst.r()));
288 uint8_t g =
289 (uint8_t)(internal::__div_255_rounded(cs * src.g() + cd * dst.g()));
290 uint8_t b =
291 (uint8_t)(internal::__div_255_rounded(cs * src.b() + cd * dst.b()));
292
293#elif ROO_DISPLAY_BLENDING_PRECISION == 0
294 // Microbenchmark timing: 21925 us
295 uint16_t tmp = dst_alpha * src_alpha;
296 uint16_t alpha = dst_alpha + src_alpha - internal::__div_255_rounded(tmp);
297 uint16_t cs = ((src_alpha + 1) << 8) / (alpha + 1);
298 uint16_t cd = 256 - cs;
299
300 uint8_t r = (uint8_t)((cs * src.r() + cd * dst.r() + 128) >> 8);
301 uint8_t g = (uint8_t)((cs * src.g() + cd * dst.g() + 128) >> 8);
302 uint8_t b = (uint8_t)((cs * src.b() + cd * dst.b() + 128) >> 8);
303
304#endif
305
306 return Color(alpha << 24 | r << 16 | g << 8 | b);
307 }
308};
309
310template <>
312 // Fa = αb; Fb = 1 – αs
313 // co = αs x Cs x αb + αb x Cb x (1 – αs)
314 // αo = αs x αb + αb x (1 – αs)
315
316 inline Color operator()(Color dst, Color src) const {
317 uint16_t src_alpha = src.a();
318 uint16_t dst_alpha = dst.a();
319 if (src_alpha == 0xFF) {
320 return src.withA(dst_alpha);
321 }
322 if (src_alpha == 0) {
323 return dst;
324 }
325 if (dst_alpha == 0) {
326 return color::Background;
327 }
328 uint16_t src_multi = src_alpha;
329 uint16_t dst_multi = 255 - src_alpha;
330
331 uint8_t r = (uint8_t)((src_multi * src.r() + dst_multi * dst.r()) >> 8);
332 uint8_t g = (uint8_t)((src_multi * src.g() + dst_multi * dst.g()) >> 8);
333 uint8_t b = (uint8_t)((src_multi * src.b() + dst_multi * dst.b()) >> 8);
334 return Color(dst_alpha << 24 | r << 16 | g << 8 | b);
335 }
336};
337
338template <>
340 inline Color operator()(Color dst, Color src) const { return dst; }
341};
342
343template <>
345 inline Color operator()(Color dst, Color src) const {
347 }
348};
349
350template <>
352 inline Color operator()(Color dst, Color src) const {
353 return BlendOp<BlendingMode::kSourceOver>()(src, dst);
354 }
355};
356
357template <>
359 inline Color operator()(Color dst, Color src) const {
360 return dst == color::Transparent && src == color::Transparent
361 ? color::Transparent
362 : color::Background;
363 }
364};
365
366template <>
368 // Fa = αb; Fb = 0
369 // co = αs x Cs x αb
370 // αo = αs x αb
371 inline Color operator()(Color dst, Color src) const {
372 uint16_t dst_alpha = dst.a();
373 if (dst_alpha == 0xFF) {
374 return src;
375 }
376 uint16_t src_alpha = src.a();
377 if (src_alpha == 0xFF) {
378 return src.withA(dst_alpha);
379 }
380 if (src_alpha == 0) {
381 return color::Background;
382 }
383 return src.withA(internal::__div_255_rounded(src_alpha * dst_alpha));
384 }
385};
386
387template <>
389 inline Color operator()(Color dst, Color src) const {
390 return BlendOp<BlendingMode::kSourceIn>()(src, dst);
391 }
392};
393
394template <>
396 inline Color operator()(Color dst, Color src) const {
397 return BlendOp<BlendingMode::kSourceAtop>()(src, dst);
398 }
399};
400
401template <>
403 // Fa = 1 – αb; Fb = 0
404 // co = αs x Cs x (1 – αb)
405 // αo = αs x (1 – αb)
406 inline Color operator()(Color dst, Color src) const {
407 uint8_t dst_alpha = dst.a();
408 if (dst_alpha == 0) {
409 return src;
410 }
411 uint8_t src_alpha = src.a();
412 if (src_alpha == 0xFF) {
413 return src.withA(dst_alpha ^ 0xFF);
414 }
415 if (src_alpha == 0) {
416 return color::Background;
417 }
418 return src.withA(
419 internal::__div_255_rounded(src_alpha * (dst_alpha ^ 0xFF)));
420 }
421};
422
423template <>
425 inline Color operator()(Color dst, Color src) const {
426 return BlendOp<BlendingMode::kSourceOut>()(src, dst);
427 }
428};
429
430template <>
432 // Fa = 1 - αb; Fb = 1 – αs
433 // co = αs x Cs x (1 - αb) + αb x Cb x (1 – αs)
434 // αo = αs x (1 - αb) + αb x (1 – αs)
435 inline Color operator()(Color dst, Color src) const {
436 uint16_t src_alpha = src.a();
437 uint16_t dst_alpha = dst.a();
438 if (src_alpha == 0xFF) {
439 return src.withA(255 - dst_alpha);
440 } else if (src_alpha == 0) {
441 return dst;
442 } else if (dst_alpha == 0xFF) {
443 return dst.withA(255 - src_alpha);
444 } else if (dst_alpha == 0) {
445 return src;
446 }
447 uint16_t alpha = internal::__div_255_rounded(src_alpha * (255 - dst_alpha) +
448 dst_alpha * (255 - src_alpha));
449 uint16_t cs = (src_alpha * (255 - dst_alpha) + alpha / 2) / alpha;
450 uint16_t cd = 255 - cs;
451
452 uint8_t r =
453 (uint8_t)(internal::__div_255_rounded(cs * src.r() + cd * dst.r()));
454 uint8_t g =
455 (uint8_t)(internal::__div_255_rounded(cs * src.g() + cd * dst.g()));
456 uint8_t b =
457 (uint8_t)(internal::__div_255_rounded(cs * src.b() + cd * dst.b()));
458 return Color(alpha << 24 | r << 16 | g << 8 | b);
459 }
460};
461
462// Utility function to calculates alpha-blending of the foreground color (fgc)
463// over the background color (bgc), ignoring background color's alpha, as if it
464// is fully opaque.
467}
468
469template <BlendingMode mode>
470struct Blender {
471 inline Color apply(Color dst, Color src) { return BlendOp<mode>()(dst, src); }
472
473 inline void applyInPlace(Color* dst, const Color* src, int16_t count) {
474 BlendOp<mode> op;
475 while (count-- > 0) {
476 *dst = op(*dst, *src);
477 ++dst;
478 ++src;
479 }
480 }
481
482 inline void applySingleSourceInPlace(Color* dst, Color src, int16_t count) {
483 BlendOp<mode> op;
484 while (count-- > 0) {
485 *dst = op(*dst, src);
486 ++dst;
487 }
488 }
489
490 inline void applyInPlaceIndexed(Color* dst, const Color* src, int16_t count,
491 const uint32_t* index) {
492 BlendOp<mode> op;
493 while (count-- > 0) {
494 dst[*index] = op(dst[*index], *src);
495 ++src;
496 ++index;
497 }
498 }
499
500 inline void applyOverBackground(Color bg, Color* src, int16_t count) {
501 BlendOp<mode> op;
502 while (count-- > 0) {
503 *src = op(bg, *src);
504 ++src;
505 }
506 }
507};
508
509namespace internal {
510
512 template <BlendingMode blending_mode>
513 __attribute__((always_inline)) Color operator()(Color dst, Color src) const {
514 return Blender<blending_mode>().apply(dst, src);
515 }
516};
517
519 template <BlendingMode blending_mode>
520 __attribute__((always_inline)) void operator()(Color* dst, const Color* src,
521 int16_t count) const {
522 return Blender<blending_mode>().applyInPlace(dst, src, count);
523 }
524};
525
527 template <BlendingMode blending_mode>
528 __attribute__((always_inline)) void operator()(Color* dst, Color src,
529 int16_t count) const {
530 return Blender<blending_mode>().applySingleSourceInPlace(dst, src, count);
531 }
532};
533
535 template <BlendingMode blending_mode>
536 __attribute__((always_inline)) void operator()(Color* dst, const Color* src,
538 const uint32_t* index) const {
539 return Blender<blending_mode>().applyInPlaceIndexed(dst, src, count, index);
540 }
541};
542
544 template <BlendingMode blending_mode>
545 __attribute__((always_inline)) void operator()(Color bg, Color* src,
546 int16_t count) const {
547 return Blender<blending_mode>().applyOverBackground(bg, src, count);
548 }
549};
550
551}; // namespace internal
552
553// Returns the result of blending `src` over `dst` using the specified mode.
555 return internal::BlenderSpecialization<internal::ApplyBlendingResolver>(
556 mode, dst, src);
557}
558
559// Blends the `src` array over the `dst` array using the specified mode, writing
560// back to `dst`.
562 const Color* src, int16_t count) {
564 internal::ApplyBlendingInPlaceResolver>(mode, dst, src, count);
565}
566
567// Blends a single `src` color over the `dst` array using the specified mode,
568// writing back to `dst`.
570 Color src, int16_t count) {
573 count);
574}
575
576// Blends the `src` array over the indexed `dst` array using the specified mode,
577// writing back to `dst`.
579 const Color* src, int16_t count,
580 const uint32_t* index) {
583 index);
584}
585
586// Blends the `src` array in place over the 'bg' color, using the specified
587// mode.
589 int16_t count) {
592}
593
594// Utility function to alpha-blend of the foreground color (fgc) over the
595// background color (bgc), in a general case, where bgc might be
596// semi-transparent. If the background is (or should be treated as) opaque, use
597// AlphaBlendOverOpaque() instead.
601
602template <typename ColorMode, BlendingMode blending_mode,
603 roo_io::ByteOrder byte_order>
605 void operator()(roo::byte* dst, Color src, const ColorMode& mode) const {
607 io.store(BlendOp<blending_mode>()(io.load(dst, mode), src), dst, mode);
608 }
609
610 void operator()(roo::byte* dst, Color src, ColorMode& mode) const {
612 io.store(BlendOp<blending_mode>()(io.load(dst, mode), src), dst, mode);
613 }
614};
615
616template <typename ColorMode, roo_io::ByteOrder byte_order>
617struct RawFullByteBlender<ColorMode, BlendingMode::kSource, byte_order> {
618 void operator()(roo::byte* dst, Color src, const ColorMode& mode) const {
620 io.store(src, dst, mode);
621 }
622
623 void operator()(roo::byte* dst, Color src, ColorMode& mode) const {
625 io.store(src, dst, mode);
626 }
627};
628
629template <typename ColorMode, roo_io::ByteOrder byte_order>
630struct RawFullByteBlender<ColorMode, BlendingMode::kDestination, byte_order> {
631 void operator()(roo::byte* dst, Color src, const ColorMode& mode) const {
632 // No-op, leave dst as is.
633 }
634};
635
636template <typename ColorMode, BlendingMode blending_mode>
639 const ColorMode& color_mode) const {
640 return color_mode.fromArgbColor(
641 BlendOp<blending_mode>()(color_mode.toArgbColor(dst), src));
642 }
643
644 uint8_t operator()(uint8_t dst, Color src, ColorMode& color_mode) const {
645 return color_mode.fromArgbColor(
646 BlendOp<blending_mode>()(color_mode.toArgbColor(dst), src));
647 }
648};
649
650template <typename ColorMode>
653 const ColorMode& color_mode) const {
654 return color_mode.fromArgbColor(src);
655 }
656
657 uint8_t operator()(uint8_t dst, Color src, ColorMode& color_mode) const {
658 return color_mode.fromArgbColor(src);
659 }
660};
661
662template <typename ColorMode>
665 const ColorMode& color_mode) const {
666 return dst;
667 }
668};
669
670namespace internal {
671template <typename ColorMode, roo_io::ByteOrder byte_order>
673 template <BlendingMode blending_mode>
674 void operator()(roo::byte* dst, Color src,
675 const ColorMode& color_mode) const {
677 color_mode);
678 }
679
680 template <BlendingMode blending_mode>
681 void operator()(roo::byte* dst, Color src, ColorMode& color_mode) const {
683 color_mode);
684 }
685};
686
687template <typename ColorMode>
689 template <BlendingMode blending_mode>
691 Color src,
692 const ColorMode& color_mode) const {
693 return RawSubByteBlender<ColorMode, blending_mode>()(dst, src, color_mode);
694 }
695
696 template <BlendingMode blending_mode>
698 Color src,
699 ColorMode& color_mode) const {
700 return RawSubByteBlender<ColorMode, blending_mode>()(dst, src, color_mode);
701 }
702};
703
704} // namespace internal
705
706// Returns the result of blending `src` over `dst` using the specified mode.
707template <typename ColorMode, roo_io::ByteOrder byte_order>
709 Color src, const ColorMode& color_mode) {
712 blending_mode, dst, src, color_mode);
713}
714
715// As above, for mutable color modes.
716template <typename ColorMode, roo_io::ByteOrder byte_order>
718 Color src, ColorMode& color_mode) {
721 blending_mode, dst, src, color_mode);
722}
723
724// As above, for sub-byte color modes.
725
726// Returns the result of blending `src` over `dst` using the specified mode.
727template <typename ColorMode>
735
736// As above, for mutable color modes.
737template <typename ColorMode>
744
745} // namespace roo_display
ARGB8888 color stored as a 32-bit unsigned integer.
Definition color.h:16
constexpr uint8_t a() const
Alpha channel.
Definition color.h:36
constexpr uint8_t b() const
Blue channel.
Definition color.h:42
constexpr uint8_t g() const
Green channel.
Definition color.h:40
constexpr uint8_t r() const
Red channel.
Definition color.h:38
constexpr Color withA(uint8_t a) const
Return a copy with the specified alpha channel.
Definition color.h:69
constexpr uint8_t __div_255_rounded(uint16_t arg)
Definition blending.h:127
constexpr uint8_t __div_65280(uint32_t arg)
Definition blending.h:131
constexpr uint8_t __div_65280_rounded(uint32_t arg)
Definition blending.h:135
auto BlenderSpecialization(const BlendingMode blending_mode, Args &&... args) -> decltype(std::declval< Functor >() .template operator()<BlendingMode::kSourceOver >(args...))
Definition blending.h:141
constexpr uint8_t __div_255(uint16_t arg)
Definition blending.h:125
Defines 140 opaque HTML named colors.
constexpr BlendingMode BLENDING_MODE_SOURCE_IN
Definition blending.h:76
ColorStorageType< ColorMode > ApplyRawSubByteBlending(BlendingMode blending_mode, uint8_t dst, Color src, const ColorMode &color_mode)
Definition blending.h:728
void ApplyBlendingOverBackground(BlendingMode mode, Color bg, Color *src, int16_t count)
Definition blending.h:588
constexpr BlendingMode BLENDING_MODE_DESTINATION
Definition blending.h:80
constexpr BlendingMode BLENDING_MODE_SOURCE_ATOP
Definition blending.h:78
BlendingMode
Porter-Duff style blending modes.
Definition blending.h:17
@ kDestinationOver
Destination is placed over the source.
@ kDestinationIn
Destination which overlaps the source, replaces the source.
@ kDestinationOut
Destination is placed, where it falls outside of the source.
@ kSourceOverOpaque
Similar to kSourceOver, but assumes that the destination is opaque.
@ kXor
The non-overlapping regions of source and destination are combined.
@ kDestination
Only the destination will be present.
@ kSource
The new ARGB8888 value completely replaces the old one.
@ kDestinationAtop
Destination which overlaps the source replaces the source. Source is placed elsewhere.
@ kSourceIn
The source that overlaps the destination, replaces the destination.
@ kSourceAtop
Source which overlaps the destination, replaces the destination. Destination is placed elsewhere.
@ kDestinationOverOpaque
Similar to kDestinationOver, but assumes that the source is opaque.
@ kClear
No regions are enabled.
@ kSourceOver
Source is placed (alpha-blended) over the destination. This is the default blending mode.
@ kSourceOut
Source is placed, where it falls outside of the destination.
void ApplyBlendingInPlace(BlendingMode mode, Color *dst, const Color *src, int16_t count)
Definition blending.h:561
constexpr BlendingMode BLENDING_MODE_DESTINATION_IN
Definition blending.h:85
constexpr BlendingMode BLENDING_MODE_SOURCE_OVER
Definition blending.h:74
Color AlphaBlend(Color bgc, Color fgc)
Definition blending.h:598
void ApplyRawFullByteBlending(BlendingMode blending_mode, roo::byte *dst, Color src, const ColorMode &color_mode)
Definition blending.h:708
constexpr BlendingMode BLENDING_MODE_DESTINATION_ATOP
Definition blending.h:88
TransparencyMode
Transparency information for a stream or color mode.
Definition blending.h:103
@ kNone
All colors are fully opaque.
@ kCrude
Colors are either fully opaque or fully transparent.
@ kFull
Colors may include partial transparency (alpha channel).
Color AlphaBlendOverOpaque(Color bgc, Color fgc)
Definition blending.h:465
roo_logging::Stream & operator<<(roo_logging::Stream &os, BlendingMode mode)
Definition blending.cpp:54
constexpr BlendingMode BLENDING_MODE_SOURCE
Definition blending.h:72
void ApplyBlendingSingleSourceInPlace(BlendingMode mode, Color *dst, Color src, int16_t count)
Definition blending.h:569
void ApplyBlendingInPlaceIndexed(BlendingMode mode, Color *dst, const Color *src, int16_t count, const uint32_t *index)
Definition blending.h:578
constexpr BlendingMode BLENDING_MODE_CLEAR
Definition blending.h:91
Color ApplyBlending(BlendingMode mode, Color dst, Color src)
Definition blending.h:554
constexpr BlendingMode BLENDING_MODE_DESTINATION_OUT
Definition blending.h:95
constexpr TransparencyMode TRANSPARENCY_NONE
Definition blending.h:113
constexpr TransparencyMode TRANSPARENCY_GRADUAL
Definition blending.h:117
constexpr BlendingMode BLENDING_MODE_DESTINATION_OVER
Definition blending.h:82
constexpr BlendingMode BLENDING_MODE_SOURCE_OUT
Definition blending.h:93
constexpr TransparencyMode TRANSPARENCY_BINARY
Definition blending.h:115
constexpr BlendingMode BLENDING_MODE_EXCLUSIVE_OR
Definition blending.h:98
float r
Definition smooth.cpp:474
BlendingMode blending_mode
Definition smooth.cpp:888
Color operator()(Color dst, Color src) const
Definition blending.h:359
Color operator()(Color dst, Color src) const
Definition blending.h:396
Color operator()(Color dst, Color src) const
Definition blending.h:389
Color operator()(Color dst, Color src) const
Definition blending.h:425
Color operator()(Color dst, Color src) const
Definition blending.h:352
Color operator()(Color dst, Color src) const
Definition blending.h:340
Color operator()(Color dst, Color src) const
Definition blending.h:316
Color operator()(Color dst, Color src) const
Definition blending.h:371
Color operator()(Color dst, Color src) const
Definition blending.h:406
Color operator()(Color dst, Color src) const
Definition blending.h:209
Color operator()(Color dst, Color src) const
Definition blending.h:246
Color operator()(Color dst, Color src) const
Definition blending.h:204
Color operator()(Color dst, Color src) const
Definition blending.h:435
void applyInPlace(Color *dst, const Color *src, int16_t count)
Definition blending.h:473
void applyOverBackground(Color bg, Color *src, int16_t count)
Definition blending.h:500
void applyInPlaceIndexed(Color *dst, const Color *src, int16_t count, const uint32_t *index)
Definition blending.h:490
void applySingleSourceInPlace(Color *dst, Color src, int16_t count)
Definition blending.h:482
Color apply(Color dst, Color src)
Definition blending.h:471
void operator()(roo::byte *dst, Color src, const ColorMode &mode) const
Definition blending.h:631
void operator()(roo::byte *dst, Color src, ColorMode &mode) const
Definition blending.h:623
void operator()(roo::byte *dst, Color src, const ColorMode &mode) const
Definition blending.h:618
void operator()(roo::byte *dst, Color src, ColorMode &mode) const
Definition blending.h:610
void operator()(roo::byte *dst, Color src, const ColorMode &mode) const
Definition blending.h:605
uint8_t operator()(uint8_t dst, Color src, const ColorMode &color_mode) const
Definition blending.h:664
uint8_t operator()(uint8_t dst, Color src, ColorMode &color_mode) const
Definition blending.h:657
uint8_t operator()(uint8_t dst, Color src, const ColorMode &color_mode) const
Definition blending.h:652
uint8_t operator()(uint8_t dst, Color src, const ColorMode &color_mode) const
Definition blending.h:638
uint8_t operator()(uint8_t dst, Color src, ColorMode &color_mode) const
Definition blending.h:644
__attribute__((always_inline)) void operator()(Color *dst
__attribute__((always_inline)) void operator()(Color *dst
__attribute__((always_inline)) void operator()(Color bg
__attribute__((always_inline)) Color operator()(Color dst
__attribute__((always_inline)) void operator()(Color *dst
void operator()(roo::byte *dst, Color src, const ColorMode &color_mode) const
Definition blending.h:674
void operator()(roo::byte *dst, Color src, ColorMode &color_mode) const
Definition blending.h:681
ColorStorageType< ColorMode > operator()(ColorStorageType< ColorMode > dst, Color src, const ColorMode &color_mode) const
Definition blending.h:690
ColorStorageType< ColorMode > operator()(ColorStorageType< ColorMode > dst, Color src, ColorMode &color_mode) const
Definition blending.h:697