1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
3 
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10 
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13 
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 
23 #ifndef VDRAWHELPER_H
24 #define VDRAWHELPER_H
25 
26 #include <memory>
27 #include <array>
28 #include "assert.h"
29 #include "vbitmap.h"
30 #include "vbrush.h"
31 #include "vrect.h"
32 #include "vrle.h"
33 
34 V_USE_NAMESPACE
35 
36 struct VSpanData;
37 struct Operator;
38 
39 struct RenderFunc
40 {
41     using Color = void (*)(uint32_t *dest, int length, uint32_t color, uint32_t alpha);
42     using Src   = void (*)(uint32_t *dest, int length, const uint32_t *src, uint32_t alpha);
43     enum class Type {
44         Invalid,
45         Color,
46         Src,
47     };
48     RenderFunc() = default;
RenderFuncRenderFunc49     RenderFunc(Type t, Color f):type_(t), color_(f){assert(t == Type::Color);}
RenderFuncRenderFunc50     RenderFunc(Type t, Src f):type_(t), src_(f){ assert(t == Type::Src);}
51 
52     Type   type_{Type::Invalid};
53     union {
54         Color color_;
55         Src   src_;
56     };
57 };
58 
59 class RenderFuncTable
60 {
61 public:
62     RenderFuncTable();
color(BlendMode mode)63     RenderFunc::Color color(BlendMode mode) const
64     {
65         return colorTable[uint32_t(mode)].color_;
66     }
src(BlendMode mode)67     RenderFunc::Src   src(BlendMode mode) const
68     {
69         return srcTable[uint32_t(mode)].src_;
70     }
71 private:
72     void neon();
73     void sse();
updateColor(BlendMode mode,RenderFunc::Color f)74     void updateColor(BlendMode mode, RenderFunc::Color f)
75     {
76         colorTable[uint32_t(mode)] = {RenderFunc::Type::Color, f};
77     }
updateSrc(BlendMode mode,RenderFunc::Src f)78     void updateSrc(BlendMode mode, RenderFunc::Src f)
79     {
80         srcTable[uint32_t(mode)] = {RenderFunc::Type::Src, f};
81     }
82 private:
83     std::array<RenderFunc, uint32_t(BlendMode::Last)> colorTable;
84     std::array<RenderFunc, uint32_t(BlendMode::Last)> srcTable;
85 };
86 
87 typedef void (*SourceFetchProc)(uint32_t *buffer, const Operator *o,
88                                 const VSpanData *data, int y, int x,
89                                 int length);
90 typedef void (*ProcessRleSpan)(size_t count, const VRle::Span *spans,
91                                void *userData);
92 
93 extern void memfill32(uint32_t *dest, uint32_t value, int count);
94 
95 struct LinearGradientValues {
96     float dx;
97     float dy;
98     float l;
99     float off;
100 };
101 
102 struct RadialGradientValues {
103     float dx;
104     float dy;
105     float dr;
106     float sqrfr;
107     float a;
108     float inv2a;
109     bool  extended;
110 };
111 
112 struct Operator {
113     BlendMode                mode;
114     SourceFetchProc          srcFetch;
115     RenderFunc::Color        funcSolid;
116     RenderFunc::Src          func;
117     union {
118         LinearGradientValues linear;
119         RadialGradientValues radial;
120     };
121 };
122 
123 class VRasterBuffer {
124 public:
125     VBitmap::Format prepare(const VBitmap *image);
126     void            clear();
127 
128     void resetBuffer(int val = 0);
129 
scanLine(int y)130     inline uchar *scanLine(int y)
131     {
132         assert(y >= 0);
133         assert(size_t(y) < mHeight);
134         return mBuffer + y * mBytesPerLine;
135     }
pixelRef(int x,int y)136     uint32_t *pixelRef(int x, int y) const
137     {
138         return (uint32_t *)(mBuffer + y * mBytesPerLine + x * mBytesPerPixel);
139     }
140 
width()141     size_t          width() const { return mWidth; }
height()142     size_t          height() const { return mHeight; }
bytesPerLine()143     size_t          bytesPerLine() const { return mBytesPerLine; }
bytesPerPixel()144     size_t          bytesPerPixel() const { return mBytesPerPixel; }
format()145     VBitmap::Format format() const { return mFormat; }
146 
147 private:
148     VBitmap::Format mFormat{VBitmap::Format::ARGB32_Premultiplied};
149     size_t          mWidth{0};
150     size_t          mHeight{0};
151     size_t          mBytesPerLine{0};
152     size_t          mBytesPerPixel{0};
153     mutable uchar * mBuffer{nullptr};
154 };
155 
156 struct VGradientData {
157     VGradient::Spread mSpread;
158     struct Linear {
159         float x1, y1, x2, y2;
160     };
161     struct Radial {
162         float cx, cy, fx, fy, cradius, fradius;
163     };
164     union {
165         Linear linear;
166         Radial radial;
167     };
168     const uint32_t *mColorTable;
169     bool            mColorTableAlpha;
170 };
171 
172 struct VTextureData : public VRasterBuffer {
pixelVTextureData173     uint32_t pixel(int x, int y) const { return *pixelRef(x, y); };
alphaVTextureData174     uchar    alpha() const { return mAlpha; }
setAlphaVTextureData175     void     setAlpha(uchar alpha) { mAlpha = alpha; }
176     void     setClip(const VRect &clip);
177     // clip rect
178     int   left;
179     int   right;
180     int   top;
181     int   bottom;
182     bool  hasAlpha;
183     uchar mAlpha;
184 };
185 
186 struct VColorTable {
187     uint32_t buffer32[VGradient::colorTableSize];
188     bool     alpha{true};
189 };
190 
191 struct VSpanData {
192     enum class Type { None, Solid, LinearGradient, RadialGradient, Texture };
193 
194     void updateSpanFunc();
195     void init(VRasterBuffer *image);
196     void setup(const VBrush &brush, BlendMode mode = BlendMode::SrcOver,
197                int alpha = 255);
198     void setupMatrix(const VMatrix &matrix);
199 
clipRectVSpanData200     VRect clipRect() const
201     {
202         return VRect(0, 0, mDrawableSize.width(), mDrawableSize.height());
203     }
204 
setDrawRegionVSpanData205     void setDrawRegion(const VRect &region)
206     {
207         mOffset = VPoint(region.left(), region.top());
208         mDrawableSize = VSize(region.width(), region.height());
209     }
210 
bufferVSpanData211     uint *buffer(int x, int y) const
212     {
213         return mRasterBuffer->pixelRef(x + mOffset.x(), y + mOffset.y());
214     }
215     void initTexture(const VBitmap *image, int alpha, const VRect &sourceRect);
textureVSpanData216     const VTextureData &texture() const { return mTexture; }
217 
218     BlendMode                          mBlendMode{BlendMode::SrcOver};
219     VRasterBuffer *                    mRasterBuffer;
220     ProcessRleSpan                     mBlendFunc;
221     ProcessRleSpan                     mUnclippedBlendFunc;
222     VSpanData::Type                    mType;
223     std::shared_ptr<const VColorTable> mColorTable{nullptr};
224     VPoint                             mOffset;  // offset to the subsurface
225     VSize                              mDrawableSize;  // suburface size
226     uint32_t                           mSolid;
227     VGradientData                      mGradient;
228     VTextureData                       mTexture;
229 
230     float m11, m12, m13, m21, m22, m23, m33, dx, dy;  // inverse xform matrix
231     bool  fast_matrix{true};
232     VMatrix::MatrixType transformType{VMatrix::MatrixType::None};
233 };
234 
235 #define BYTE_MUL(c, a)                                  \
236     ((((((c) >> 8) & 0x00ff00ff) * (a)) & 0xff00ff00) + \
237      (((((c)&0x00ff00ff) * (a)) >> 8) & 0x00ff00ff))
238 
vRed(uint32_t c)239 inline constexpr int vRed(uint32_t c)
240 {
241     return ((c >> 16) & 0xff);
242 }
243 
vGreen(uint32_t c)244 inline constexpr int vGreen(uint32_t c)
245 {
246     return ((c >> 8) & 0xff);
247 }
248 
vBlue(uint32_t c)249 inline constexpr int vBlue(uint32_t c)
250 {
251     return (c & 0xff);
252 }
253 
vAlpha(uint32_t c)254 inline constexpr int vAlpha(uint32_t c)
255 {
256     return c >> 24;
257 }
258 
interpolate_pixel(uint x,uint a,uint y,uint b)259 static inline uint32_t interpolate_pixel(uint x, uint a, uint y, uint b)
260 {
261     uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
262     t >>= 8;
263     t &= 0xff00ff;
264     x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
265     x &= 0xff00ff00;
266     x |= t;
267     return x;
268 }
269 
270 #endif  // QDRAWHELPER_P_H
271