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 #include "gfx_utils/diagram/vertexgenerate/vertex_generate_stroke.h"
16 
17 #include "gfx_utils/diagram/vertexprimitive/geometry_shorten_path.h"
18 
19 namespace OHOS {
VertexGenerateStroke()20 VertexGenerateStroke::VertexGenerateStroke()
21     : stroker_(),
22       srcVertices_(),
23       outVertices_(),
24       strokeShorten_(0.0f),
25       closed_(0),
26       status_(INITIAL),
27       srcVertex_(0),
28       outVertex_(0)
29 {
30 }
31 
RemoveAll()32 void VertexGenerateStroke::RemoveAll()
33 {
34     srcVertices_.Clear();
35     closed_ = 0;
36     status_ = INITIAL;
37 }
38 
AddVertex(float x,float y,uint32_t cmd)39 void VertexGenerateStroke::AddVertex(float x, float y, uint32_t cmd)
40 {
41     status_ = INITIAL;
42     if (IsMoveTo(cmd)) {
43         srcVertices_.ModifyLast(VertexDist(x, y));
44     } else {
45         if (IsVertex(cmd)) {
46             srcVertices_.Add(VertexDist(x, y));
47         } else {
48             closed_ = GetCloseFlag(cmd);
49         }
50     }
51 }
52 
Rewind(uint32_t)53 void VertexGenerateStroke::Rewind(uint32_t)
54 {
55     if (status_ == INITIAL) {
56         srcVertices_.Close(closed_ != 0);
57         ShortenPath(srcVertices_, strokeShorten_, closed_);
58         const uint32_t verticeNum = 3;
59         if (srcVertices_.Size() < verticeNum) {
60             closed_ = 0;
61         }
62     }
63     status_ = READY;
64     srcVertex_ = 0;
65     outVertex_ = 0;
66 }
67 
GenerateVertex(float * x,float * y)68 uint32_t VertexGenerateStroke::GenerateVertex(float* x, float* y)
69 {
70     const uint32_t verticesNum = 2;
71     uint32_t cmd = PATH_CMD_LINE_TO;
72     while (!IsStop(cmd)) {
73         switch (status_) {
74             case INITIAL:
75                 Rewind(0); // It will be ready immediately after initialization
76                 /* fallthru */
77             case READY:
78                 VertexReady(verticesNum, cmd);
79                 break;
80             case LINECAP_START:
81                 VertexLineCapStart();
82                 break;
83             case LINECAP_END:
84                 VertexLineCapEnd(verticesNum);
85                 break;
86             case LINEJOIN_START:
87                 VertexLineJoinStart();
88                 break;
89             case CLOSE_FIRST:
90                 VertexCloseFirst(cmd);
91                 break;
92             case LINEJOIN_END:
93                 VertexLineJoinEnd();
94                 break;
95             case OUT_VERTICES:
96                 if (IsVertexOutVertices(x, y)) {
97                     return cmd;
98                 }
99                 break;
100             case CLOCKWISE_ENDPOLY:
101                 status_ = prevStatus_;
102                 return PATH_CMD_END_POLY | PATH_FLAGS_CLOSE | PATH_FLAGS_CLOCKWISE;
103             case ANTI_CLOCKWISE_ENDPOLY:
104                 status_ = prevStatus_;
105                 return PATH_CMD_END_POLY | PATH_FLAGS_CLOSE | PATH_FLAGS_ANTI_CLOCKWISE;
106             case STOP:
107                 cmd = PATH_CMD_STOP;
108                 break;
109             default: break;
110         }
111     }
112     return cmd;
113 }
114 
VertexReady(const uint32_t & verticesNum,uint32_t & cmd)115 void VertexGenerateStroke::VertexReady(const uint32_t& verticesNum, uint32_t& cmd)
116 {
117     if (srcVertices_.Size() < verticesNum + uint32_t(closed_ != 0)) {
118         cmd = PATH_CMD_STOP;
119         return;
120     }
121     if (closed_) {
122         status_ = LINEJOIN_START;
123     } else {
124         status_ = LINECAP_START;
125     }
126     cmd = PATH_CMD_MOVE_TO;
127     srcVertex_ = 0;
128     outVertex_ = 0;
129 }
130 
VertexLineCapStart()131 void VertexGenerateStroke::VertexLineCapStart()
132 {
133 #if defined(GRAPHIC_ENABLE_LINECAP_FLAG) && GRAPHIC_ENABLE_LINECAP_FLAG
134     stroker_.CalcCap(outVertices_,
135                      srcVertices_[0],
136                      srcVertices_[1],
137                      srcVertices_[0].vertexDistance);
138 #endif
139     srcVertex_ = 1;
140     prevStatus_ = LINEJOIN_START;
141     status_ = OUT_VERTICES;
142     outVertex_ = 0;
143 }
144 
VertexLineCapEnd(const uint32_t & verticesNum)145 void VertexGenerateStroke::VertexLineCapEnd(const uint32_t& verticesNum)
146 {
147 #if defined(GRAPHIC_ENABLE_LINECAP_FLAG) && GRAPHIC_ENABLE_LINECAP_FLAG
148     stroker_.CalcCap(outVertices_,
149                      srcVertices_[srcVertices_.Size() - 1],
150                      srcVertices_[srcVertices_.Size() - verticesNum],
151                      srcVertices_[srcVertices_.Size() - verticesNum].vertexDistance);
152 #endif
153     prevStatus_ = LINEJOIN_END;
154     status_ = OUT_VERTICES;
155     outVertex_ = 0;
156 }
157 
VertexLineJoinStart()158 void VertexGenerateStroke::VertexLineJoinStart()
159 {
160     if (closed_ && srcVertex_ >= srcVertices_.Size()) {
161         prevStatus_ = CLOSE_FIRST;
162         status_ = CLOCKWISE_ENDPOLY;
163         return;
164     }
165     if (!closed_ && srcVertex_ >= srcVertices_.Size() - 1) {
166         status_ = LINECAP_END;
167         return;
168     }
169 #if defined(GRAPHIC_ENABLE_LINEJOIN_FLAG) && GRAPHIC_ENABLE_LINEJOIN_FLAG
170     stroker_.CalcJoin(outVertices_,
171                       srcVertices_.Prev(srcVertex_),
172                       srcVertices_.Curr(srcVertex_),
173                       srcVertices_.Next(srcVertex_),
174                       srcVertices_.Prev(srcVertex_).vertexDistance,
175                       srcVertices_.Curr(srcVertex_).vertexDistance);
176 #endif
177     ++srcVertex_;
178     prevStatus_ = status_;
179     status_ = OUT_VERTICES;
180     outVertex_ = 0;
181 }
182 
VertexLineJoinEnd()183 void VertexGenerateStroke::VertexLineJoinEnd()
184 {
185     if (srcVertex_ <= uint32_t(closed_ == 0)) {
186         status_ = ANTI_CLOCKWISE_ENDPOLY;
187         prevStatus_ = STOP;
188         return;
189     }
190     --srcVertex_;
191 #if defined(GRAPHIC_ENABLE_LINEJOIN_FLAG) && GRAPHIC_ENABLE_LINEJOIN_FLAG
192     stroker_.CalcJoin(outVertices_,
193                       srcVertices_.Next(srcVertex_),
194                       srcVertices_.Curr(srcVertex_),
195                       srcVertices_.Prev(srcVertex_),
196                       srcVertices_.Curr(srcVertex_).vertexDistance,
197                       srcVertices_.Prev(srcVertex_).vertexDistance);
198 #endif
199     outVertex_ = 0;
200     prevStatus_ = status_;
201     status_ = OUT_VERTICES;
202 }
203 
VertexCloseFirst(uint32_t & cmd)204 void VertexGenerateStroke::VertexCloseFirst(uint32_t& cmd)
205 {
206     status_ = LINEJOIN_END;
207     cmd = PATH_CMD_MOVE_TO;
208 }
209 
IsVertexOutVertices(float * x,float * y)210 bool VertexGenerateStroke::IsVertexOutVertices(float* x, float* y)
211 {
212     if (outVertex_ >= outVertices_.Size()) {
213         status_ = prevStatus_;
214         return false;
215     } else {
216         const PointF& c = outVertices_[outVertex_++];
217         *x = c.x;
218         *y = c.y;
219         return true;
220     }
221 }
222 } // namespace OHOS
223