GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_multi_line_text_view_text_draw.c Lines: 76 76 100.0 %
Date: 2026-03-06 19:21:09 Branches: 35 35 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
/**   Multi Line Text View Management (Multi Line Text View)              */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "gx_api.h"
28
#include "gx_system.h"
29
#include "gx_canvas.h"
30
#include "gx_context.h"
31
#include "gx_multi_line_text_view.h"
32
#include "gx_utility.h"
33
#include "gx_widget.h"
34
#include "gx_window.h"
35
#include "gx_scrollbar.h"
36
37
/**************************************************************************/
38
/*                                                                        */
39
/*  FUNCTION                                               RELEASE        */
40
/*                                                                        */
41
/*    _gx_multi_line_text_view_draw                       PORTABLE C      */
42
/*                                                           6.1          */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    Kenneth Maxwell, Microsoft Corporation                              */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function draws text for a multi-line-text-view widget.         */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    text_view                              Multi-line_text_view widget  */
54
/*                                             control block              */
55
/*    text_color                             ID of text color             */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    None                                                                */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    _gx_context_line_color_set            Set the context color         */
64
/*    _gx_context_font_get                  Get font associated with the  */
65
/*                                            specified ID                */
66
/*    _gx_context_font_set                  Set the context font          */
67
/*    _gx_context_brush_width_set           Set the brush width           */
68
/*    _gx_multi_line_text_view_visible_rows_compute                       */
69
/*                                          Calculate visible rows        */
70
/*    _gx_multi_line_text_view_string_total_rows_compute                  */
71
/*                                          Calculate total rows for input*/
72
/*                                            string                      */
73
/*    _gx_utility_rectangle_resize          Offset rectangle by specified */
74
/*                                            value                       */
75
/*    _gx_utility_rectangle_overlap_detect  Detect rectangle overlaps     */
76
/*    _gx_utility_string_length_check       Test string length            */
77
/*    _gx_system_string_get                 Get string by specified id    */
78
/*    _gx_system_private_string_get         Get string pointer in         */
79
/*                                            dynamically copied string   */
80
/*                                            buffer                      */
81
/*    _gx_multi_line_text_view_paragraph_start_get                        */
82
/*                                          Get start index of a paragraph*/
83
/*    _gx_utility_bidi_paragraph_reorder    Reorder bidi text for display */
84
/*    _gx_system_string_width_get           Get string width              */
85
/*    _gx_canvas_text_draw                  Draw the text                 */
86
/*    _gx_canvas_drawing_initiate           Initiate a drawing context    */
87
/*    _gx_canvas_drawing_complete           Complete a drawing            */
88
/*                                                                        */
89
/*  CALLED BY                                                             */
90
/*                                                                        */
91
/*    Application Code                                                    */
92
/*    GUIX Internal Code                                                  */
93
/*                                                                        */
94
/**************************************************************************/
95
24137
VOID  _gx_multi_line_text_view_text_draw(GX_MULTI_LINE_TEXT_VIEW *text_view, GX_RESOURCE_ID text_color)
96
{
97
INT           index;
98
INT           line_height;
99
GX_STRING     string;
100
GX_STRING     line_string;
101
INT           x_pos;
102
INT           y_pos;
103
GX_RECTANGLE  client;
104
GX_RECTANGLE  draw_area;
105
GX_CANVAS    *canvas;
106
INT           first_visible_line;
107
INT           last_visible_line;
108
UINT          line_start_index;
109
UINT          line_end_index;
110
UINT          line_cache_start;
111
GX_VALUE      text_width;
112
GX_VALUE      space_width;
113
GX_VALUE      client_width;
114
GX_FONT      *font;
115
GX_SCROLLBAR *scroll;
116
117
#if defined(GX_DYNAMIC_BIDI_TEXT_SUPPORT)
118
GX_BIDI_RESOLVED_TEXT_INFO *next = GX_NULL;
119
UINT                        bidi_text_line_index = 0;
120
#endif
121
122
24137
    _gx_context_line_color_set(text_color);
123
24137
    _gx_context_font_get(text_view -> gx_multi_line_text_view_font_id, &font);
124
24137
    _gx_context_font_set(text_view -> gx_multi_line_text_view_font_id);
125
24137
    _gx_context_brush_width_set(1);
126
127
24137
    _gx_window_scrollbar_find((GX_WINDOW *)text_view, GX_TYPE_VERTICAL_SCROLL, &scroll);
128
129
24137
    if (text_view -> gx_multi_line_text_view_line_index_old)
130
    {
131
132
        /* Get visible rows. */
133
563
        _gx_multi_line_text_view_visible_rows_compute(text_view);
134
135
        /* Calculate text total rows. */
136
563
        _gx_multi_line_text_view_string_total_rows_compute(text_view);
137
138
563
        if (scroll)
139
        {
140
            /* Reset scrollbar.  */
141
90
            _gx_scrollbar_reset(scroll, GX_NULL);
142
        }
143
        else
144
        {
145
473
            if (text_view -> gx_multi_line_text_view_text_total_rows >
146
473
                text_view -> gx_multi_line_text_view_cache_size)
147
            {
148
                /* Update line cache. */
149
4
                _gx_multi_line_text_view_line_cache_update(text_view);
150
            }
151
        }
152
    }
153
154
    /* Is there a string and font?  */
155
24137
    if ((text_view -> gx_multi_line_text_view_text.gx_string_length <= 0)  ||
156
18590
        font == GX_NULL)
157
    {
158
5588
        return;
159
    }
160
161
    /* Pickup text height. */
162
18568
    line_height = font -> gx_font_line_height + text_view -> gx_multi_line_text_view_line_space;
163
164
18568
    if (!line_height)
165
    {
166
19
        return;
167
    }
168
169
    /* pick up current canvas */
170
18549
    canvas = _gx_system_current_draw_context -> gx_draw_context_canvas;
171
172
    /* Pick up client area.  */
173
18549
    client = text_view -> gx_window_client;
174
175
    /* Offset client area by the size of whitespace.  */
176
18549
    _gx_utility_rectangle_resize(&client, (GX_VALUE)(-text_view -> gx_multi_line_text_view_whitespace));
177
178
    /* check for auto-scrolling vertically centered text */
179
18549
    if (text_view -> gx_widget_type == GX_TYPE_MULTI_LINE_TEXT_VIEW &&
180
9058
        scroll == GX_NULL &&
181
8242
        (text_view -> gx_widget_style & GX_STYLE_VALIGN_CENTER) == GX_STYLE_VALIGN_CENTER)
182
    {
183
4
        space_width = (GX_VALUE)(client.gx_rectangle_bottom - client.gx_rectangle_top);
184
4
        space_width = (GX_VALUE)((INT)space_width - (INT)((INT)text_view -> gx_multi_line_text_view_text_total_rows * line_height));
185
4
        text_view -> gx_multi_line_text_view_text_scroll_shift = (space_width >> 1);
186
    }
187
188
18549
    _gx_utility_rectangle_overlap_detect(&_gx_system_current_draw_context -> gx_draw_context_dirty, &client, &draw_area);
189
18549
    _gx_canvas_drawing_initiate(canvas, (GX_WIDGET *)text_view, &draw_area);
190
191
    /* Compute the start displaying position of pixels in x direction and y direction. */
192
18549
    y_pos = client.gx_rectangle_top;
193
18549
    y_pos += text_view -> gx_multi_line_text_view_text_scroll_shift;
194
18549
    y_pos += (text_view -> gx_multi_line_text_view_line_space >> 1);
195
196
18549
    line_string.gx_string_ptr = " ";
197
18549
    line_string.gx_string_length = 1;
198
199
18549
    _gx_system_string_width_get_ext(font, &line_string, &space_width);
200
201
18549
    first_visible_line = ((-text_view -> gx_multi_line_text_view_text_scroll_shift)) / line_height;
202
203
18549
    if (first_visible_line < 0)
204
    {
205
4
        first_visible_line = 0;
206
    }
207
208
18549
    last_visible_line = first_visible_line + (INT)(text_view -> gx_multi_line_text_view_text_visible_rows);
209
210
18549
    if (last_visible_line > (INT)(text_view -> gx_multi_line_text_view_text_total_rows - 1))
211
    {
212
14589
        last_visible_line = (INT)(text_view -> gx_multi_line_text_view_text_total_rows - 1);
213
    }
214
215
18549
    if (text_view -> gx_multi_line_text_view_text_id)
216
    {
217
2862
        _gx_widget_string_get_ext((GX_WIDGET *)text_view, text_view -> gx_multi_line_text_view_text_id, &string);
218
    }
219
    else
220
    {
221
15687
        _gx_system_private_string_get(&text_view -> gx_multi_line_text_view_text, &string, text_view -> gx_widget_style);
222
    }
223
224
18549
    y_pos += (INT)(first_visible_line * line_height);
225
226
115503
    for (index = first_visible_line; index <= last_visible_line; index++)
227
    {
228
#if defined(GX_DYNAMIC_BIDI_TEXT_SUPPORT)
229
        if (_gx_system_bidi_text_enabled)
230
        {
231
            line_string.gx_string_ptr = GX_NULL;
232
            line_string.gx_string_length = 0;
233
234
            if (!next)
235
            {
236
                next = text_view -> gx_multi_line_text_view_bidi_resolved_text_info;
237
            }
238
239
            while (next)
240
            {
241
                if (bidi_text_line_index + next -> gx_bidi_resolved_text_info_total_lines > (UINT)index)
242
                {
243
                    /* Get line string. */
244
                    if (next -> gx_bidi_resolved_text_info_text)
245
                    {
246
                        line_string = next -> gx_bidi_resolved_text_info_text[(UINT)index - bidi_text_line_index];
247
                    }
248
                    break;
249
                }
250
251
                bidi_text_line_index += next -> gx_bidi_resolved_text_info_total_lines;
252
                next = next -> gx_bidi_resolved_text_info_next;
253
            }
254
        }
255
        else
256
        {
257
#endif /* defined(GX_DYNAMIC_BIDI_TEXT_SUPPORT) */
258
96954
            line_cache_start = text_view -> gx_multi_line_text_view_first_cache_line;
259
96954
            line_start_index = text_view -> gx_multi_line_text_view_line_index[index - (INT)line_cache_start];
260
261
96954
            if ((INT)(index - (INT)line_cache_start) >= (INT)(text_view -> gx_multi_line_text_view_cache_size - 1))
262
            {
263
15120
                line_end_index = text_view -> gx_multi_line_text_view_text.gx_string_length;
264
            }
265
            else
266
            {
267
81834
                line_end_index = text_view -> gx_multi_line_text_view_line_index[index - (INT)(line_cache_start) + 1];
268
            }
269
270
            /* Get line string. */
271
96954
            line_string.gx_string_ptr = string.gx_string_ptr + line_start_index;
272
96954
            line_string.gx_string_length = line_end_index - line_start_index;
273
#if defined(GX_DYNAMIC_BIDI_TEXT_SUPPORT)
274
        }
275
#endif /* defined(GX_DYNAMIC_BIDI_TEXT_SUPPORT) */
276
277
278
96954
        switch (text_view -> gx_widget_style & GX_STYLE_TEXT_ALIGNMENT_MASK)
279
        {
280
12114
        case GX_STYLE_TEXT_RIGHT:
281
12114
            _gx_system_string_width_get_ext(font, &line_string, &text_width);
282
13042
            while (text_width > (client.gx_rectangle_right - client.gx_rectangle_left - 2))
283
            {
284
928
                text_width = (GX_VALUE)(text_width - space_width);
285
            }
286
12114
            x_pos = client.gx_rectangle_right - 1;
287
12114
            x_pos = (GX_VALUE)(x_pos - text_width);
288
12114
            break;
289
71507
        case GX_STYLE_TEXT_LEFT:
290
71507
            x_pos = client.gx_rectangle_left + 1;
291
71507
            break;
292
13333
        case GX_STYLE_TEXT_CENTER:
293
        default:
294
13333
            _gx_system_string_width_get_ext(font, &line_string, &text_width);
295
13333
            client_width = (GX_VALUE)(client.gx_rectangle_right - client.gx_rectangle_left + 1);
296
14173
            while (text_width > (client_width - 3))
297
            {
298
840
                text_width = (GX_VALUE)(text_width - space_width);
299
            }
300
13333
            x_pos = (GX_VALUE)(client.gx_rectangle_left + ((client_width - text_width) / 2));
301
13333
            break;
302
        }
303
304
        /* Draw the text. */
305
96954
        _gx_canvas_text_draw_ext((GX_VALUE)x_pos, (GX_VALUE)y_pos, &line_string);
306
96954
        y_pos += line_height;
307
    }
308
309
18549
    _gx_canvas_drawing_complete(canvas, GX_FALSE);
310
}
311