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