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 /** Progress Bar Management (Radial Progress Bar) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23 /* Include necessary system files. */
24
25 #include "gx_api.h"
26 #include "gx_context.h"
27 #include "gx_widget.h"
28 #include "gx_canvas.h"
29 #include "gx_utility.h"
30 #include "gx_radial_progress_bar.h"
31 #include "gx_system.h"
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _gx_radial_progress_bar_background_draw PORTABLE C */
38 /* 6.1.8 */
39 /* AUTHOR */
40 /* */
41 /* Kenneth Maxwell, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This service draws a radial progress bar background. */
46 /* */
47 /* INPUT */
48 /* */
49 /* progress_bar Radial Progress Bar control */
50 /* block */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* _gx_widget_background_draw */
59 /* _gx_context_brush_get */
60 /* _gx_context_line_color_set */
61 /* _gx_context_brush_width_set */
62 /* _gx_canvas_circle_draw */
63 /* _gx_canvas_arc_draw */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* Application Code */
68 /* GUIX Internal Code */
69 /* */
70 /* RELEASE HISTORY */
71 /* */
72 /* DATE NAME DESCRIPTION */
73 /* */
74 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
75 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
76 /* resulting in version 6.1 */
77 /* 08-02-2021 Ting Zhu Modified comment(s), */
78 /* supported no background */
79 /* radial track mode, */
80 /* resulting in version 6.1.8 */
81 /* */
82 /**************************************************************************/
_gx_radial_progress_bar_background_draw(GX_RADIAL_PROGRESS_BAR * progress_bar)83 VOID _gx_radial_progress_bar_background_draw(GX_RADIAL_PROGRESS_BAR *progress_bar)
84 {
85 GX_RADIAL_PROGRESS_BAR_INFO *info;
86 GX_VALUE xcenter;
87 GX_VALUE ycenter;
88 GX_BRUSH *brush;
89 GX_RECTANGLE *size;
90
91 #if defined(GX_BRUSH_ALPHA_SUPPORT)
92 GX_UBYTE brush_alpha;
93 GX_RECTANGLE dirty;
94 GX_PIXELMAP map;
95 VOID *canvas_memory;
96 INT canvas_size;
97 GX_DISPLAY *display;
98 GX_CANVAS *canvas;
99 GX_VALUE old_xpos = 0;
100 GX_VALUE old_ypos = 0;
101 #endif
102
103 _gx_context_brush_get(&brush);
104
105 #if defined(GX_BRUSH_ALPHA_SUPPORT)
106 brush_alpha = brush -> gx_brush_alpha;
107 if (brush_alpha == 0)
108 {
109 return;
110 }
111
112 if (brush_alpha != GX_ALPHA_VALUE_OPAQUE)
113 {
114 size = &progress_bar -> gx_widget_size;
115 map.gx_pixelmap_width = (GX_VALUE)(size -> gx_rectangle_right - size -> gx_rectangle_left + 1);
116 map.gx_pixelmap_height = (GX_VALUE)(size -> gx_rectangle_bottom - size -> gx_rectangle_top + 1);
117
118 display = _gx_system_current_draw_context -> gx_draw_context_display;
119
120 if ((progress_bar -> gx_radial_progress_bar_canvas.gx_canvas_id != GX_CANVAS_ID) &&
121 _gx_system_memory_allocator)
122 {
123
124 /* Pixelmap width and height is GX_VALUE type, overflow cannot occur. */
125 canvas_size = display -> gx_display_driver_row_pitch_get((USHORT)map.gx_pixelmap_width);
126 canvas_size *= map.gx_pixelmap_height;
127
128 canvas_memory = _gx_system_memory_allocator((ULONG)canvas_size);
129
130 if (canvas_memory)
131 {
132 _gx_canvas_create(&progress_bar -> gx_radial_progress_bar_canvas, "progress_bar_canvas",
133 display, GX_CANVAS_SIMPLE, (UINT)map.gx_pixelmap_width,
134 (UINT)map.gx_pixelmap_height, (GX_COLOR *)canvas_memory, (ULONG)canvas_size);
135 }
136 }
137
138 if (progress_bar -> gx_radial_progress_bar_canvas.gx_canvas_id == GX_CANVAS_ID)
139 {
140 /* Remove resize notify temporary. */
141 progress_bar -> gx_widget_status &= ~GX_STATUS_RESIZE_NOTIFY;
142
143 old_xpos = size -> gx_rectangle_left;
144 old_ypos = size -> gx_rectangle_top;
145
146 if (old_xpos || old_ypos)
147 {
148 _gx_widget_shift((GX_WIDGET *)progress_bar, (GX_VALUE)(-old_xpos), (GX_VALUE)(-old_ypos), GX_FALSE);
149 }
150
151 canvas = _gx_system_current_draw_context -> gx_draw_context_canvas;
152 dirty = canvas -> gx_canvas_dirty_area;
153 _gx_utility_rectangle_shift(&dirty, (GX_VALUE)(-old_xpos), (GX_VALUE)(-old_ypos));
154 _gx_utility_rectangle_overlap_detect(&dirty, &progress_bar -> gx_widget_size, &dirty);
155
156 _gx_canvas_drawing_initiate(&progress_bar -> gx_radial_progress_bar_canvas, GX_NULL, &dirty);
157
158 if (progress_bar -> gx_widget_status & GX_STATUS_TRANSPARENT)
159 {
160 xcenter = canvas -> gx_canvas_display_offset_x;
161 ycenter = canvas -> gx_canvas_display_offset_y;
162 _gx_canvas_offset_set(canvas, (GX_VALUE)(-old_xpos), (GX_VALUE)(-old_ypos));
163 display -> gx_display_driver_canvas_copy(canvas, &progress_bar -> gx_radial_progress_bar_canvas);
164 _gx_canvas_offset_set(canvas, xcenter, ycenter);
165 }
166
167 _gx_context_brush_get(&brush);
168 }
169 }
170
171 #endif
172
173 /* Draw progress bar background. */
174 _gx_widget_background_draw((GX_WIDGET *)progress_bar);
175
176 /* Draw circular track. */
177 info = &progress_bar -> gx_radial_progress_bar_info;
178
179 size = &progress_bar -> gx_widget_size;
180
181 xcenter = (GX_VALUE)(size -> gx_rectangle_right + size -> gx_rectangle_left);
182 xcenter >>= 1;
183
184 ycenter = (GX_VALUE)(size -> gx_rectangle_bottom + size -> gx_rectangle_top);
185 ycenter >>= 1;
186
187 brush -> gx_brush_style &= (ULONG)(~GX_BRUSH_SOLID_FILL);
188
189 if (progress_bar -> gx_widget_style & GX_STYLE_RADIAL_PROGRESS_ALIAS)
190 {
191 brush -> gx_brush_style |= GX_BRUSH_ALIAS;
192 }
193
194 if (progress_bar -> gx_widget_style & GX_STYLE_RADIAL_PROGRESS_ROUND)
195 {
196 brush -> gx_brush_style |= GX_BRUSH_ROUND;
197 }
198
199 if (!(progress_bar -> gx_widget_style & GX_STYLE_RADIAL_PROGRESS_NO_BACKTRACK))
200 {
201 _gx_context_line_color_set(info -> gx_radial_progress_bar_info_normal_brush_color);
202 _gx_context_brush_width_set((UINT)(info -> gx_radial_progress_bar_info_normal_brush_width));
203
204 _gx_canvas_circle_draw(xcenter, ycenter, (UINT)(info -> gx_radial_progress_bar_info_radius));
205 }
206
207 if (info -> gx_radial_progress_bar_info_current_val != 0)
208 {
209 _gx_context_line_color_set(info -> gx_radial_progress_bar_info_selected_brush_color);
210 brush -> gx_brush_width = info -> gx_radial_progress_bar_info_selected_brush_width;
211
212 if (info -> gx_radial_progress_bar_info_current_val > 0)
213 {
214 _gx_canvas_arc_draw(xcenter, ycenter,
215 (UINT)(info -> gx_radial_progress_bar_info_radius),
216 info -> gx_radial_progress_bar_info_anchor_val,
217 info -> gx_radial_progress_bar_info_current_val + info -> gx_radial_progress_bar_info_anchor_val);
218 }
219 else
220 {
221 _gx_canvas_arc_draw(xcenter, ycenter,
222 (UINT)(info -> gx_radial_progress_bar_info_radius),
223 info -> gx_radial_progress_bar_info_current_val + info -> gx_radial_progress_bar_info_anchor_val,
224 info -> gx_radial_progress_bar_info_anchor_val);
225 }
226 }
227
228 #if defined(GX_BRUSH_ALPHA_SUPPORT)
229 if ((brush_alpha != GX_ALPHA_VALUE_OPAQUE) &&
230 (progress_bar -> gx_radial_progress_bar_canvas.gx_canvas_id == GX_CANVAS_ID))
231 {
232 if (old_xpos || old_ypos)
233 {
234 _gx_widget_shift((GX_WIDGET *)progress_bar, old_xpos, old_ypos, GX_FALSE);
235 }
236
237 _gx_canvas_pixelmap_get(&map);
238 _gx_canvas_drawing_complete(&progress_bar -> gx_radial_progress_bar_canvas, GX_FALSE);
239 _gx_canvas_pixelmap_blend(old_xpos, old_ypos, &map, brush_alpha);
240
241 /* Added resize notification back. */
242 progress_bar -> gx_widget_status |= GX_STATUS_RESIZE_NOTIFY;
243 }
244 #endif
245 }
246
247