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
16namespace os {
17
18namespace {
19
20#define MUL_UN8(a, b, t) \
21 ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
22
23inline 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
55template<typename Base>
56class GenericDrawColoredRgbaSurface : public Base {
57public:
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