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 /** Canvas Management (Canvas) */
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_utility.h"
29 #include "gx_canvas.h"
30 #include "gx_display.h"
31 #include "gx_window.h"
32
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* _gx_canvas_block_move.c PORTABLE C */
39 /* 6.3.0 */
40 /* AUTHOR */
41 /* */
42 /* Kenneth Maxwell, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* This function copies a block of pixel from one reference position */
47 /* to another. */
48 /* */
49 /* INPUT */
50 /* */
51 /* block Rectangle to move */
52 /* x_shift Distance to move in x */
53 /* direction */
54 /* y_shift Distance to move in y */
55 /* direction */
56 /* dirty Flag of dirty block */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* status Completion status */
61 /* */
62 /* CALLS */
63 /* */
64 /* _gx_utility_rectangle_inside_detect Detect if a second rectangle */
65 /* is completely within the */
66 /* first one */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Application Code */
71 /* _gx_window_client_scroll */
72 /* */
73 /* RELEASE HISTORY */
74 /* */
75 /* DATE NAME DESCRIPTION */
76 /* */
77 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
78 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
79 /* resulting in version 6.1 */
80 /* 10-31-2023 Ting Zhu Modified comment(s), */
81 /* added canvas status check, */
82 /* resulting in version 6.3.0 */
83 /* */
84 /**************************************************************************/
_gx_canvas_block_move(GX_RECTANGLE * block,GX_VALUE x_shift,GX_VALUE y_shift,GX_RECTANGLE * dirty)85 UINT _gx_canvas_block_move(GX_RECTANGLE *block, GX_VALUE x_shift, GX_VALUE y_shift, GX_RECTANGLE *dirty)
86 {
87 GX_DRAW_CONTEXT *context;
88 GX_DISPLAY *display;
89 GX_VIEW *view;
90 UINT status = GX_FAILURE;
91
92
93 /* pick up the current drawing context */
94 context = _gx_system_current_draw_context;
95
96 /* If the caller hasn't opened the canvas, we can't do anything */
97 if (!context)
98 {
99 return status;
100 }
101
102 /* pick up current display driver */
103 display = context -> gx_draw_context_display;
104
105 /* check to see if this driver supports block move */
106 if (!display -> gx_display_driver_block_move || (context -> gx_draw_context_canvas -> gx_canvas_status & GX_CANVAS_PARTIAL_FRAME_BUFFER))
107 {
108 /* this driver doesn't support block move. If we are
109 partial drawing just mark the caller as dirty so that
110 a normal redraw operation occurs.
111 */
112 return status;
113 }
114
115 /* test to determine if any viewport of the caller contains the block to move.
116 If yes, we can do the block move. If no, we have to
117 do a normal invalidation and redraw.
118 */
119 view = context -> gx_draw_context_view_head;
120
121 while (view)
122 {
123 if (_gx_utility_rectangle_inside_detect(&view -> gx_view_rectangle, block))
124 {
125 context -> gx_draw_context_clip = block;
126 display -> gx_display_driver_block_move(context, block, x_shift, y_shift);
127 status = GX_SUCCESS;
128 break;
129 }
130 view = view -> gx_view_next;
131 }
132
133 if (status == GX_SUCCESS && dirty)
134 {
135 /* we were able to aid drawing by doing a block move. Mark
136 the remainder that was not updated as dirty so that the
137 caller can redraw that portion
138 */
139 *dirty = *block;
140
141 if (x_shift)
142 {
143 if (x_shift > 0)
144 {
145 dirty -> gx_rectangle_right = (GX_VALUE)(dirty -> gx_rectangle_left + x_shift - 1);
146 }
147 else
148 {
149 dirty -> gx_rectangle_left = (GX_VALUE)(dirty -> gx_rectangle_right + x_shift + 1);
150 }
151 }
152 else
153 {
154 if (y_shift > 0)
155 {
156 dirty -> gx_rectangle_bottom = (GX_VALUE)(dirty -> gx_rectangle_top + y_shift - 1);
157 }
158 else
159 {
160 dirty -> gx_rectangle_top = (GX_VALUE)(dirty -> gx_rectangle_bottom + y_shift + 1);
161 }
162 }
163 }
164 return(status);
165 }
166
167