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