1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** Utility (Utility) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23 /* Include necessary system files. */
24
25 #include "gx_api.h"
26 #include "gx_canvas.h"
27 #include "gx_system.h"
28 #include "gx_utility.h"
29
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _gx_utility_gradient_find PORTABLE C */
35 /* 6.1 */
36 /* AUTHOR */
37 /* */
38 /* Kenneth Maxwell, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* Helper function for _gx_utility_gradient_create. This function */
43 /* searches the gradient list to find a match. */
44 /* */
45 /* INPUT */
46 /* */
47 /* gradient GX_GRADIENT pointer */
48 /* */
49 /* OUTPUT */
50 /* */
51 /* Completion Status */
52 /* */
53 /* CALLS */
54 /* */
55 /* None */
56 /* */
57 /* CALLED BY */
58 /* */
59 /* _gx_utility_gradient_create */
60 /* */
61 /* RELEASE HISTORY */
62 /* */
63 /* DATE NAME DESCRIPTION */
64 /* */
65 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
66 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
67 /* resulting in version 6.1 */
68 /* */
69 /**************************************************************************/
_gx_utility_gradient_find(GX_GRADIENT * gradient)70 static GX_BOOL _gx_utility_gradient_find(GX_GRADIENT *gradient)
71 {
72 GX_GRADIENT *search = _gx_system_gradient_list;
73
74 /* look for a matching gradient */
75 while (search)
76 {
77 if (search -> gx_gradient_pixelmap.gx_pixelmap_data &&
78 search -> gx_gradient_type == gradient -> gx_gradient_type &&
79 search -> gx_gradient_alpha_start == gradient -> gx_gradient_alpha_start &&
80 search -> gx_gradient_alpha_end == gradient -> gx_gradient_alpha_end &&
81 search -> gx_gradient_pixelmap.gx_pixelmap_width == gradient -> gx_gradient_pixelmap.gx_pixelmap_width &&
82 search -> gx_gradient_pixelmap.gx_pixelmap_height == gradient -> gx_gradient_pixelmap.gx_pixelmap_height)
83 {
84 /* found a match, just copy the pixelmap */
85 gradient -> gx_gradient_pixelmap = search -> gx_gradient_pixelmap;
86 return GX_TRUE;
87 }
88 search = search -> gx_gradient_next;
89 }
90
91 /* did not find a match, need to create a new gradient pixelmap */
92 return GX_FALSE;
93 }
94
95
96 /**************************************************************************/
97 /* */
98 /* FUNCTION RELEASE */
99 /* */
100 /* _gx_utility_horizontal_alpha_gradient_create PORTABLE C */
101 /* 6.1 */
102 /* AUTHOR */
103 /* */
104 /* Kenneth Maxwell, Microsoft Corporation */
105 /* */
106 /* DESCRIPTION */
107 /* */
108 /* This function creates a horizontal alpha gradient pixelmap. */
109 /* */
110 /* INPUT */
111 /* */
112 /* gradient GX_GRADIENT structure */
113 /* */
114 /* OUTPUT */
115 /* */
116 /* Completion Status */
117 /* */
118 /* CALLS */
119 /* */
120 /* None */
121 /* */
122 /* CALLED BY */
123 /* */
124 /* _gx_utility_gradient_create */
125 /* */
126 /* RELEASE HISTORY */
127 /* */
128 /* DATE NAME DESCRIPTION */
129 /* */
130 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
131 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
132 /* resulting in version 6.1 */
133 /* */
134 /**************************************************************************/
_gx_utility_horizontal_alpha_gradient_create(GX_GRADIENT * gradient)135 static UINT _gx_utility_horizontal_alpha_gradient_create(GX_GRADIENT *gradient)
136 {
137 INT column;
138 INT row;
139 INT height;
140 INT width;
141 GX_UBYTE dataval;
142 GX_UBYTE *data;
143 GX_UBYTE *data_start = (GX_UBYTE *)gradient -> gx_gradient_pixelmap.gx_pixelmap_data;
144
145 height = gradient -> gx_gradient_pixelmap.gx_pixelmap_height;
146 width = gradient -> gx_gradient_pixelmap.gx_pixelmap_width;
147
148 if (gradient -> gx_gradient_type & GX_GRADIENT_TYPE_MIRROR)
149 {
150 for (column = 0; column < width / 2; column++)
151 {
152 dataval = (GX_UBYTE)(GX_FIXED_VAL_TO_INT(gradient -> gx_gradient_alpha_current));
153 data = data_start;
154
155 for (row = 0; row < height; row++)
156 {
157 *data = dataval;
158 data += width;
159 }
160 data_start++;
161 gradient -> gx_gradient_alpha_current += gradient -> gx_gradient_alpha_step;
162 }
163 for (; column < width; column++)
164 {
165 dataval = (GX_UBYTE)(GX_FIXED_VAL_TO_INT(gradient -> gx_gradient_alpha_current));
166 data = data_start;
167
168 for (row = 0; row < height; row++)
169 {
170 *data = dataval;
171 data += width;
172 }
173 data_start++;
174 gradient -> gx_gradient_alpha_current -= gradient -> gx_gradient_alpha_step;
175 }
176 }
177 else
178 {
179 for (column = 0; column < width; column++)
180 {
181 dataval = (GX_UBYTE)(GX_FIXED_VAL_TO_INT(gradient -> gx_gradient_alpha_current));
182 data = data_start;
183
184 for (row = 0; row < height; row++)
185 {
186 *data = dataval;
187 data += width;
188 }
189 data_start++;
190 gradient -> gx_gradient_alpha_current += gradient -> gx_gradient_alpha_step;
191 }
192 }
193 return GX_SUCCESS;
194 }
195
196 /**************************************************************************/
197 /* */
198 /* FUNCTION RELEASE */
199 /* */
200 /* _gx_utility_vertical_alpha_gradient_create PORTABLE C */
201 /* 6.1 */
202 /* AUTHOR */
203 /* */
204 /* Kenneth Maxwell, Microsoft Corporation */
205 /* */
206 /* DESCRIPTION */
207 /* */
208 /* This function creates a vertical alpha gradient pixelmap. */
209 /* */
210 /* INPUT */
211 /* */
212 /* gradient GX_GRADIENT structure */
213 /* */
214 /* OUTPUT */
215 /* */
216 /* Completion status */
217 /* */
218 /* CALLS */
219 /* */
220 /* None */
221 /* */
222 /* CALLED BY */
223 /* */
224 /* _gx_utility_gradient_create */
225 /* */
226 /* RELEASE HISTORY */
227 /* */
228 /* DATE NAME DESCRIPTION */
229 /* */
230 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
231 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
232 /* resulting in version 6.1 */
233 /* */
234 /**************************************************************************/
_gx_utility_vertical_alpha_gradient_create(GX_GRADIENT * gradient)235 static UINT _gx_utility_vertical_alpha_gradient_create(GX_GRADIENT *gradient)
236 {
237 INT row;
238 INT height;
239 INT width;
240 GX_UBYTE *data = (GX_UBYTE *)gradient -> gx_gradient_pixelmap.gx_pixelmap_data;
241
242 height = gradient -> gx_gradient_pixelmap.gx_pixelmap_height;
243 width = gradient -> gx_gradient_pixelmap.gx_pixelmap_width;
244
245 if (gradient -> gx_gradient_type & GX_GRADIENT_TYPE_MIRROR)
246 {
247 for (row = 0; row < height / 2; row++)
248 {
249 memset(data, GX_FIXED_VAL_TO_INT(gradient -> gx_gradient_alpha_current), (size_t)width);
250 data += width;
251 gradient -> gx_gradient_alpha_current += gradient -> gx_gradient_alpha_step;
252 }
253 for (; row < height; row++)
254 {
255 memset(data, GX_FIXED_VAL_TO_INT(gradient -> gx_gradient_alpha_current), (size_t)width);
256 data += width;
257 gradient -> gx_gradient_alpha_current -= gradient -> gx_gradient_alpha_step;
258 }
259 }
260 else
261 {
262 for (row = 0; row < height; row++)
263 {
264 memset(data, GX_FIXED_VAL_TO_INT(gradient -> gx_gradient_alpha_current), (size_t)width);
265 data += width;
266 gradient -> gx_gradient_alpha_current += gradient -> gx_gradient_alpha_step;
267 }
268 }
269
270 return GX_SUCCESS;
271 }
272
273
274
275
276 /**************************************************************************/
277 /* */
278 /* FUNCTION RELEASE */
279 /* */
280 /* _gx_utility_gradient_create PORTABLE C */
281 /* 6.1.3 */
282 /* AUTHOR */
283 /* */
284 /* Kenneth Maxwell, Microsoft Corporation */
285 /* */
286 /* DESCRIPTION */
287 /* */
288 /* This function creates a gradient pixelmap. */
289 /* */
290 /* INPUT */
291 /* */
292 /* gradient Pointer to GX_GRADIENT */
293 /* width Requested width */
294 /* height Requested height */
295 /* type Gradient type */
296 /* alpha_start Starting alpha value */
297 /* alpha_end Ending alpha value */
298 /* */
299 /* OUTPUT */
300 /* */
301 /* None */
302 /* */
303 /* CALLS */
304 /* */
305 /* _gx_system_gradient_find */
306 /* _gx_utility_alphamap_create */
307 /* */
308 /* CALLED BY */
309 /* */
310 /* _gx_text_scroll_wheel_gradient_create */
311 /* */
312 /* RELEASE HISTORY */
313 /* */
314 /* DATE NAME DESCRIPTION */
315 /* */
316 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
317 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
318 /* resulting in version 6.1 */
319 /* 12-31-2020 Kenneth Maxwell Modified comment(s), removed */
320 /* errant comment, */
321 /* resulting in version 6.1.3 */
322 /* */
323 /**************************************************************************/
_gx_utility_gradient_create(GX_GRADIENT * gradient,GX_VALUE width,GX_VALUE height,UCHAR type,GX_UBYTE alpha_start,GX_UBYTE alpha_end)324 UINT _gx_utility_gradient_create(GX_GRADIENT *gradient, GX_VALUE width, GX_VALUE height,
325 UCHAR type, GX_UBYTE alpha_start, GX_UBYTE alpha_end)
326 {
327 UINT status = GX_FAILURE;
328
329 /* width and height must be >= 2 pixels */
330
331 if (width < 2 || height < 2)
332 {
333 return GX_INVALID_SIZE;
334 }
335
336 /* only alpha gradient supported currently */
337 if (!(type & GX_GRADIENT_TYPE_ALPHA))
338 {
339 return GX_NOT_SUPPORTED;
340 }
341
342 memset(&gradient -> gx_gradient_pixelmap, 0, sizeof(GX_PIXELMAP));
343 gradient -> gx_gradient_pixelmap.gx_pixelmap_width = width;
344 gradient -> gx_gradient_pixelmap.gx_pixelmap_height = height;
345 gradient -> gx_gradient_type = type;
346 gradient -> gx_gradient_alpha_start = alpha_start;
347 gradient -> gx_gradient_alpha_end = alpha_end;
348 gradient -> gx_gradient_previous = GX_NULL;
349 gradient -> gx_gradient_next = GX_NULL;
350
351 if (_gx_utility_gradient_find(gradient))
352 {
353 status = GX_SUCCESS;
354 }
355 else
356 {
357 gradient -> gx_gradient_alpha_current = GX_FIXED_VAL_MAKE(gradient -> gx_gradient_alpha_start);
358 gradient -> gx_gradient_alpha_step = GX_FIXED_VAL_MAKE(gradient -> gx_gradient_alpha_end);
359 gradient -> gx_gradient_alpha_step -= GX_FIXED_VAL_MAKE(gradient -> gx_gradient_alpha_start);
360
361 status = _gx_utility_alphamap_create(width, height, &gradient -> gx_gradient_pixelmap);
362
363 if (status == GX_SUCCESS)
364 {
365 if (gradient -> gx_gradient_type & GX_GRADIENT_TYPE_VERTICAL)
366 {
367 if (gradient -> gx_gradient_type & GX_GRADIENT_TYPE_MIRROR)
368 {
369 gradient -> gx_gradient_alpha_step /= (height / 2);
370 }
371 else
372 {
373 gradient -> gx_gradient_alpha_step /= height;
374 }
375 status = _gx_utility_vertical_alpha_gradient_create(gradient);
376 }
377 else
378 {
379 if (gradient -> gx_gradient_type & GX_GRADIENT_TYPE_MIRROR)
380 {
381 gradient -> gx_gradient_alpha_step /= (width / 2);
382 }
383 else
384 {
385 gradient -> gx_gradient_alpha_step /= width;
386 }
387 status = _gx_utility_horizontal_alpha_gradient_create(gradient);
388 }
389 }
390 }
391
392 if (status == GX_SUCCESS)
393 {
394 /* lock access to GUIX */
395 GX_ENTER_CRITICAL
396
397 /* insert gradient into global gradient list */
398 gradient -> gx_gradient_next = _gx_system_gradient_list;
399
400 if (_gx_system_gradient_list)
401 {
402 _gx_system_gradient_list -> gx_gradient_previous = gradient;
403 }
404 _gx_system_gradient_list = gradient;
405
406 GX_EXIT_CRITICAL
407 }
408
409 return status;
410 }
411
412