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_antialias.h"
17
18 namespace OHOS {
19 /**
20 * @brief Scan line that gets a y value from rasterizer stage
21 * And iterate the cell array of the current scan line to obtain area->cover,
22 * Use both to calculate delta area as area cover and convert it into gamma cover
23 * the color information is obtained successfully,
24 * and then the alpha information of color is calculated by gamma function
25 * Fill in the new scanline and have subsequent render.
26 * @since 1.0
27 * @version 1.0
28 */
SweepScanline(GeometryScanline & sl)29 bool RasterizerScanlineAntialias::SweepScanline(GeometryScanline& sl)
30 {
31 while (true) {
32 if (scanY_ > outline_.GetMaxY()) {
33 return false;
34 }
35 sl.ResetSpans();
36 uint32_t numCells = outline_.GetScanlineNumCells(scanY_);
37 const CellBuildAntiAlias * const *cells = outline_.GetScanlineCells(scanY_);
38 int32_t cover = 0;
39
40 while (numCells) {
41 const CellBuildAntiAlias* curCell = *cells;
42 if (curCell == nullptr) {
43 GRAPHIC_LOGE("Text: RasterizerScanlineAntialias::SweepScanline can not new curCell");
44 return true;
45 }
46 int32_t x = curCell->x;
47 int32_t area = curCell->area;
48 uint32_t alpha;
49
50 cover += curCell->cover;
51 // accumulate all cells with the same X
52 while (--numCells && (curCell = *++cells) && (curCell != nullptr) && (curCell->x == x)) {
53 area += curCell->area;
54 cover += curCell->cover;
55 }
56 if (area) {
57 // Span interval from area to (cover << (POLY_SUBPIXEL_SHIFT + 1))
58 // Cover can be understood as a delta mask with an area of 1
59 alpha = CalculateAlpha((cover << (POLY_SUBPIXEL_SHIFT + 1)) - area);
60 if (alpha) {
61 sl.AddCell(x, alpha);
62 }
63 x++;
64 }
65 if (numCells && (curCell != nullptr) && curCell->x > x) {
66 // At this time, area is 0, that is, 0 to cover << (POLY_SUBPIXEL_SHIFT + 1)
67 alpha = CalculateAlpha(cover << (POLY_SUBPIXEL_SHIFT + 1));
68 if (alpha) {
69 sl.AddSpan(x, curCell->x - x, alpha);
70 }
71 }
72 }
73
74 if (sl.NumSpans()) {
75 break;
76 }
77 ++scanY_;
78 }
79
80 sl.Finalize(scanY_);
81 ++scanY_;
82 return true;
83 }
84
85 /**
86 * @brief Convert area cover to gamma cover value to calculate alpha.
87 * @since 1.0
88 * @version 1.0
89 */
CalculateAlpha(int32_t area) const90 uint32_t RasterizerScanlineAntialias::CalculateAlpha(int32_t area) const
91 {
92 int32_t cover = area >> (POLY_SUBPIXEL_SHIFT * 2 + 1 - AA_SHIFT);
93
94 if (cover < 0) {
95 cover = -cover;
96 }
97 if (fillingRule_ == FILL_EVEN_ODD) {
98 cover &= AA_MASK2;
99 if (cover > AA_SCALE) {
100 cover = AA_SCALE2 - cover;
101 }
102 }
103 if (cover > AA_MASK) {
104 cover = AA_MASK;
105 }
106 return gammar_[cover];
107 }
108
Reset()109 void RasterizerScanlineAntialias::Reset()
110 {
111 outline_.Reset();
112 status_ = STATUS_INITIAL;
113 }
114
ClipBox(float x1,float y1,float x2,float y2)115 void RasterizerScanlineAntialias::ClipBox(float x1, float y1, float x2, float y2)
116 {
117 Reset();
118 clipper_.ClipBox(RasterDepictInt::UpScale(x1), RasterDepictInt::UpScale(y1),
119 RasterDepictInt::UpScale(x2), RasterDepictInt::UpScale(y2));
120 }
121
ResetClipping()122 void RasterizerScanlineAntialias::ResetClipping()
123 {
124 Reset();
125 clipper_.ResetClipping();
126 }
127
ClosePolygon()128 void RasterizerScanlineAntialias::ClosePolygon()
129 {
130 if (status_ == STATUS_LINE_TO) {
131 clipper_.LineTo(outline_, startX_, startY_);
132 status_ = STATUS_CLOSED;
133 }
134 }
135
MoveTo(int32_t x,int32_t y)136 void RasterizerScanlineAntialias::MoveTo(int32_t x, int32_t y)
137 {
138 if (outline_.GetSorted()) {
139 Reset();
140 }
141 if (autoClose_) {
142 ClosePolygon();
143 }
144 clipper_.MoveTo(startX_ = RasterDepictInt::DownScale(x),
145 startY_ = RasterDepictInt::DownScale(y));
146 status_ = STATUS_MOVE_TO;
147 }
148
LineTo(int32_t x,int32_t y)149 void RasterizerScanlineAntialias::LineTo(int32_t x, int32_t y)
150 {
151 clipper_.LineTo(outline_, RasterDepictInt::DownScale(x), RasterDepictInt::DownScale(y));
152 status_ = STATUS_LINE_TO;
153 }
154
MoveToByfloat(float x,float y)155 void RasterizerScanlineAntialias::MoveToByfloat(float x, float y)
156 {
157 if (outline_.GetSorted()) {
158 Reset();
159 }
160 if (autoClose_) {
161 ClosePolygon();
162 }
163 clipper_.MoveTo(startX_ = RasterDepictInt::UpScale(x),
164 startY_ = RasterDepictInt::UpScale(y));
165 status_ = STATUS_MOVE_TO;
166 }
167
LineToByfloat(float x,float y)168 void RasterizerScanlineAntialias::LineToByfloat(float x, float y)
169 {
170 clipper_.LineTo(outline_, RasterDepictInt::UpScale(x), RasterDepictInt::UpScale(y));
171 status_ = STATUS_LINE_TO;
172 }
173
AddVertex(float x,float y,uint32_t cmd)174 void RasterizerScanlineAntialias::AddVertex(float x, float y, uint32_t cmd)
175 {
176 if (IsMoveTo(cmd)) {
177 MoveToByfloat(x, y);
178 } else if (IsVertex(cmd)) {
179 LineToByfloat(x, y);
180 } else if (IsClose(cmd)) {
181 ClosePolygon();
182 }
183 }
184
Sort()185 void RasterizerScanlineAntialias::Sort()
186 {
187 if (autoClose_) {
188 ClosePolygon();
189 }
190 outline_.SortAllCells();
191 }
192
RewindScanlines()193 bool RasterizerScanlineAntialias::RewindScanlines()
194 {
195 if (autoClose_) {
196 ClosePolygon();
197 }
198 outline_.SortAllCells();
199 if (outline_.GetTotalCells() == 0) {
200 return false;
201 }
202 scanY_ = outline_.GetMinY();
203 return true;
204 }
205 } // namespace OHOS
206