1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** GUIX Component                                                        */
17 /**                                                                       */
18 /**   Canvas Management (Canvas)                                          */
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_utility.h"
30 #include "gx_canvas.h"
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _gx_canvas_rectangle_fill                           PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Kenneth Maxwell, Microsoft Corporation                              */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    Support function for gx_canvas_rectangle_draw, draw a wide border   */
45 /*    by drawing a filled rectangle.                                      */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    rectangle                             Rectangle specification       */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    status                                Completion status             */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    _gx_utility_rectangle_overlap_detect  Detect rectangle overlap      */
58 /*    _gx_canvas_line_draw                  Draw a line                   */
59 /*    [gx_display_driver_horizontal_line_draw]                            */
60 /*                                          Display driver horizontal     */
61 /*                                            line draw routine           */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    _gx_canvas_rectangle_draw                                           */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
72 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
73 /*                                            resulting in version 6.1    */
74 /*                                                                        */
75 /**************************************************************************/
_gx_canvas_rectangle_fill(GX_RECTANGLE * rectangle,GX_COLOR fill_color)76 static UINT  _gx_canvas_rectangle_fill(GX_RECTANGLE *rectangle, GX_COLOR fill_color)
77 {
78 GX_DRAW_CONTEXT *context;
79 GX_DISPLAY      *display;
80 GX_RECTANGLE     fill_rect;
81 GX_RECTANGLE     bound;
82 GX_VIEW         *view;
83 GX_VALUE         rectangle_height;
84 
85     /* pick up current drawing context */
86     context = _gx_system_current_draw_context;
87 
88     /* Check to see if the rectangle overlaps the dirty area.  */
89     if (!_gx_utility_rectangle_overlap_detect(rectangle, &context -> gx_draw_context_dirty, &bound))
90     {
91         /* nothing to draw, return */
92         return GX_SUCCESS;
93     }
94 
95     /* pick up current display driver */
96     display = context -> gx_draw_context_display;
97 
98 
99     /* test to determine if the bounding rectangle overlaps the region we are allowed to draw
100        into. For each view that overlaps the bounding rectangle, do some drawing.
101      */
102     view = context -> gx_draw_context_view_head;
103 
104     while (view)
105     {
106         if (_gx_utility_rectangle_overlap_detect(&bound, &view -> gx_view_rectangle, &fill_rect))
107         {
108             /* Pickup the height.  */
109             rectangle_height = (GX_VALUE)(fill_rect.gx_rectangle_bottom - fill_rect.gx_rectangle_top + 1);
110             context -> gx_draw_context_clip = &fill_rect;
111 
112             display -> gx_display_driver_horizontal_line_draw(context,
113                                                               fill_rect.gx_rectangle_left,
114                                                               fill_rect.gx_rectangle_right,
115                                                               fill_rect.gx_rectangle_top,
116                                                               rectangle_height, fill_color);
117         }
118         view = view -> gx_view_next;
119     }
120 
121     /* Return successful completion.  */
122     return(GX_SUCCESS);
123 }
124 
125 
126 
127 /**************************************************************************/
128 /*                                                                        */
129 /*  FUNCTION                                               RELEASE        */
130 /*                                                                        */
131 /*    _gx_canvas_rectangle_draw                           PORTABLE C      */
132 /*                                                           6.1          */
133 /*  AUTHOR                                                                */
134 /*                                                                        */
135 /*    Kenneth Maxwell, Microsoft Corporation                              */
136 /*                                                                        */
137 /*  DESCRIPTION                                                           */
138 /*                                                                        */
139 /*    This draws the specified rectangle on the current context.          */
140 /*                                                                        */
141 /*  INPUT                                                                 */
142 /*                                                                        */
143 /*    rectangle                             Rectangle specification       */
144 /*                                                                        */
145 /*  OUTPUT                                                                */
146 /*                                                                        */
147 /*    status                                Completion status             */
148 /*                                                                        */
149 /*  CALLS                                                                 */
150 /*                                                                        */
151 /*    _gx_utility_rectangle_overlap_detect  Detect rectangle overlap      */
152 /*    _gx_canvas_line_draw                  Draw a line                   */
153 /*    _gx_canvas_rectangle_draw             Draw a rectangle              */
154 /*    [gx_display_driver_horizontal_line_draw]                            */
155 /*                                          Display driver horizontal     */
156 /*                                            line draw routine           */
157 /*                                                                        */
158 /*  CALLED BY                                                             */
159 /*                                                                        */
160 /*    _gx_scrollbar_draw                                                  */
161 /*    _gx_slider_needle_draw                                              */
162 /*    _gx_widget_border_draw                                              */
163 /*                                                                        */
164 /*  RELEASE HISTORY                                                       */
165 /*                                                                        */
166 /*    DATE              NAME                      DESCRIPTION             */
167 /*                                                                        */
168 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
169 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
170 /*                                            resulting in version 6.1    */
171 /*                                                                        */
172 /**************************************************************************/
_gx_canvas_rectangle_draw(GX_RECTANGLE * rectangle)173 UINT  _gx_canvas_rectangle_draw(GX_RECTANGLE *rectangle)
174 {
175 GX_DRAW_CONTEXT *context;
176 GX_DISPLAY      *display;
177 GX_RECTANGLE     fill_rect;
178 GX_RECTANGLE     bound;
179 GX_VIEW         *view;
180 GX_COLOR         fill_color;
181 GX_VALUE         rectangle_height;
182 GX_VALUE         brush_width;
183 
184     /* pick up current drawing context */
185     context = _gx_system_current_draw_context;
186 
187     /* Check to see if the rectangle overlaps the dirty area.  */
188     if (!_gx_utility_rectangle_overlap_detect(rectangle, &context -> gx_draw_context_dirty, &bound))
189     {
190         /* nothing to draw, return */
191         return GX_SUCCESS;
192     }
193 
194     /* pick up current display driver */
195     display = context -> gx_draw_context_display;
196 
197     /* if the rectangle has a border, call either the line function (for a single-pixel border)
198        or the rectangle functions (for a wide border), then reduce the size of the rectangle
199        we are drawing here
200      */
201 
202     fill_rect = *rectangle;
203     brush_width = context -> gx_draw_context_brush.gx_brush_width;
204 
205     switch (brush_width)
206     {
207     case 0:
208         /* no border */
209         break;
210 
211     case 1:
212         /* thin border */
213         _gx_canvas_line_draw(rectangle -> gx_rectangle_left,
214                              (GX_VALUE)(rectangle -> gx_rectangle_top + 1),
215                              rectangle -> gx_rectangle_left,
216                              (GX_VALUE)(rectangle -> gx_rectangle_bottom - 1));
217 
218         _gx_canvas_line_draw(rectangle -> gx_rectangle_right,
219                              (GX_VALUE)(rectangle -> gx_rectangle_top + 1),
220                              rectangle -> gx_rectangle_right,
221                              (GX_VALUE)(rectangle -> gx_rectangle_bottom - 1));
222 
223         _gx_canvas_line_draw(rectangle -> gx_rectangle_left,
224                              rectangle -> gx_rectangle_top,
225                              rectangle -> gx_rectangle_right,
226                              rectangle -> gx_rectangle_top);
227 
228         _gx_canvas_line_draw(rectangle -> gx_rectangle_left,
229                              rectangle -> gx_rectangle_bottom,
230                              rectangle -> gx_rectangle_right,
231                              rectangle -> gx_rectangle_bottom);
232 
233         fill_rect.gx_rectangle_top = (GX_VALUE)(fill_rect.gx_rectangle_top + 1);
234         fill_rect.gx_rectangle_bottom = (GX_VALUE)(fill_rect.gx_rectangle_bottom - 1);
235         fill_rect.gx_rectangle_left = (GX_VALUE)(fill_rect.gx_rectangle_left + 1);
236         fill_rect.gx_rectangle_right = (GX_VALUE)(fill_rect.gx_rectangle_right - 1);
237         break;
238 
239     default:
240 
241         /* draw the wide top line */
242         fill_rect.gx_rectangle_bottom = (GX_VALUE)(fill_rect.gx_rectangle_top + brush_width - 1);
243         _gx_canvas_rectangle_fill(&fill_rect, context -> gx_draw_context_brush.gx_brush_line_color);
244 
245         /* draw the wide bottom line */
246         fill_rect.gx_rectangle_bottom = rectangle -> gx_rectangle_bottom;
247         fill_rect.gx_rectangle_top = (GX_VALUE)(fill_rect.gx_rectangle_bottom - brush_width + 1);
248         _gx_canvas_rectangle_fill(&fill_rect, context -> gx_draw_context_brush.gx_brush_line_color);
249 
250         /* draw the wide left side */
251         fill_rect.gx_rectangle_top = (GX_VALUE)(rectangle -> gx_rectangle_top + brush_width);
252         fill_rect.gx_rectangle_bottom = (GX_VALUE)(fill_rect.gx_rectangle_bottom - brush_width);
253         fill_rect.gx_rectangle_right = (GX_VALUE)(fill_rect.gx_rectangle_left + brush_width - 1);
254         _gx_canvas_rectangle_fill(&fill_rect, context -> gx_draw_context_brush.gx_brush_line_color);
255 
256         /* draw the wide right side */
257         fill_rect.gx_rectangle_right = rectangle -> gx_rectangle_right;
258         fill_rect.gx_rectangle_left = (GX_VALUE)(fill_rect.gx_rectangle_right - brush_width + 1);
259         _gx_canvas_rectangle_fill(&fill_rect, context -> gx_draw_context_brush.gx_brush_line_color);
260 
261         /* subtract the border from the fill_rect */
262         fill_rect.gx_rectangle_bottom = (GX_VALUE)(rectangle -> gx_rectangle_bottom - brush_width);
263         fill_rect.gx_rectangle_top = (GX_VALUE)(rectangle -> gx_rectangle_top + brush_width);
264         fill_rect.gx_rectangle_left = (GX_VALUE)(rectangle -> gx_rectangle_left + brush_width);
265         fill_rect.gx_rectangle_right = (GX_VALUE)(rectangle -> gx_rectangle_right - brush_width);
266     }
267 
268     if (context -> gx_draw_context_brush.gx_brush_width != 0)
269     {
270         /* Check again, after reducing size, to see if the rectangle overlaps the dirty area.  */
271         if (!_gx_utility_rectangle_overlap_detect(&fill_rect, &context -> gx_draw_context_dirty, &bound))
272         {
273             /* nothing to draw, return */
274             return GX_SUCCESS;
275         }
276     }
277 
278     if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_SOLID_FILL) == 0)
279     {
280         return GX_SUCCESS;
281     }
282 
283     /* test to determine if the bounding rectangle overlaps the region we are allowed to draw
284        into. For each view that overlaps the bounding rectangle, do some drawing.
285      */
286     view = context -> gx_draw_context_view_head;
287 
288     /* save the fill color for later */
289     fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
290 
291     while (view)
292     {
293         if (_gx_utility_rectangle_overlap_detect(&bound, &view -> gx_view_rectangle, &fill_rect))
294         {
295             /* Pickup the height.  */
296             rectangle_height = (GX_VALUE)(fill_rect.gx_rectangle_bottom - fill_rect.gx_rectangle_top + 1);
297             context -> gx_draw_context_clip = &fill_rect;
298 
299             display -> gx_display_driver_horizontal_line_draw(context,
300                                                               fill_rect.gx_rectangle_left,
301                                                               fill_rect.gx_rectangle_right,
302                                                               fill_rect.gx_rectangle_top,
303                                                               rectangle_height, fill_color);
304         }
305         view = view -> gx_view_next;
306     }
307 
308     /* Return successful completion.  */
309     return(GX_SUCCESS);
310 }
311 
312