1 /********************************************************************/
2 /*                                                                  */
3 /*  drw_rtl.c     Platform idependent drawing functions.            */
4 /*  Copyright (C) 1989 - 2013, 2015 - 2018  Thomas Mertes           */
5 /*                                                                  */
6 /*  This file is part of the Seed7 Runtime Library.                 */
7 /*                                                                  */
8 /*  The Seed7 Runtime Library is free software; you can             */
9 /*  redistribute it and/or modify it under the terms of the GNU     */
10 /*  Lesser General Public License as published by the Free Software */
11 /*  Foundation; either version 2.1 of the License, or (at your      */
12 /*  option) any later version.                                      */
13 /*                                                                  */
14 /*  The Seed7 Runtime Library is distributed in the hope that it    */
15 /*  will be useful, but WITHOUT ANY WARRANTY; without even the      */
16 /*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /*  PURPOSE.  See the GNU Lesser General Public License for more    */
18 /*  details.                                                        */
19 /*                                                                  */
20 /*  You should have received a copy of the GNU Lesser General       */
21 /*  Public License along with this program; if not, write to the    */
22 /*  Free Software Foundation, Inc., 51 Franklin Street,             */
23 /*  Fifth Floor, Boston, MA  02110-1301, USA.                       */
24 /*                                                                  */
25 /*  Module: Seed7 Runtime Library                                   */
26 /*  File: seed7/src/drw_rtl.c                                       */
27 /*  Changes: 2007, 2013, 2015 - 2018  Thomas Mertes                 */
28 /*  Content: Platform idependent drawing functions.                 */
29 /*                                                                  */
30 /********************************************************************/
31 
32 #define LOG_FUNCTIONS 0
33 #define VERBOSE_EXCEPTIONS 0
34 
35 #include "version.h"
36 
37 #include "stdlib.h"
38 #include "stdio.h"
39 #include "string.h"
40 
41 #include "common.h"
42 #include "data_rtl.h"
43 #include "rtl_err.h"
44 #include "drw_drv.h"
45 
46 #undef EXTERN
47 #define EXTERN
48 #include "drw_rtl.h"
49 
50 
51 #define USE_DUFFS_UNROLLING 1
52 
53 
54 
55 #if USE_DUFFS_UNROLLING
memcpy_pixel(register int32Type * const dest,register const intType * const src,memSizeType len)56 static void memcpy_pixel (register int32Type *const dest,
57     register const intType *const src, memSizeType len)
58 
59   {
60     register memSizeType pos;
61 
62   /* memcpy_pixel */
63     if (len != 0) {
64       pos = (len + 31) & ~(memSizeType) 31;
65       switch (len & 31) {
66         do {
67           case  0: dest[pos -  1] = (int32Type) src[pos -  1];
68           case 31: dest[pos -  2] = (int32Type) src[pos -  2];
69           case 30: dest[pos -  3] = (int32Type) src[pos -  3];
70           case 29: dest[pos -  4] = (int32Type) src[pos -  4];
71           case 28: dest[pos -  5] = (int32Type) src[pos -  5];
72           case 27: dest[pos -  6] = (int32Type) src[pos -  6];
73           case 26: dest[pos -  7] = (int32Type) src[pos -  7];
74           case 25: dest[pos -  8] = (int32Type) src[pos -  8];
75           case 24: dest[pos -  9] = (int32Type) src[pos -  9];
76           case 23: dest[pos - 10] = (int32Type) src[pos - 10];
77           case 22: dest[pos - 11] = (int32Type) src[pos - 11];
78           case 21: dest[pos - 12] = (int32Type) src[pos - 12];
79           case 20: dest[pos - 13] = (int32Type) src[pos - 13];
80           case 19: dest[pos - 14] = (int32Type) src[pos - 14];
81           case 18: dest[pos - 15] = (int32Type) src[pos - 15];
82           case 17: dest[pos - 16] = (int32Type) src[pos - 16];
83           case 16: dest[pos - 17] = (int32Type) src[pos - 17];
84           case 15: dest[pos - 18] = (int32Type) src[pos - 18];
85           case 14: dest[pos - 19] = (int32Type) src[pos - 19];
86           case 13: dest[pos - 20] = (int32Type) src[pos - 20];
87           case 12: dest[pos - 21] = (int32Type) src[pos - 21];
88           case 11: dest[pos - 22] = (int32Type) src[pos - 22];
89           case 10: dest[pos - 23] = (int32Type) src[pos - 23];
90           case  9: dest[pos - 24] = (int32Type) src[pos - 24];
91           case  8: dest[pos - 25] = (int32Type) src[pos - 25];
92           case  7: dest[pos - 26] = (int32Type) src[pos - 26];
93           case  6: dest[pos - 27] = (int32Type) src[pos - 27];
94           case  5: dest[pos - 28] = (int32Type) src[pos - 28];
95           case  4: dest[pos - 29] = (int32Type) src[pos - 29];
96           case  3: dest[pos - 30] = (int32Type) src[pos - 30];
97           case  2: dest[pos - 31] = (int32Type) src[pos - 31];
98           case  1: dest[pos - 32] = (int32Type) src[pos - 32];
99         } while ((pos -= 32) != 0);
100       } /* switch */
101     } /* if */
102   } /* memcpy_pixel */
103 
104 #else
105 
106 
107 
memcpy_pixel(register int32Type * dest,register const intType * src,memSizeType len)108 static void memcpy_pixel (register int32Type *dest,
109     register const intType *src, memSizeType len)
110 
111   { /* memcpy_pixel */
112     for (; len > 0; len--, src++, dest++) {
113       *dest = (int32Type) *src;
114     } /* for */
115   } /* memcpy_pixel */
116 #endif
117 
118 
119 
120 /**
121  *  Assign source to *dest.
122  *  A copy function assumes that *dest contains a legal value.
123  */
drwCpy(winType * const dest,const winType source)124 void drwCpy (winType *const dest, const winType source)
125 
126   { /* drwCpy */
127     logFunction(printf("drwCpy(" FMT_U_MEM " (usage=" FMT_U "), "
128                        FMT_U_MEM " (usage=" FMT_U "))\n",
129                        (memSizeType) *dest,
130                        *dest != NULL ? (*dest)->usage_count : (uintType) 0,
131                        (memSizeType) source,
132                        source != NULL ? source->usage_count : (uintType) 0););
133     if (source != NULL && source->usage_count != 0) {
134       source->usage_count++;
135     } /* if */
136     if (*dest != NULL && (*dest)->usage_count != 0) {
137       (*dest)->usage_count--;
138       if ((*dest)->usage_count == 0) {
139         drwFree(*dest);
140       } /* if */
141     } /* if */
142     *dest = source;
143     logFunction(printf("drwCpy(" FMT_U_MEM " (usage=" FMT_U "), "
144                        FMT_U_MEM " (usage=" FMT_U ")) -->\n",
145                        (memSizeType) *dest,
146                        *dest != NULL ? (*dest)->usage_count : (uintType) 0,
147                        (memSizeType) source,
148                        source != NULL ? source->usage_count : (uintType) 0););
149   } /* drwCpy */
150 
151 
152 
153 /**
154  *  Reinterpret the generic parameters as winType and call drwCpy.
155  *  Function pointers in C programs generated by the Seed7 compiler
156  *  may point to this function. This assures correct behaviour even
157  *  if sizeof(genericType) != sizeof(winType).
158  */
drwCpyGeneric(genericType * const dest,const genericType source)159 void drwCpyGeneric (genericType *const dest, const genericType source)
160 
161   { /* drwCpyGeneric */
162     drwCpy(&((rtlObjectType *) dest)->value.winValue,
163            ((const_rtlObjectType *) &source)->value.winValue);
164   } /* drwCpyGeneric */
165 
166 
167 
168 /**
169  *  Return a copy of source, that can be assigned to a new destination.
170  *  It is assumed that the destination of the assignment is undefined.
171  *  Create functions can be used to initialize Seed7 constants.
172  *  @return a copy of source.
173  */
drwCreate(const winType source)174 winType drwCreate (const winType source)
175 
176   { /* drwCreate */
177     logFunction(printf("drwCreate(" FMT_U_MEM ") (usage=" FMT_U ")\n",
178                        (memSizeType) source,
179                        source != NULL ? source->usage_count : (uintType) 0););
180     if (source != NULL && source->usage_count != 0) {
181       source->usage_count++;
182     } /* if */
183     logFunction(printf("drwCreate --> " FMT_U_MEM " (usage=" FMT_U ")\n",
184                        (memSizeType) source,
185                        source != NULL ? source->usage_count : (uintType) 0););
186     return source;
187   } /* drwCreate */
188 
189 
190 
191 /**
192  *  Generic Create function to be used via function pointers.
193  *  Function pointers in C programs generated by the Seed7 compiler
194  *  may point to this function. This assures correct behaviour even
195  *  if sizeof(genericType) != sizeof(winType).
196  */
drwCreateGeneric(const genericType from_value)197 genericType drwCreateGeneric (const genericType from_value)
198 
199   {
200     rtlObjectType result;
201 
202   /* drwCreateGeneric */
203     INIT_GENERIC_PTR(result.value.genericValue);
204     result.value.winValue =
205         drwCreate(((const_rtlObjectType *) &from_value)->value.winValue);
206     return result.value.genericValue;
207   } /* drwCreateGeneric */
208 
209 
210 
211 /**
212  *  Maintain a usage count and free an unused window 'old_win'.
213  *  After a window is freed 'old_win' refers to not existing memory.
214  *  The memory where 'old_win' is stored can be freed after drwDestr.
215  */
drwDestr(const winType old_win)216 void drwDestr (const winType old_win)
217 
218   { /* drwDestr */
219     logFunction(printf("drwDestr(" FMT_U_MEM ") (usage=" FMT_U ")\n",
220                        (memSizeType) old_win,
221                        old_win != NULL ? old_win->usage_count : (uintType) 0););
222     if (old_win != NULL && old_win->usage_count != 0) {
223       old_win->usage_count--;
224       if (old_win->usage_count == 0) {
225         drwFree(old_win);
226       } /* if */
227     } /* if */
228   } /* drwDestr */
229 
230 
231 
232 /**
233  *  Generic Destr function to be used via function pointers.
234  *  Function pointers in C programs generated by the Seed7 compiler
235  *  may point to this function. This assures correct behaviour even
236  *  if sizeof(genericType) != sizeof(winType).
237  */
drwDestrGeneric(const genericType old_value)238 void drwDestrGeneric (const genericType old_value)
239 
240   { /* drwDestrGeneric */
241     drwDestr(((const_rtlObjectType *) &old_value)->value.winValue);
242   } /* drwDestrGeneric */
243 
244 
245 
drwGetImagePixel(const_bstriType image,intType width,intType height,intType x,intType y)246 intType drwGetImagePixel (const_bstriType image, intType width,
247     intType height, intType x, intType y)
248 
249   {
250     memSizeType idx;
251     int32Type *image_data;
252     intType pixel;
253 
254   /* drwGetImagePixel */
255     logFunction(printf("drwGetImagePixel(" FMT_U_MEM ", " FMT_D ", "
256                        FMT_D ", " FMT_D ", " FMT_D ")\n",
257                        (memSizeType) image, width, height, x, y););
258     if (unlikely(width  < 0 || x < 0 || x >= width ||
259                  height < 0 || y < 0 || y >= height ||
260                  (uintType) height >
261                  MAX_MEMSIZETYPE / sizeof(int32Type) / (uintType) width)) {
262       raise_error(RANGE_ERROR);
263       pixel = 0;
264     } else {
265       idx = (memSizeType) y * (memSizeType) width + (memSizeType) x;
266       if (unlikely(idx >= image->size / sizeof(int32Type))) {
267         raise_error(RANGE_ERROR);
268         pixel = 0;
269       } else {
270         image_data = (int32Type *) image->mem;
271         pixel = image_data[idx];
272       } /* if */
273     } /* if */
274     return pixel;
275   } /* drwGetImagePixel */
276 
277 
278 
drwRtlImage(const const_rtlArrayType image)279 winType drwRtlImage (const const_rtlArrayType image)
280 
281   {
282     const_rtlObjectType *curr_line;
283     rtlArrayType arr_line;
284     int32Type *pixel_elem;
285     memSizeType height;
286     memSizeType width;
287     memSizeType line;
288     int32Type *image_data;
289     winType result;
290 
291   /* drwRtlImage */
292     height = arraySize(image);
293     /* printf("drwRtlImage: height=" FMT_U_MEM "\n", height); */
294     if (height == 0) {
295       raise_error(RANGE_ERROR);
296       result = NULL;
297     } else {
298       curr_line = &image->arr[0];
299       arr_line = curr_line->value.arrayValue;
300       width = arraySize(arr_line);
301       /* printf("drwRtlImage: width=" FMT_U_MEM "\n", width); */
302       if (width == 0) {
303         raise_error(RANGE_ERROR);
304         result = NULL;
305       } else {
306         if (height > MAX_MEMSIZETYPE / sizeof(int32Type) / (memSizeType) width ||
307             (image_data = (int32Type *) malloc((memSizeType) height * (memSizeType) width *
308                                                sizeof(int32Type))) == NULL) {
309           raise_error(MEMORY_ERROR);
310           result = NULL;
311         } else {
312           pixel_elem = image_data;
313           for (line = height; line > 0; line--, curr_line++) {
314             arr_line = curr_line->value.arrayValue;
315             memcpy_pixel(pixel_elem, (intType *) arr_line->arr, width);
316             pixel_elem += width;
317           } /* for */
318           result = drwImage(image_data, width, height);
319           free(image_data);
320         } /* if */
321       } /* if */
322     } /* if */
323     return result;
324   } /* drwRtlImage */
325