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 /**   Dispaly Management (Dispaly)                                        */
18 /**                                                                       */
19 /**************************************************************************/
20 
21 #define GX_SOURCE_CODE
22 
23 
24 /* Include necessary system files.  */
25 
26 #include "gx_api.h"
27 #include "gx_system.h"
28 #include "gx_display.h"
29 
30 #if defined GX_BRUSH_ALPHA_SUPPORT
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _gx_display_driver_generic_alphamap_raw_alpha_draw  PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Kenneth Maxwell, Microsoft Corporation                              */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    Internal helper function that handles writing  with brush alpha     */
45 /*    of uncompressed alpha map file.                                     */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    context                               Drawing context               */
50 /*    xpos                                  x-coord of top-left draw point*/
51 /*    ypos                                  y-coord of top-left draw point*/
52 /*    pixelmap                              Pointer to GX_PIXELMAP struct */
53 /*    alpha                                 alpha value from 0 to 255     */
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    None                                                                */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    [gx_display_driver_pixel_blend]       Basic display driver pixel    */
62 /*                                            blend function              */
63 /*                                                                        */
64 /*  CALLED BY                                                             */
65 /*                                                                        */
66 /*    _gx_display_driver_generic_alphamap_draw                            */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
73 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*                                                                        */
76 /**************************************************************************/
_gx_display_driver_generic_alphamap_raw_alpha_draw(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pmp,GX_UBYTE alpha)77 static VOID  _gx_display_driver_generic_alphamap_raw_alpha_draw(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pmp, GX_UBYTE alpha)
78 {
79 INT                xval;
80 INT                yval;
81 GX_UBYTE          *getrowalpha;
82 GX_CONST GX_UBYTE *getalpha;
83 GX_UBYTE           combined_alpha;
84 GX_COLOR           fill_color;
85 GX_RECTANGLE      *clip;
86 VOID               (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR fcolor, GX_UBYTE alpha);
87 
88     /* Pick up clip rectangle.  */
89     clip = context -> gx_draw_context_clip;
90 
91     blend_func = context -> gx_draw_context_display -> gx_display_driver_pixel_blend;
92 
93     if (blend_func == GX_NULL)
94     {
95         return;
96     }
97 
98     /* Pick up context fill color.  */
99     fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
100 
101     getrowalpha = (UCHAR *)(pmp -> gx_pixelmap_data);
102     getrowalpha += (pmp -> gx_pixelmap_width) * (clip -> gx_rectangle_top - ypos);
103     getrowalpha += (clip -> gx_rectangle_left - xpos);
104 
105     for (yval = clip -> gx_rectangle_top; yval <= clip -> gx_rectangle_bottom; yval++)
106     {
107         getalpha = getrowalpha;
108 
109         for (xval = clip -> gx_rectangle_left; xval <= clip -> gx_rectangle_right; xval++)
110         {
111             combined_alpha = (GX_UBYTE)((*getalpha++) * alpha / 255);
112             blend_func(context, xval, yval, fill_color, combined_alpha);
113         }
114 
115         getrowalpha += pmp -> gx_pixelmap_width;
116     }
117 }
118 
119 /**************************************************************************/
120 /*                                                                        */
121 /*  FUNCTION                                               RELEASE        */
122 /*                                                                        */
123 /*    _gx_display_driver_generic_alphamap_c_alpha_draw    PORTABLE C      */
124 /*                                                           6.1          */
125 /*  AUTHOR                                                                */
126 /*                                                                        */
127 /*    Kenneth Maxwell, Microsoft Corporation                              */
128 /*                                                                        */
129 /*  DESCRIPTION                                                           */
130 /*                                                                        */
131 /*    Internal helper function that handles writing with brush alpha      */
132 /*    of compressed alpha map file.                                       */
133 /*                                                                        */
134 /*  INPUT                                                                 */
135 /*                                                                        */
136 /*    context                               Drawing context               */
137 /*    xpos                                  x-coord of top-left draw point*/
138 /*    ypos                                  y-coord of top-left draw point*/
139 /*    pixelmap                              Pointer to GX_PIXELMAP struct */
140 /*    alpha                                 alpha value from 0 to 255     */
141 /*                                                                        */
142 /*  OUTPUT                                                                */
143 /*                                                                        */
144 /*    None                                                                */
145 /*                                                                        */
146 /*  CALLS                                                                 */
147 /*                                                                        */
148 /*    [gx_display_driver_pixel_blend]       Basic display driver pixel    */
149 /*                                            blend function              */
150 /*                                                                        */
151 /*  CALLED BY                                                             */
152 /*                                                                        */
153 /*    _gx_display_driver_generic_alphamap_draw                            */
154 /*                                                                        */
155 /*  RELEASE HISTORY                                                       */
156 /*                                                                        */
157 /*    DATE              NAME                      DESCRIPTION             */
158 /*                                                                        */
159 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
160 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
161 /*                                            resulting in version 6.1    */
162 /*                                                                        */
163 /**************************************************************************/
_gx_display_driver_generic_alphamap_compressed_alpha_draw(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pmp,GX_UBYTE alpha)164 static VOID  _gx_display_driver_generic_alphamap_compressed_alpha_draw(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pmp, GX_UBYTE alpha)
165 {
166 INT                yval;
167 INT                xval;
168 GX_CONST GX_UBYTE *get;
169 GX_UBYTE           count;
170 GX_UBYTE           falpha;
171 GX_COLOR           fill_color;
172 GX_RECTANGLE      *clip;
173 GX_UBYTE           combined_alpha;
174 VOID               (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR fcolor, GX_UBYTE alpha);
175 
176     /* Pick up clip rectangle. */
177     clip = context -> gx_draw_context_clip;
178 
179     blend_func = context -> gx_draw_context_display -> gx_display_driver_pixel_blend;
180 
181     if (blend_func == GX_NULL)
182     {
183         return;
184     }
185 
186     /* Pick up context fill color.  */
187     fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
188 
189     get = (GX_CONST GX_UBYTE *)pmp -> gx_pixelmap_data;
190 
191     /* compressed with no alpha is a two-byte count and two-byte pixel value */
192 
193     /* first, skip to the starting row */
194     for (yval = ypos; yval < clip -> gx_rectangle_top; yval++)
195     {
196         xval = 0;
197         while (xval < pmp -> gx_pixelmap_width)
198         {
199             count = *get++;
200 
201             if (count & 0x80)
202             {
203                 count = (GX_UBYTE)((count & 0x7f) + 1);
204                 get++;      /* skip repeated pixel value */
205             }
206             else
207             {
208                 count++;
209                 get += count;   /* skip raw pixel values */
210             }
211             xval += count;
212         }
213     }
214 
215     /* now we are on the first visible row, copy pixels until we get
216        to the enf of the last visible row
217      */
218 
219     while (yval <= clip -> gx_rectangle_bottom)
220     {
221         xval = xpos;
222 
223         while (xval < xpos + pmp -> gx_pixelmap_width)
224         {
225             count = *get++;
226 
227             if (count & 0x80)
228             {
229                 /* repeated value */
230                 count = (GX_UBYTE)((count & 0x7f) + 1);
231                 falpha = *get++;
232 
233                 while (count--)
234                 {
235                     if (xval >= clip -> gx_rectangle_left &&
236                         xval <= clip -> gx_rectangle_right)
237                     {
238                         combined_alpha = (GX_UBYTE)(falpha * alpha / 255);
239                         blend_func(context, xval, yval, fill_color, combined_alpha);
240                     }
241                     xval++;
242                 }
243             }
244             else
245             {
246                 /* string of non-repeated values */
247                 count++;
248                 while (count--)
249                 {
250                     if (xval >= clip -> gx_rectangle_left &&
251                         xval <= clip -> gx_rectangle_right)
252                     {
253                         combined_alpha = (GX_UBYTE)((*get) * alpha / 255);
254                         blend_func(context, xval, yval, fill_color, combined_alpha);
255                     }
256                     get++;
257                     xval++;
258                 }
259             }
260         }
261         yval++;
262     }
263 }
264 #endif /* GX_BRUSH_ALPHA_SUPPORT*/
265 
266 /**************************************************************************/
267 /*                                                                        */
268 /*  FUNCTION                                               RELEASE        */
269 /*                                                                        */
270 /*    _gx_display_driver_generic_alphamap_raw_draw        PORTABLE C      */
271 /*                                                           6.1          */
272 /*  AUTHOR                                                                */
273 /*                                                                        */
274 /*    Kenneth Maxwell, Microsoft Corporation                              */
275 /*                                                                        */
276 /*  DESCRIPTION                                                           */
277 /*                                                                        */
278 /*    Internal helper function that handles writing of uncompressed       */
279 /*    alpha map file.                                                     */
280 /*                                                                        */
281 /*  INPUT                                                                 */
282 /*                                                                        */
283 /*    context                               Drawing context               */
284 /*    xpos                                  x-coord of top-left draw point*/
285 /*    ypos                                  y-coord of top-left draw point*/
286 /*    pixelmap                              Pointer to GX_PIXELMAP struct */
287 /*                                                                        */
288 /*  OUTPUT                                                                */
289 /*                                                                        */
290 /*    None                                                                */
291 /*                                                                        */
292 /*  CALLS                                                                 */
293 /*                                                                        */
294 /*    [gx_display_driver_pixel_blend]       Basic display driver pixel    */
295 /*                                            blend function              */
296 /*                                                                        */
297 /*  CALLED BY                                                             */
298 /*                                                                        */
299 /*    _gx_display_driver_generic_alphamap_draw                            */
300 /*                                                                        */
301 /*  RELEASE HISTORY                                                       */
302 /*                                                                        */
303 /*    DATE              NAME                      DESCRIPTION             */
304 /*                                                                        */
305 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
306 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
307 /*                                            resulting in version 6.1    */
308 /*                                                                        */
309 /**************************************************************************/
_gx_display_driver_generic_alphamap_raw_draw(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pmp)310 static VOID  _gx_display_driver_generic_alphamap_raw_draw(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pmp)
311 {
312 INT                xval;
313 INT                yval;
314 GX_UBYTE          *getrowalpha;
315 GX_CONST GX_UBYTE *getalpha;
316 GX_COLOR           fill_color;
317 GX_RECTANGLE      *clip;
318 VOID               (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR fcolor, GX_UBYTE alpha);
319 
320     /* Pick up clip rectangle.  */
321     clip = context -> gx_draw_context_clip;
322 
323     blend_func = context -> gx_draw_context_display -> gx_display_driver_pixel_blend;
324 
325     if (blend_func == GX_NULL)
326     {
327         return;
328     }
329 
330     /* Pick up context fill color.  */
331     fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
332 
333     getrowalpha = (UCHAR *)(pmp -> gx_pixelmap_data);
334     getrowalpha += (pmp -> gx_pixelmap_width) * (clip -> gx_rectangle_top - ypos);
335     getrowalpha += (clip -> gx_rectangle_left - xpos);
336 
337     for (yval = clip -> gx_rectangle_top; yval <= clip -> gx_rectangle_bottom; yval++)
338     {
339         getalpha = getrowalpha;
340 
341         for (xval = clip -> gx_rectangle_left; xval <= clip -> gx_rectangle_right; xval++)
342         {
343             blend_func(context, xval, yval, fill_color, *getalpha++);
344         }
345 
346         getrowalpha += pmp -> gx_pixelmap_width;
347     }
348 }
349 
350 /**************************************************************************/
351 /*                                                                        */
352 /*  FUNCTION                                               RELEASE        */
353 /*                                                                        */
354 /*    _gx_display_driver_generic_alphamap_compressed_draw PORTABLE C      */
355 /*                                                           6.1          */
356 /*  AUTHOR                                                                */
357 /*                                                                        */
358 /*    Kenneth Maxwell, Microsoft Corporation                              */
359 /*                                                                        */
360 /*  DESCRIPTION                                                           */
361 /*                                                                        */
362 /*    Internal helper function that handles writing of compressed         */
363 /*    alpha map file.                                                     */
364 /*                                                                        */
365 /*  INPUT                                                                 */
366 /*                                                                        */
367 /*    context                               Drawing context               */
368 /*    xpos                                  x-coord of top-left draw point*/
369 /*    ypos                                  y-coord of top-left draw point*/
370 /*    pixelmap                              Pointer to GX_PIXELMAP struct */
371 /*                                                                        */
372 /*  OUTPUT                                                                */
373 /*                                                                        */
374 /*    None                                                                */
375 /*                                                                        */
376 /*  CALLS                                                                 */
377 /*                                                                        */
378 /*    [gx_display_driver_pixel_blend]       Basic display driver pixel    */
379 /*                                            blend function              */
380 /*                                                                        */
381 /*  CALLED BY                                                             */
382 /*                                                                        */
383 /*    _gx_display_driver_generic_alphamap_draw                            */
384 /*                                                                        */
385 /*  RELEASE HISTORY                                                       */
386 /*                                                                        */
387 /*    DATE              NAME                      DESCRIPTION             */
388 /*                                                                        */
389 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
390 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
391 /*                                            resulting in version 6.1    */
392 /*                                                                        */
393 /**************************************************************************/
_gx_display_driver_generic_alphamap_compressed_draw(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pmp)394 static VOID  _gx_display_driver_generic_alphamap_compressed_draw(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pmp)
395 {
396 INT                yval;
397 INT                xval;
398 GX_CONST GX_UBYTE *get;
399 GX_UBYTE           count;
400 GX_UBYTE           pixel;
401 GX_COLOR           fill_color;
402 GX_RECTANGLE      *clip;
403 VOID               (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR fcolor, GX_UBYTE alpha);
404 
405     /* Pick up clip rectangle.  */
406     clip = context -> gx_draw_context_clip;
407 
408     blend_func = context -> gx_draw_context_display -> gx_display_driver_pixel_blend;
409 
410     if (blend_func == GX_NULL)
411     {
412         return;
413     }
414 
415     /* Pick up context fill color.  */
416     fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
417 
418     get = (GX_CONST GX_UBYTE *)pmp -> gx_pixelmap_data;
419 
420     /* compressed with no alpha is a two-byte count and two-byte pixel value */
421 
422     /* first, skip to the starting row */
423     for (yval = ypos; yval < clip -> gx_rectangle_top; yval++)
424     {
425         xval = 0;
426         while (xval < pmp -> gx_pixelmap_width)
427         {
428             count = *get++;
429 
430             if (count & 0x80)
431             {
432                 count = (GX_UBYTE)((count & 0x7f) + 1);
433                 get++;      /* skip repeated pixel value */
434             }
435             else
436             {
437                 count++;
438                 get += count;   /* skip raw pixel values */
439             }
440             xval += count;
441         }
442     }
443 
444     /* now we are on the first visible row, copy pixels until we get
445        to the enf of the last visible row
446      */
447 
448     while (yval <= clip -> gx_rectangle_bottom)
449     {
450         xval = xpos;
451 
452         while (xval < xpos + pmp -> gx_pixelmap_width)
453         {
454             count = *get++;
455 
456             if (count & 0x80)
457             {
458                 /* repeated value */
459                 count = (GX_UBYTE)((count & 0x7f) + 1);
460                 pixel = *get++;
461 
462                 while (count--)
463                 {
464                     if (xval >= clip -> gx_rectangle_left &&
465                         xval <= clip -> gx_rectangle_right)
466                     {
467                         blend_func(context, xval, yval, fill_color, pixel);
468                     }
469                     xval++;
470                 }
471             }
472             else
473             {
474                 /* string of non-repeated values */
475                 count++;
476                 while (count--)
477                 {
478                     if (xval >= clip -> gx_rectangle_left &&
479                         xval <= clip -> gx_rectangle_right)
480                     {
481                         blend_func(context, xval, yval, fill_color, *get);
482                     }
483                     get++;
484                     xval++;
485                 }
486             }
487         }
488         yval++;
489     }
490 }
491 
492 /**************************************************************************/
493 /*                                                                        */
494 /*  FUNCTION                                               RELEASE        */
495 /*                                                                        */
496 /*    _gx_display_driver_generic_alphamap_draw            PORTABLE C      */
497 /*                                                           6.1          */
498 /*  AUTHOR                                                                */
499 /*                                                                        */
500 /*    Kenneth Maxwell, Microsoft Corporation                              */
501 /*                                                                        */
502 /*  DESCRIPTION                                                           */
503 /*                                                                        */
504 /*    This function blends the context fill color with the canvas         */
505 /*      background.                                                       */
506 /*                                                                        */
507 /*  INPUT                                                                 */
508 /*                                                                        */
509 /*    context                               Drawing context               */
510 /*    xpos                                  x-coord of top-left draw point*/
511 /*    ypos                                  y-coord of top-left draw point*/
512 /*    pmp                                   Pointer to GX_PIXELMAP struct */
513 /*                                                                        */
514 /*  OUTPUT                                                                */
515 /*                                                                        */
516 /*    status                                Completion status             */
517 /*                                                                        */
518 /*  CALLS                                                                 */
519 /*                                                                        */
520 /*    _gx_display_driver_generic_alphamap_compressed_alpha_draw           */
521 /*                                          Real display driver alphamap  */
522 /*                                            draw function               */
523 /*    _gx_display_driver_generic_alphamap_raw_alpha_draw                  */
524 /*                                          Real display driver alphamap  */
525 /*                                            draw function               */
526 /*    _gx_display_driver_generic_alphamap_compressed_draw                 */
527 /*                                          Real display driver alphamap  */
528 /*                                            draw function               */
529 /*    _gx_display_driver_generic_alphamap_raw_draw                        */
530 /*                                          Real display driver alphamap  */
531 /*                                            draw function               */
532 /*                                                                        */
533 /*  CALLED BY                                                             */
534 /*                                                                        */
535 /*    Application Code                                                    */
536 /*    GUIX default draw funtions                                          */
537 /*                                                                        */
538 /*  RELEASE HISTORY                                                       */
539 /*                                                                        */
540 /*    DATE              NAME                      DESCRIPTION             */
541 /*                                                                        */
542 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
543 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
544 /*                                            resulting in version 6.1    */
545 /*                                                                        */
546 /**************************************************************************/
_gx_display_driver_generic_alphamap_draw(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pmp)547 VOID  _gx_display_driver_generic_alphamap_draw(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pmp)
548 {
549 #if defined GX_BRUSH_ALPHA_SUPPORT
550 GX_UBYTE alpha;
551 
552     alpha = context -> gx_draw_context_brush.gx_brush_alpha;
553     if (alpha == 0)
554     {
555         /* Nothing to drawn. Just return. */
556         return;
557     }
558 
559     if (alpha != 0xff)
560     {
561         if (pmp -> gx_pixelmap_flags & GX_PIXELMAP_COMPRESSED)
562         {
563             _gx_display_driver_generic_alphamap_compressed_alpha_draw(context, xpos, ypos, pmp, alpha);
564         }
565         else
566         {
567             _gx_display_driver_generic_alphamap_raw_alpha_draw(context, xpos, ypos, pmp, alpha);
568         }
569         return;
570     }
571 #endif
572 
573     if (pmp -> gx_pixelmap_flags & GX_PIXELMAP_COMPRESSED)
574     {
575         _gx_display_driver_generic_alphamap_compressed_draw(context, xpos, ypos, pmp);
576     }
577     else
578     {
579         _gx_display_driver_generic_alphamap_raw_draw(context, xpos, ypos, pmp);
580     }
581 }
582 
583