1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 
19 #ifndef VDRAWHELPER_H
20 #define VDRAWHELPER_H
21 
22 #include <cstring>
23 #include <memory>
24 #include "assert.h"
25 #include "vbitmap.h"
26 #include "vbrush.h"
27 #include "vpainter.h"
28 #include "vrect.h"
29 #include "vrle.h"
30 
31 V_USE_NAMESPACE
32 
33 struct VSpanData;
34 struct Operator;
35 
36 typedef void (*CompositionFunctionSolid)(uint32_t *dest, int length,
37                                          uint32_t color, uint32_t const_alpha);
38 typedef void (*CompositionFunction)(uint32_t *dest, const uint32_t *src,
39                                     int length, uint32_t const_alpha);
40 typedef void (*SourceFetchProc)(uint32_t *buffer, const Operator *o,
41                                 const VSpanData *data, int y, int x,
42                                 int length);
43 typedef void (*ProcessRleSpan)(size_t count, const VRle::Span *spans,
44                                void *userData);
45 
46 extern void memfill32(uint32_t *dest, uint32_t value, int count);
47 
48 struct LinearGradientValues {
49     float dx;
50     float dy;
51     float l;
52     float off;
53 };
54 
55 struct RadialGradientValues {
56     float dx;
57     float dy;
58     float dr;
59     float sqrfr;
60     float a;
61     float inv2a;
62     bool  extended;
63 };
64 
65 struct Operator {
66     VPainter::CompositionMode mode;
67     SourceFetchProc           srcFetch;
68     CompositionFunctionSolid  funcSolid;
69     CompositionFunction       func;
70     union {
71         LinearGradientValues linear;
72         RadialGradientValues radial;
73     };
74 };
75 
76 class VRasterBuffer {
77 public:
78     VBitmap::Format prepare(VBitmap *image);
79     void            clear();
80 
81     void resetBuffer(int val = 0);
82 
scanLine(int y)83     inline uchar *scanLine(int y)
84     {
85         assert(y >= 0);
86         assert(size_t(y) < mHeight);
87         return mBuffer + y * mBytesPerLine;
88     }
89 
width()90     size_t width() const { return mWidth; }
height()91     size_t height() const { return mHeight; }
bytesPerLine()92     size_t bytesPerLine() const { return mBytesPerLine; }
bytesPerPixel()93     size_t bytesPerPixel() const { return mBytesPerPixel; }
94 
95     VBitmap::Format           mFormat{VBitmap::Format::ARGB32_Premultiplied};
96 private:
97     size_t    mWidth{0};
98     size_t    mHeight{0};
99     size_t    mBytesPerLine{0};
100     size_t    mBytesPerPixel{0};
101     uchar    *mBuffer{nullptr};
102 };
103 
104 struct VGradientData {
105     VGradient::Spread mSpread;
106     struct Linear{
107         float x1, y1, x2, y2;
108     };
109     struct Radial{
110         float cx, cy, fx, fy, cradius, fradius;
111     };
112     union {
113         Linear linear;
114         Radial radial;
115     };
116     const uint32_t *mColorTable;
117     bool            mColorTableAlpha;
118 };
119 
120 struct VBitmapData
121 {
122     const uchar *imageData;
scanLineVBitmapData123     const uchar *scanLine(int y) const { return imageData + y*bytesPerLine; }
124 
125     int width;
126     int height;
127     // clip rect
128     int x1;
129     int y1;
130     int x2;
131     int y2;
132     uint bytesPerLine;
133     VBitmap::Format format;
134     bool hasAlpha;
135     enum Type {
136         Plain,
137         Tiled
138     };
139     Type type;
140     int const_alpha;
141 };
142 
143 struct VColorTable
144 {
145     uint32_t buffer32[VGradient::colorTableSize];
146     bool     alpha{true};
147 };
148 
149 struct VSpanData {
150     enum class Type { None, Solid, LinearGradient, RadialGradient, Texture };
151 
152     void  updateSpanFunc();
153     void  init(VRasterBuffer *image);
154     void  setup(const VBrush &            brush,
155                 VPainter::CompositionMode mode = VPainter::CompModeSrcOver,
156                 int                       alpha = 255);
157     void  setupMatrix(const VMatrix &matrix);
158 
clipRectVSpanData159     VRect clipRect() const
160     {
161         return VRect(0, 0, mDrawableSize.width(), mDrawableSize.height());
162     }
163 
setDrawRegionVSpanData164     void setDrawRegion(const VRect &region)
165     {
166         mOffset = VPoint(region.left(), region.top());
167         mDrawableSize = VSize(region.width(), region.height());
168     }
169 
bufferVSpanData170     uint *buffer(int x, int y) const
171     {
172         return (uint *)(mRasterBuffer->scanLine(y + mOffset.y())) + x + mOffset.x();
173     }
174     void initTexture(const VBitmap *image, int alpha, VBitmapData::Type type, const VRect &sourceRect);
175 
176     VPainter::CompositionMode            mCompositionMode{VPainter::CompositionMode::CompModeSrcOver};
177     VRasterBuffer *                      mRasterBuffer;
178     ProcessRleSpan                       mBlendFunc;
179     ProcessRleSpan                       mUnclippedBlendFunc;
180     VSpanData::Type                      mType;
181     std::shared_ptr<const VColorTable>   mColorTable{nullptr};
182     VPoint                               mOffset; // offset to the subsurface
183     VSize                                mDrawableSize;// suburface size
184     union {
185         uint32_t      mSolid;
186         VGradientData mGradient;
187         VBitmapData   mBitmap;
188     };
189     float m11, m12, m13, m21, m22, m23, m33, dx, dy;  // inverse xform matrix
190     bool fast_matrix{true};
191     VMatrix::MatrixType   transformType{VMatrix::MatrixType::None};
192 };
193 
194 void        vInitDrawhelperFunctions();
195 extern void vInitBlendFunctions();
196 
197 #define BYTE_MUL(c, a)                                  \
198     ((((((c) >> 8) & 0x00ff00ff) * (a)) & 0xff00ff00) + \
199      (((((c)&0x00ff00ff) * (a)) >> 8) & 0x00ff00ff))
200 
vRed(uint32_t c)201 inline constexpr int vRed(uint32_t c)
202 {
203     return ((c >> 16) & 0xff);
204 }
205 
vGreen(uint32_t c)206 inline constexpr int vGreen(uint32_t c)
207 {
208     return ((c >> 8) & 0xff);
209 }
210 
vBlue(uint32_t c)211 inline constexpr int vBlue(uint32_t c)
212 {
213     return (c & 0xff);
214 }
215 
vAlpha(uint32_t c)216 inline constexpr int vAlpha(uint32_t c)
217 {
218     return c >> 24;
219 }
220 
INTERPOLATE_PIXEL_255(uint x,uint a,uint y,uint b)221 static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b)
222 {
223     uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
224     t >>= 8;
225     t &= 0xff00ff;
226     x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
227     x &= 0xff00ff00;
228     x |= t;
229     return x;
230 }
231 
232 #define LOOP_ALIGNED_U1_A4(DEST, LENGTH, UOP, A4OP) \
233     {                                               \
234         while ((uintptr_t)DEST & 0xF && LENGTH)     \
235             UOP                                     \
236                                                     \
237                 while (LENGTH)                      \
238             {                                       \
239                 switch (LENGTH) {                   \
240                 case 3:                             \
241                 case 2:                             \
242                 case 1:                             \
243                     UOP break;                      \
244                 default:                            \
245                     A4OP break;                     \
246                 }                                   \
247             }                                       \
248     }
249 
250 #endif  // QDRAWHELPER_P_H
251