1 | // LAF OS Library |
2 | // Copyright (C) 2012-2017 David Capello |
3 | // |
4 | // This file is released under the terms of the MIT license. |
5 | // Read LICENSE.txt for more information. |
6 | |
7 | #ifndef OS_COMMON_GENERIC_SURFACE_H |
8 | #define OS_COMMON_GENERIC_SURFACE_H |
9 | #pragma once |
10 | |
11 | #include "base/debug.h" |
12 | #include "gfx/clip.h" |
13 | #include "gfx/color.h" |
14 | #include "os/surface.h" |
15 | |
16 | namespace os { |
17 | |
18 | namespace { |
19 | |
20 | #define MUL_UN8(a, b, t) \ |
21 | ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8)) |
22 | |
23 | inline gfx::Color blend(const gfx::Color backdrop, gfx::Color src) |
24 | { |
25 | if (gfx::geta(backdrop) == 0) |
26 | return src; |
27 | else if (gfx::geta(src) == 0) |
28 | return backdrop; |
29 | |
30 | int Br, Bg, Bb, Ba; |
31 | int Sr, Sg, Sb, Sa; |
32 | int Rr, Rg, Rb, Ra; |
33 | |
34 | Br = gfx::getr(backdrop); |
35 | Bg = gfx::getg(backdrop); |
36 | Bb = gfx::getb(backdrop); |
37 | Ba = gfx::geta(backdrop); |
38 | |
39 | Sr = gfx::getr(src); |
40 | Sg = gfx::getg(src); |
41 | Sb = gfx::getb(src); |
42 | Sa = gfx::geta(src); |
43 | |
44 | int t; |
45 | Ra = Ba + Sa - MUL_UN8(Ba, Sa, t); |
46 | Rr = Br + (Sr-Br) * Sa / Ra; |
47 | Rg = Bg + (Sg-Bg) * Sa / Ra; |
48 | Rb = Bb + (Sb-Bb) * Sa / Ra; |
49 | |
50 | return gfx::rgba(Rr, Rg, Rb, Ra); |
51 | } |
52 | |
53 | } // anoynmous namespace |
54 | |
55 | template<typename Base> |
56 | class GenericDrawColoredRgbaSurface : public Base { |
57 | public: |
58 | |
59 | void drawColoredRgbaSurface(const Surface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clipbase) override { |
60 | gfx::Clip clip(clipbase); |
61 | if (!clip.clip(this->width(), |
62 | this->height(), |
63 | src->width(), src->height())) |
64 | return; |
65 | |
66 | SurfaceFormatData format; |
67 | src->getFormat(&format); |
68 | |
69 | ASSERT(format.format == kRgbaSurfaceFormat); |
70 | ASSERT(format.bitsPerPixel == 32); |
71 | |
72 | for (int v=0; v<clip.size.h; ++v) { |
73 | const uint32_t* ptr = (const uint32_t*)src->getData( |
74 | clip.src.x, clip.src.y+v); |
75 | |
76 | for (int u=0; u<clip.size.w; ++u) { |
77 | gfx::Color dstColor = this->getPixel(clip.dst.x+u, clip.dst.y+v); |
78 | if (gfx::geta(bg) > 0) |
79 | dstColor = blend(dstColor, bg); |
80 | |
81 | uint32_t src = (((*ptr) & format.alphaMask) >> format.alphaShift); |
82 | if (src > 0) { |
83 | src = gfx::rgba(gfx::getr(fg), |
84 | gfx::getg(fg), |
85 | gfx::getb(fg), src); |
86 | dstColor = blend(dstColor, src); |
87 | } |
88 | |
89 | this->putPixel(dstColor, clip.dst.x+u, clip.dst.y+v); |
90 | ++ptr; |
91 | } |
92 | } |
93 | } |
94 | }; |
95 | |
96 | } // namespace os |
97 | |
98 | #endif |
99 | |