• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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