1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "gfx_utils/diagram/rasterizer/rasterizer_scanline_clip.h"
17 
18 namespace OHOS {
19 /**
20  * @brief In the RASTERIZER process,Judge the mark according to the last clipping range
21  * And the cutting range judgment flag this time,
22  * add the actual sampling points and set relevant attributes
23  * @since 1.0
24  * @version 1.0
25  */
LineClipY(RasterizerCellsAntiAlias & ras,int32_t x1,int32_t y1,int32_t x2,int32_t y2,uint32_t clipFlagsOne,uint32_t clipFlagsTwo) const26 void RasterizerScanlineClip::LineClipY(RasterizerCellsAntiAlias& ras,
27                                        int32_t x1, int32_t y1,
28                                        int32_t x2, int32_t y2,
29                                        uint32_t clipFlagsOne, uint32_t clipFlagsTwo) const
30 {
31     clipFlagsOne &= DIRECTLY_BELOW;
32     clipFlagsTwo &= DIRECTLY_BELOW;
33     if ((clipFlagsOne | clipFlagsTwo) == 0) {
34         /**
35          * It indicates that the coordinates x1, y1, x2 and y2 are all within the range, and the line operates
36          */
37         ras.LineOperate(RasterDepictInt::GetXCoordinateValue(x1),
38                         RasterDepictInt::GetYCoordinateValue(y1),
39                         RasterDepictInt::GetXCoordinateValue(x2),
40                         RasterDepictInt::GetYCoordinateValue(y2));
41     } else {
42         if (clipFlagsOne == clipFlagsTwo) {
43             /**
44              * It indicates that the coordinates x1, y1, x2 and y2 are all outside the range and do not operate
45              */
46             return;
47         }
48         int32_t tx1 = x1;
49         int32_t ty1 = y1;
50         int32_t tx2 = x2;
51         int32_t ty2 = y2;
52         /**
53          * Indicates that the coordinate y1 < clip.y1
54          */
55         if (clipFlagsOne & 0x08) {
56             tx1 = x1 + RasterDepictInt::MultDiv(clipBox_.GetTop() - y1, x2 - x1, y2 - y1);
57             ty1 = clipBox_.GetTop();
58         }
59 
60         /**
61          * Indicates that the coordinate y1 > clip.y2
62          */
63         if (clipFlagsOne & 0x02) {
64             tx1 = x1 + RasterDepictInt::MultDiv(clipBox_.GetBottom() - y1, x2 - x1, y2 - y1);
65             ty1 = clipBox_.GetBottom();
66         }
67         /**
68          * Indicates that the coordinate y1 > clip.y2
69          */
70         if (clipFlagsTwo & 0x08) {
71             tx2 = x1 + RasterDepictInt::MultDiv(clipBox_.GetTop() - y1, x2 - x1, y2 - y1);
72             ty2 = clipBox_.GetTop();
73         }
74         /**
75          * Indicates that the coordinate y2 > clip.y2
76          */
77         if (clipFlagsTwo & 0x02) {
78             tx2 = x1 + RasterDepictInt::MultDiv(clipBox_.GetBottom() - y1, x2 - x1, y2 - y1);
79             ty2 = clipBox_.GetBottom();
80         }
81         ras.LineOperate(RasterDepictInt::GetXCoordinateValue(tx1), RasterDepictInt::GetYCoordinateValue(ty1),
82                         RasterDepictInt::GetXCoordinateValue(tx2), RasterDepictInt::GetYCoordinateValue(ty2));
83     }
84 }
85 
86 /**
87  * @brief Cohen–Sutherland
88  * In the RASTERIZER process, add the set sampling point,
89  * And set the sampling point, set the related cover and area attributes, etc.
90  *         |        |
91  *   0110  |  0010  | 0011
92  *         |        |
93  *  -------+--------+-------- clip_box.y2
94  *         |        |
95  *   0100  |  0000  | 0001
96  *         |        |
97  *  -------+--------+-------- clip_box.y1
98  *         |        |
99  *   1100  |  1000  | 1001
100  *         |        |
101  *   clip_box.x1  clip_box.x2
102  * @since 1.0
103  * @version 1.0
104  */
LineTo(RasterizerCellsAntiAlias & rasterLine,int32_t x2,int32_t y2)105 void RasterizerScanlineClip::LineTo(RasterizerCellsAntiAlias& rasterLine, int32_t x2, int32_t y2)
106 {
107     if (clipping_) {
108         uint32_t cFlagsLineToPoint = ClippingFlags(x2, y2, clipBox_);
109         if ((clippingFlags_ & 0x0A) == (cFlagsLineToPoint & 0x0A) && (clippingFlags_ & 0x0A) != 0) {
110             x1_ = x2;
111             y1_ = y2;
112             clippingFlags_ = cFlagsLineToPoint;
113             return;
114         }
115 
116         int32_t x1 = x1_;
117         int32_t y1 = y1_;
118         uint32_t clipFlagsMoveToPoint = clippingFlags_;
119         int32_t yPilotOne;
120         int32_t yPilotTwo;
121         uint32_t yClipFlagsOne = 0;
122         uint32_t yClipFlagsTwo = 0;
123 
124         switch (((clipFlagsMoveToPoint & 0x05) << 1) | (cFlagsLineToPoint & 0x05)) {
125             /**
126              * It indicates that x1, y1, x2,and y2 are all in the clip area
127              */
128             case 0x00:
129                 LineClipY(rasterLine, x1, y1, x2, y2, clipFlagsMoveToPoint, cFlagsLineToPoint);
130                 break;
131             /**
132              * indicate x2 > clip.x2
133              */
134             case 0x01:
135                 yPilotOne = y1 + RasterDepictInt::MultDiv(clipBox_.GetRight() - x1, y2 - y1, x2 - x1);
136                 yClipFlagsOne = ClippingFlagsY(yPilotOne, clipBox_);
137                 LineClipY(rasterLine, x1, y1, clipBox_.GetRight(), yPilotOne,
138                           clipFlagsMoveToPoint, yClipFlagsOne);
139                 LineClipY(rasterLine, clipBox_.GetRight(), yPilotOne,
140                           clipBox_.GetRight(), y2, yClipFlagsOne, cFlagsLineToPoint);
141                 break;
142             /**
143              * indicate x1 > clip.x2
144              */
145             case 0x02:
146                 yPilotOne = y1 + RasterDepictInt::MultDiv(clipBox_.GetRight() - x1, y2 - y1, x2 - x1);
147                 yClipFlagsOne = ClippingFlagsY(yPilotOne, clipBox_);
148                 LineClipY(rasterLine, clipBox_.GetRight(), y1, clipBox_.GetRight(),
149                           yPilotOne, clipFlagsMoveToPoint, yClipFlagsOne);
150                 LineClipY(rasterLine, clipBox_.GetRight(), yPilotOne, x2, y2,
151                           yClipFlagsOne, cFlagsLineToPoint);
152                 break;
153             /**
154              * indicate x1 > clip.x2 && x2 > clip.x2
155              */
156             case 0x03:
157                 LineClipY(rasterLine, clipBox_.GetRight(), y1, clipBox_.GetRight(), y2,
158                           clipFlagsMoveToPoint, cFlagsLineToPoint);
159                 break;
160             /**
161              * indicate x2 < clip.x1
162              */
163             case 0x04:
164                 yPilotOne = y1 + RasterDepictInt::MultDiv(clipBox_.GetLeft() - x1, y2 - y1, x2 - x1);
165                 yClipFlagsOne = ClippingFlagsY(yPilotOne, clipBox_);
166                 LineClipY(rasterLine, x1, y1, clipBox_.GetLeft(), yPilotOne,
167                           clipFlagsMoveToPoint, yClipFlagsOne);
168                 LineClipY(rasterLine, clipBox_.GetLeft(), yPilotOne, clipBox_.GetLeft(), y2,
169                           yClipFlagsOne, cFlagsLineToPoint);
170                 break;
171             /**
172              * indicate x1 > clip.x2 && x2 < clip.x1
173              */
174             case 0x06:
175                 yPilotOne = y1 + RasterDepictInt::MultDiv(clipBox_.GetRight() - x1, y2 - y1, x2 - x1);
176                 yPilotTwo = y1 + RasterDepictInt::MultDiv(clipBox_.GetLeft() - x1, y2 - y1, x2 - x1);
177                 yClipFlagsOne = ClippingFlagsY(yPilotOne, clipBox_);
178                 yClipFlagsTwo = ClippingFlagsY(yPilotTwo, clipBox_);
179                 LineClipY(rasterLine, clipBox_.GetRight(), y1, clipBox_.GetRight(), yPilotOne,
180                           clipFlagsMoveToPoint, yClipFlagsOne);
181                 LineClipY(rasterLine, clipBox_.GetRight(), yPilotOne, clipBox_.GetLeft(), yPilotTwo,
182                           yClipFlagsOne, yClipFlagsTwo);
183                 LineClipY(rasterLine, clipBox_.GetLeft(), yPilotTwo, clipBox_.GetLeft(), y2,
184                           yClipFlagsTwo, cFlagsLineToPoint);
185                 break;
186 
187             /**
188              * indicate x1 < clip.x1
189              */
190             case 0x08:
191                 yPilotOne = y1 + RasterDepictInt::MultDiv(clipBox_.GetLeft() - x1, y2 - y1, x2 - x1);
192                 yClipFlagsOne = ClippingFlagsY(yPilotOne, clipBox_);
193                 LineClipY(rasterLine, clipBox_.GetLeft(), y1, clipBox_.GetLeft(), yPilotOne,
194                           clipFlagsMoveToPoint, yClipFlagsOne);
195                 LineClipY(rasterLine, clipBox_.GetLeft(), yPilotOne, x2, y2,
196                           yClipFlagsOne, cFlagsLineToPoint);
197                 break;
198             /**
199              * indicate x1 < clip.x1 && x2 > clip.x2
200              */
201             case 0x09:
202                 yPilotOne = y1 + RasterDepictInt::MultDiv(clipBox_.GetLeft() - x1, y2 - y1, x2 - x1);
203                 yPilotTwo = y1 + RasterDepictInt::MultDiv(clipBox_.GetRight() - x1, y2 - y1, x2 - x1);
204                 yClipFlagsOne = ClippingFlagsY(yPilotOne, clipBox_);
205                 yClipFlagsTwo = ClippingFlagsY(yPilotTwo, clipBox_);
206                 LineClipY(rasterLine, clipBox_.GetLeft(), y1, clipBox_.GetLeft(), yPilotOne,
207                           clipFlagsMoveToPoint, yClipFlagsOne);
208                 LineClipY(rasterLine, clipBox_.GetLeft(), yPilotOne, clipBox_.GetRight(), yPilotTwo,
209                           yClipFlagsOne, yClipFlagsTwo);
210                 LineClipY(rasterLine, clipBox_.GetRight(), yPilotTwo, clipBox_.GetRight(), y2,
211                           yClipFlagsTwo, cFlagsLineToPoint);
212                 break;
213             /**
214              * indicate x1 < clip.x1 && x2 < clip.x1
215              */
216             case 0x0c:
217                 LineClipY(rasterLine, clipBox_.GetLeft(), y1, clipBox_.GetLeft(), y2,
218                           clipFlagsMoveToPoint, cFlagsLineToPoint);
219                 break;
220         }
221         clippingFlags_ = cFlagsLineToPoint;
222     } else {
223         rasterLine.LineOperate(RasterDepictInt::GetXCoordinateValue(x1_),
224                                RasterDepictInt::GetYCoordinateValue(y1_),
225                                RasterDepictInt::GetXCoordinateValue(x2),
226                                RasterDepictInt::GetYCoordinateValue(y2));
227     }
228     x1_ = x2;
229     y1_ = y2;
230 }
231 } // namespace OHOS
232