GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_4444argb_pixelmap_rotate.c Lines: 156 156 100.0 %
Date: 2026-03-06 19:21:09 Branches: 66 66 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** GUIX Component                                                        */
17
/**                                                                       */
18
/**   Display Management (Display)                                        */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define ALPHAVAL(_c) (GX_UBYTE)(((_c) >> 12) & 0x0f)
23
#define REDVAL(_c)   (GX_UBYTE)(((_c) >> 8) & 0x0f)
24
#define GREENVAL(_c) (GX_UBYTE)(((_c) >> 4) & 0x0f)
25
#define BLUEVAL(_c)  (GX_UBYTE)(((_c)) & 0x0f)
26
27
#define ASSEMBLECOLOR(_a, _r, _g, _b) \
28
    ((((_a) & 0x0f) << 12) |          \
29
     (((_r) & 0x0f) << 8) |           \
30
     (((_g) & 0x0f) << 4) |           \
31
     (((_b) & 0x0f)))
32
33
#define GX_SOURCE_CODE
34
35
/* Include necessary system files.  */
36
37
#include "gx_api.h"
38
#include "gx_display.h"
39
#include "gx_context.h"
40
#include "gx_utility.h"
41
#include "gx_system.h"
42
43
/**************************************************************************/
44
/*                                                                        */
45
/*  FUNCTION                                               RELEASE        */
46
/*                                                                        */
47
/*    _gx_display_driver_4444argb_pixelmap_general_rotate                 */
48
/*                                                        PORTABLE C      */
49
/*                                                           6.1.10       */
50
/*  AUTHOR                                                                */
51
/*                                                                        */
52
/*    Kenneth Maxwell, Microsoft Corporation                              */
53
/*                                                                        */
54
/*  DESCRIPTION                                                           */
55
/*                                                                        */
56
/*    Internal helper function that rotate an 4444argb format pixelmap    */
57
/*    without compression, without alpha.                                 */
58
/*                                                                        */
59
/*  INPUT                                                                 */
60
/*                                                                        */
61
/*    context                               Drawing context               */
62
/*    xpos                                  x-coord of top-left draw point*/
63
/*    ypos                                  y-coord of top-left draw point*/
64
/*    pixelmap                              Pointer to GX_PIXELMAP struct */
65
/*    angle                                 The angle to rotate           */
66
/*    cx                                    x-coord of rotate center      */
67
/*    cy                                    y-coord of rotate center      */
68
/*                                                                        */
69
/*  OUTPUT                                                                */
70
/*                                                                        */
71
/*    status                                Completion status             */
72
/*                                                                        */
73
/*  CALLS                                                                 */
74
/*                                                                        */
75
/*    _gx_utility_math_cos                  Compute the cosine value      */
76
/*    _gx_utility_math_sin                  Compute the sine value        */
77
/*    [gx_display_driver_pixel_blend]       Display driver basic pixel    */
78
/*                                             blend function             */
79
/*                                                                        */
80
/*  CALLED BY                                                             */
81
/*                                                                        */
82
/*    GUIX Internal Code                                                  */
83
/*                                                                        */
84
/**************************************************************************/
85
1425
static VOID _gx_display_driver_4444argb_pixelmap_general_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
86
                                                                INT angle, INT cx, INT cy)
