1 /**
2  * painter utils
3  *
4  * Copyright 2015-2016 Jay Sorg <jay.sorg@gmail.com>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #if defined(HAVE_CONFIG_H)
20 #include <config_ac.h>
21 #endif
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "painter.h"
28 #include "painter_utils.h"
29 
30 /*****************************************************************************/
31 /* do a raster op */
32 int
do_rop(int rop,int src,int dst)33 do_rop(int rop, int src, int dst)
34 {
35     switch (rop)
36     {
37         case PT_ROP_0:    return 0;
38         case PT_ROP_DSon: return ~(src | dst);
39         case PT_ROP_DSna: return (~src) & dst;
40         case PT_ROP_Sn:   return ~src;
41         case PT_ROP_SDna: return src & (~dst);
42         case PT_ROP_Dn:   return ~(dst);
43         case PT_ROP_DSx:  return src ^ dst;
44         case PT_ROP_DSan: return ~(src & dst);
45         case PT_ROP_DSa:  return src & dst;
46         case PT_ROP_DSxn: return ~(src) ^ dst;
47         case PT_ROP_D:    return dst;
48         case PT_ROP_DSno: return (~src) | dst;
49         case PT_ROP_S:    return src;
50         case PT_ROP_SDno: return src | (~dst);
51         case PT_ROP_DSo:  return src | dst;
52         case PT_ROP_1:    return ~0;
53     }
54     return dst;
55 }
56 
57 /*****************************************************************************/
58 char *
bitmap_get_ptr(struct painter_bitmap * bitmap,int x,int y)59 bitmap_get_ptr(struct painter_bitmap *bitmap, int x, int y)
60 {
61     char *p;
62     int bpp;
63     int Bpp;
64 
65     if ((x >= 0) && (x < bitmap->width) &&
66         (y >= 0) && (y < bitmap->height))
67     {
68         bpp = bitmap->format >> 24;
69         if (bpp < 8)
70         {
71             p = bitmap->data + (y * bitmap->stride_bytes) + (x / 8);
72             return p;
73         }
74         else
75         {
76             Bpp = (bpp + 7) / 8;
77             p = bitmap->data + (y * bitmap->stride_bytes) + (x * Bpp);
78             return p;
79         }
80     }
81     else
82     {
83         return NULL;
84     }
85 }
86 
87 /*****************************************************************************/
88 int
bitmap_get_pixel(struct painter_bitmap * bitmap,int x,int y)89 bitmap_get_pixel(struct painter_bitmap *bitmap, int x, int y)
90 {
91     char *ptr;
92     int rv;
93 
94     ptr = bitmap_get_ptr(bitmap, x, y);
95     if (ptr == NULL)
96     {
97         return 0;
98     }
99     switch (bitmap->format)
100     {
101         case PT_FORMAT_c1:
102             rv = *((unsigned char *) ptr);
103             rv = (rv & (0x80 >> (x % 8))) != 0;
104             return rv;
105         case PT_FORMAT_c8:
106             return *((unsigned char *) ptr);
107         case PT_FORMAT_r3g3b2:
108             return *((unsigned char *) ptr);
109         case PT_FORMAT_a1r5g5b5:
110             return *((unsigned short *) ptr);
111         case PT_FORMAT_r5g6b5:
112             return *((unsigned short *) ptr);
113         case PT_FORMAT_a8r8g8b8:
114             return *((unsigned int *) ptr);
115         case PT_FORMAT_a8b8g8r8:
116             return *((unsigned int *) ptr);
117     }
118     return 0;
119 }
120 
121 /*****************************************************************************/
122 int
bitmap_set_pixel(struct painter_bitmap * bitmap,int x,int y,int pixel)123 bitmap_set_pixel(struct painter_bitmap *bitmap, int x, int y, int pixel)
124 {
125     char *ptr;
126 
127     ptr = bitmap_get_ptr(bitmap, x, y);
128     if (ptr == NULL)
129     {
130         return 0;
131     }
132     switch (bitmap->format)
133     {
134         case PT_FORMAT_r3g3b2:
135             *((unsigned char *) ptr) = pixel;
136             break;
137         case PT_FORMAT_a1r5g5b5:
138             *((unsigned short *) ptr) = pixel;
139             break;
140         case PT_FORMAT_r5g6b5:
141             *((unsigned short *) ptr) = pixel;
142             break;
143         case PT_FORMAT_a8r8g8b8:
144             *((unsigned int *) ptr) = pixel;
145             break;
146         case PT_FORMAT_a8b8g8r8:
147             *((unsigned int *) ptr) = pixel;
148             break;
149     }
150     return 0;
151 }
152 
153 /*****************************************************************************/
154 int
pixel_convert(int pixel,int src_format,int dst_format,int * palette)155 pixel_convert(int pixel, int src_format, int dst_format, int *palette)
156 {
157     int a;
158     int r;
159     int g;
160     int b;
161     int rv;
162 
163     if (src_format == dst_format)
164     {
165         return pixel;
166     }
167     a = 0;
168     r = 0;
169     g = 0;
170     b = 0;
171     switch (src_format)
172     {
173         case PT_FORMAT_r3g3b2:
174             SPLIT_r3g3b2(pixel, a, r, g, b);
175             break;
176         case PT_FORMAT_a1r5g5b5:
177             SPLIT_a1r5g5b5(pixel, a, r, g, b);
178             break;
179         case PT_FORMAT_r5g6b5:
180             SPLIT_r5g6b5(pixel, a, r, g, b);
181             break;
182         case PT_FORMAT_a8r8g8b8:
183             SPLIT_a8r8g8b8(pixel, a, r, g, b);
184             break;
185         case PT_FORMAT_a8b8g8r8:
186             SPLIT_a8b8g8r8(pixel, a, r, g, b);
187             break;
188     }
189     rv = 0;
190     switch (dst_format)
191     {
192         case PT_FORMAT_a1r5g5b5:
193             MAKE_a1r5g5b5(rv, a, r, g, b);
194             break;
195         case PT_FORMAT_r5g6b5:
196             MAKE_r5g6b5(rv, a, r, g, b);
197             break;
198         case PT_FORMAT_a8r8g8b8:
199             MAKE_a8r8g8b8(rv, a, r, g, b);
200             break;
201         case PT_FORMAT_a8b8g8r8:
202             MAKE_a8b8g8r8(rv, a, r, g, b);
203             break;
204     }
205     return rv;
206 }
207 
208 /*****************************************************************************/
209 int
painter_get_pixel(struct painter * painter,struct painter_bitmap * bitmap,int x,int y)210 painter_get_pixel(struct painter *painter, struct painter_bitmap *bitmap,
211                   int x, int y)
212 {
213     int rv;
214 
215     rv = 0;
216     if ((x >= 0) && (x < bitmap->width) && (y >= 0) && (y < bitmap->height))
217     {
218         switch (bitmap->format)
219         {
220             case PT_FORMAT_c1:
221                 rv = bitmap_get_pixel(bitmap, x, y);
222                 rv = rv ? painter->fgcolor : painter->bgcolor;
223                 break;
224             case PT_FORMAT_c8:
225                 rv = bitmap_get_pixel(bitmap, x, y);
226                 rv = painter->palette[rv & 0xff];
227                 break;
228             default:
229                 rv = bitmap_get_pixel(bitmap, x, y);
230                 break;
231         }
232     }
233     return rv;
234 }
235 
236 /*****************************************************************************/
237 int
painter_set_pixel(struct painter * painter,struct painter_bitmap * bitmap,int x,int y,int pixel,int pixel_format)238 painter_set_pixel(struct painter *painter, struct painter_bitmap *bitmap,
239                   int x, int y, int pixel, int pixel_format)
240 {
241     if ((painter->clip_valid == 0) ||
242         ((x >= painter->clip.x1) && (x < painter->clip.x2) &&
243          (y >= painter->clip.y1) && (y < painter->clip.y2)))
244     {
245         if ((x >= 0) && (x < bitmap->width) &&
246             (y >= 0) && (y < bitmap->height))
247         {
248             pixel = pixel_convert(pixel, pixel_format, bitmap->format,
249                                   painter->palette);
250             if (painter->rop != PT_ROP_S)
251             {
252                 pixel = do_rop(painter->rop, pixel,
253                                bitmap_get_pixel(bitmap, x, y));
254             }
255             bitmap_set_pixel(bitmap, x, y, pixel);
256         }
257     }
258     return 0;
259 }
260 
261 /*****************************************************************************/
262 /* return true if there is something to draw */
263 int
painter_warp_coords(struct painter * painter,int * x,int * y,int * cx,int * cy,int * srcx,int * srcy)264 painter_warp_coords(struct painter *painter,
265                     int *x, int *y, int *cx, int *cy,
266                     int *srcx, int *srcy)
267 {
268     int dx;
269     int dy;
270     int lx;
271     int ly;
272     int lcx;
273     int lcy;
274 
275     lx = *x;
276     ly = *y;
277     lcx = *cx;
278     lcy = *cy;
279     dx = 0;
280     dy = 0;
281     if (painter->clip_valid)
282     {
283         if (painter->clip.x1 > lx)
284         {
285             dx = painter->clip.x1 - lx;
286         }
287         if (painter->clip.y1 > ly)
288         {
289             dy = painter->clip.y1 - ly;
290         }
291         if (lx + lcx > painter->clip.x2)
292         {
293             lcx = (lcx - ((lx + lcx) - painter->clip.x2));
294         }
295         if (*y + lcy > painter->clip.y2)
296         {
297             lcy = (lcy - ((ly + lcy) - painter->clip.y2));
298         }
299     }
300     lcx = lcx - dx;
301     lcy = lcy - dy;
302     if (lcx <= 0)
303     {
304         return 0;
305     }
306     if (lcy <= 0)
307     {
308         return 0;
309     }
310     lx = lx + dx;
311     ly = ly + dy;
312     if (srcx != 0)
313     {
314         *srcx = *srcx + dx;
315     }
316     if (srcy != 0)
317     {
318         *srcy = *srcy + dy;
319     }
320     *x = lx;
321     *y = ly;
322     *cx = lcx;
323     *cy = lcy;
324     return 1;
325 }
326 
327