87
{
88
USHORT       *get;
89
INT           srcxres;
90
INT           srcyres;
91
INT           cosv;
92
INT           sinv;
93
USHORT        red;
94
USHORT        green;
95
USHORT        blue;
96
INT           idxminx;
97
INT           idxmaxx;
98
INT           idxmaxy;
99
INT          *mx;
100
INT          *my;
101
INT           xres;
102
INT           yres;
103
INT           x;
104
INT           y;
105
INT           xx;
106
INT           yy;
107
USHORT        a;
108
USHORT        b;
109
USHORT        c;
110
USHORT        d;
111
INT           xdiff;
112
INT           ydiff;
113
INT           newxpos;
114
INT           newypos;
115
GX_DISPLAY   *display;
116
GX_RECTANGLE *clip;
117
VOID          (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
118
1425
USHORT        alpha[4] = {0};
119
120
1425
    clip = context -> gx_draw_context_clip;
121
1425
    display = context -> gx_draw_context_display;
122
1425
    blend_func = display -> gx_display_driver_pixel_blend;
123
124
1425
    if (!blend_func)
125
    {
126
1
        return;
127
    }
128
129
1424
    mx = _gx_system_scratchpad;
130
1424
    my = mx + 4;
131
132
1424
    mx[0] = mx[3] = -1;
133
1424
    mx[1] = mx[2] = 1;
134
135
1424
    my[0] = my[1] = 1;
136
1424
    my[2] = my[3] = -1;
137
138
1424
    idxminx = (angle / 90) & 0x3;
139
1424
    idxmaxx = (idxminx + 2) & 0x3;
140
1424
    idxmaxy = (idxminx + 1) & 0x3;
141
142
    /* Calculate the source x and y center. */
143
1424
    srcxres = pixelmap -> gx_pixelmap_width >> 1;
144
1424
    srcyres = pixelmap -> gx_pixelmap_height >> 1;
145
146
1424
    cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
147
1424
    sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
148
149
1424
    xres = GX_FIXED_VAL_TO_INT(mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv);
150
1424
    yres = GX_FIXED_VAL_TO_INT(my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv);
151
152
    /* Calculate the new rotation axis. */
153
154
1424
    xres = GX_FIXED_VAL_TO_INT((cx - srcxres) * cosv - (cy - srcyres) * sinv) + xres;
155
1424
    yres = GX_FIXED_VAL_TO_INT((cy - srcyres) * cosv + (cx - srcxres) * sinv) + xres;
156
157
1424
    newxpos = xpos + cx - xres;
158
1424
    newypos = ypos + cy - yres;
159
160
    /* Loop through the destination's pixels.  */
161
318258
    for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
162
    {
163
81087609
        for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
164
        {
165
80770775
            xx = (x - xres) * cosv + (y - yres) * sinv;
166
80770775
            yy = (y - yres) * cosv - (x - xres) * sinv;
167
168
80770775
            xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
169
80770775
            ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
170
171
80770775
            xx = GX_FIXED_VAL_TO_INT(xx) + cx;
172
80770775
            yy = GX_FIXED_VAL_TO_INT(yy) + cy;
173
174

80770775
            if ((xx >= -1) && (xx < pixelmap -> gx_pixelmap_width) &&
175
57533958
                (yy >= -1) && (yy < pixelmap -> gx_pixelmap_height))
176
            {
177

47556374
                if ((xx >= 0) && (xx < pixelmap -> gx_pixelmap_width - 1) &&
178
46889878
                    (yy >= 0) && (yy < pixelmap -> gx_pixelmap_height - 1))
179
                {
180
46618699
                    get = (USHORT *)pixelmap -> gx_pixelmap_data;
181
46618699
                    get += yy * pixelmap -> gx_pixelmap_width;
182
46618699
                    get += xx;
183
184
46618699
                    a = *get;
185
46618699
                    b = *(get + 1);
186
46618699
                    c = *(get + pixelmap -> gx_pixelmap_width);
187
46618699
                    d = *(get + pixelmap -> gx_pixelmap_width + 1);
188
46618699
                    alpha[0] = ALPHAVAL(a);
189
46618699
                    alpha[1] = ALPHAVAL(b);
190
46618699
                    alpha[2] = ALPHAVAL(c);
191
46618699
                    alpha[3] = ALPHAVAL(d);
192
                }
193
                else
194
                {
195
937675
                    get = (USHORT *)pixelmap -> gx_pixelmap_data;
196
197
937675
                    a = 0;
198
937675
                    b = 0;
199
937675
                    c = 0;
200
937675
                    d = 0;
201
202
937675
                    if (xx == -1)
203
                    {
204
                        /* handle left edge.  */
205
192402
                        if (yy >= 0)
206
                        {
207
191702
                            b = *(get + yy * pixelmap -> gx_pixelmap_width);
208
191702
                            alpha[1] = ALPHAVAL(b);
209
                        }
210
211
192402
                        if (yy < pixelmap -> gx_pixelmap_height - 1)
212
                        {
213
191509
                            d = *(get + (yy + 1) * pixelmap -> gx_pixelmap_width);
214
191509
                            alpha[3] = ALPHAVAL(d);
215
                        }
216
                    }
217
745273
                    else if (yy == -1)
218
                    {
219
                        /* handle top edge.  */
220
229346
                        c = *(get + xx);
221
229346
                        alpha[2] = ALPHAVAL(c);
222
223
229346
                        if (xx < pixelmap -> gx_pixelmap_width - 1)
224
                        {
225
228292
                            d = *(get + xx + 1);
226
228292
                            alpha[3] = ALPHAVAL(d);
227
                        }
228
                    }
229
515927
                    else if (xx == pixelmap -> gx_pixelmap_width - 1)
230
                    {
231
                        /* handle right edget. */
232
244748
                        a = *(get + yy * pixelmap -> gx_pixelmap_width + xx);
233
244748
                        alpha[0] = ALPHAVAL(a);
234
235
244748
                        if (yy < pixelmap -> gx_pixelmap_height - 1)
236
                        {
237
242676
                            c = *(get + (yy + 1) * pixelmap -> gx_pixelmap_width + xx);
238
242676
                            alpha[2] = ALPHAVAL(c);
239
                        }
240
                    }
241
                    else
242
                    {
243
                        /* handle bottom edge. */
244
271179
                        a = *(get + yy * pixelmap -> gx_pixelmap_width + xx);
245
271179
                        alpha[0] = ALPHAVAL(a);
246
247
271179
                        b = *(get + yy * pixelmap -> gx_pixelmap_width + xx + 1);
248
271179
                        alpha[1] = ALPHAVAL(b);
249
                    }
250
251
937675
                    if (!a)
252
                    {
253
421748
                        alpha[0] = 0;
254
                    }
255
256
937675
                    if (!b)
257
                    {
258
474794
                        alpha[1] = 0;
259
                    }
260
261
937675
                    if (!c)
262
                    {
263
465653
                        alpha[2] = 0;
264
                    }
265
266
937675
                    if (!d)
267
                    {
268
517874
                        alpha[3] = 0;
269
                    }
270
                }
271
272
47556374
                red = (USHORT)((REDVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) +
273
47556374
                                REDVAL(b) * alpha[1] * xdiff * (256 - ydiff) +
274
47556374
                                REDVAL(c) * alpha[2] * ydiff * (256 - xdiff) +
275
47556374
                                REDVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
276
277
47556374
                green = (USHORT)((GREENVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) +
278
47556374
                                  GREENVAL(b) * alpha[1] * xdiff * (256 - ydiff) +
279
47556374
                                  GREENVAL(c) * alpha[2] * ydiff * (256 - xdiff) +
280
47556374
                                  GREENVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
281
282
47556374
                blue = (USHORT)((BLUEVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) +
283
47556374
                                 BLUEVAL(b) * alpha[1] * xdiff * (256 - ydiff) +
284
47556374
                                 BLUEVAL(c) * alpha[2] * ydiff * (256 - xdiff) +
285
47556374
                                 BLUEVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
286
287
47556374
                alpha[0] = (USHORT)((alpha[0] * (256 - xdiff) * (256 - ydiff) +
288
47556374
                                     alpha[1] * xdiff * (256 - ydiff) +
289
47556374
                                     alpha[2] * ydiff * (256 - xdiff) +
290
47556374
                                     alpha[3] * xdiff * ydiff) >> 16);
291
292
47556374
                if (alpha[0])
293
                {
294
39320652
                    red /= alpha[0];
295
39320652
                    green /= alpha[0];
296
39320652
                    blue /= alpha[0];
297
                }
298
299
47556374
                red = red > 15 ? 15 : red;
300
47556374
                green = green > 15 ? 15 : green;
301
47556374
                blue = blue > 15 ? 15 : blue;
302
47556374
                alpha[0] = alpha[0] > 15 ? 15 : alpha[0];
303
304
47556374
                blend_func(context, x + newxpos, y + newypos, (GX_COLOR)ASSEMBLECOLOR(alpha[0], red, green, blue), (GX_UBYTE)0xff);
305
            }
306
        }
307
    }
308
}
309
310
/**************************************************************************/
311
/*                                                                        */
312
/*  FUNCTION                                               RELEASE        */
313
/*                                                                        */
314
/*    _gx_display_driver_4444argb_pixelmap_simple_rotate  PORTABLE C      */
315
/*                                                           6.1.7        */
316
/*  AUTHOR                                                                */
317
/*                                                                        */
318
/*    Kenneth Maxwell, Microsoft Corporation                              */
319
/*                                                                        */
320
/*  DESCRIPTION                                                           */
321
/*                                                                        */
322
/*    Internal help function that hangles 90, 180 and 270 degree pixelmap */
323
/*    rotation.                                                           */
324
/*                                                                        */
325
/*  INPUT                                                                 */
326
/*                                                                        */
327
/*    context                               Drawing context               */
328
/*    xpos                                  x-coord of top-left draw point*/
329
/*    ypos                                  y-coord of top-left draw point*/
330
/*    pixelmap                              Pointer to GX_PIXELMAP struct */
331
/*    angle                                 The angle to rotate           */
332
/*    cx                                    x-coord of rotate center      */
333
/*    cy                                    y-coord of rotate center      */
334
/*                                                                        */
335
/*  OUTPUT                                                                */
336
/*                                                                        */
337
/*    status                                Completion status             */
338
/*                                                                        */
339
/*  CALLS                                                                 */
340
/*                                                                        */
341
/*    [gx_display_driver_pixel_blend]       Display driver basic pixel    */
342
/*                                             blend function             */
343
/*                                                                        */
344
/*  CALLED BY                                                             */
345
/*                                                                        */
346
/*    GUIX Internal Code                                                  */
347
/*                                                                        */
348
/**************************************************************************/
349
12
static VOID _gx_display_driver_4444argb_pixelmap_simple_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
350
                                                               INT angle, INT cx, INT cy)
351
{
352
USHORT       *get;
353
INT           width;
354
INT           height;
355
INT           x;
356
INT           y;
357
GX_RECTANGLE *clip;
358
INT           newxpos;
359
INT           newypos;
360
USHORT        color;
361
VOID          (*blend_func)(GX_DRAW_CONTEXT *context, INT x1, INT y1, GX_COLOR color, GX_UBYTE alpha);
362
363
12
    blend_func = context -> gx_draw_context_display -> gx_display_driver_pixel_blend;
364
12
    clip = context -> gx_draw_context_clip;
365
366
12
    if (angle == 90)
367
    {
368
4
        width = pixelmap -> gx_pixelmap_height;
369
4
        height = pixelmap -> gx_pixelmap_width;
370
371
4
        newxpos = xpos + cx - (width - 1 - cy);
372
4
        newypos = ypos + cy - cx;
373
374
865
        for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
375
        {
376
147567
            for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
377
            {
378
146706
                get = (USHORT *)pixelmap -> gx_pixelmap_data;
379
146706
                get += (width - 1 - x) * height;
380
146706
                get += y;
381
146706
                color = *get;
382
146706
                blend_func(context, x + newxpos, y + newypos, color, 0xff);
383
            }
384
        }
385
    }
386
8
    else if (angle == 180)
387
    {
388
389
4
        width = pixelmap -> gx_pixelmap_width;
390
4
        height = pixelmap -> gx_pixelmap_height;
391
392
4
        newxpos = xpos + cx - (width - 1 - cx);
393
4
        newypos = ypos + cy - (height - 1 - cy);
394
395
541
        for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
396
        {
397
106445
            for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
398
            {
399
105908
                get = (USHORT *)pixelmap -> gx_pixelmap_data;
400
105908
                get += (height - 1 - y) * width;
401
105908
                get += width - 1 - x;
402
105908
                color = *get;
403
105908
                blend_func(context, x + newxpos, y + newypos, color, 0xff);
404
            }
405
        }
406
    }
407
    else
408
    {
409
4
        height = pixelmap -> gx_pixelmap_width;
410
411
4
        newxpos = xpos + cx - cy;
412
4
        newypos = ypos + cx - (height - 1 - cy);
413
414
583
        for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
415
        {
416
106245
            for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
417
            {
418
105666
                get = (USHORT *)pixelmap -> gx_pixelmap_data;
419
105666
                get += x * height;
420
105666
                get += height - 1 - y;
421
105666
                color = *get;
422
105666
                blend_func(context, x + newxpos, y + newypos, color, 0xff);
423
            }
424
        }
425
    }
426
12
}
427
428
/**************************************************************************/
429
/*                                                                        */
430
/*  FUNCTION                                               RELEASE        */
431
/*                                                                        */
432
/*    _gx_display_driver_4444argb_pixelmap_rotate         PORTABLE C      */
433
/*                                                           6.1          */
434
/*  AUTHOR                                                                */
435
/*                                                                        */
436
/*    Kenneth Maxwell, Microsoft Corporation                              */
437
/*                                                                        */
438
/*  DESCRIPTION                                                           */
439
/*                                                                        */
440
/*    This service rotates an 4444argb format pixelmap to canvas memory.  */
441
/*                                                                        */
442
/*  INPUT                                                                 */
443
/*                                                                        */
444
/*    context                               Drawing context               */
445
/*    xpos                                  x-coord of top-left draw point*/
446
/*    ypos                                  y-coord of top-left draw point*/
447
/*    pixelmap                              Pointer to GX_PIXELMAP struct */
448
/*    angle                                 The angle to rotate           */
449
/*    rot_cx                                x-coord of rotating center.   */
450
/*    rot_cy                                y-coord of rotationg center.  */
451
/*                                                                        */
452
/*  OUTPUT                                                                */
453
/*                                                                        */
454
/*    status                                Completion status             */
455
/*                                                                        */
456
/*  CALLS                                                                 */
457
/*                                                                        */
458
/*    _gx_display_driver_4444argb_pixelmap_simple_rotate                  */
459
/*                                          Rotate 4444argb format        */
460
/*                                            pixlemap in simple case     */
461
/*    _gx_display_driver_4444argb_pixelmap_rotate                         */
462
/*                                          Rotate 4444argb format        */
463
/*                                            pixelmap in generate case   */
464
/*                                                                        */
465
/*  CALLED BY                                                             */
466
/*                                                                        */
467
/*    Application Code                                                    */
468
/*    GUIX Internal Code                                                  */
469
/*                                                                        */
470
/**************************************************************************/
471
1438
VOID _gx_display_driver_4444argb_pixelmap_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
472
                                                 INT angle, INT rot_cx, INT rot_cy)
473
{
474
1438
    switch (pixelmap -> gx_pixelmap_format)
475
    {
476
1437
    case GX_COLOR_FORMAT_4444ARGB:
477
1437
        if (angle % 90 == 0)
478
        {
479
            /* Simple angle rotate: 90 degree, 180 degree and 270 degree.  */
480
12
            _gx_display_driver_4444argb_pixelmap_simple_rotate(context, xpos, ypos, pixelmap, angle, rot_cx, rot_cy);
481
        }
482
        else
483
        {
484
1425
            _gx_display_driver_4444argb_pixelmap_general_rotate(context, xpos, ypos, pixelmap, angle, rot_cx, rot_cy);
485
        }
486
1437
        break;
487
    }
488
489
1438
    return;
490
}
491