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/vertexgenerate/vertex_generate_dash.h"
17 
18 #include "gfx_utils/diagram/vertexprimitive/geometry_shorten_path.h"
19 
20 namespace OHOS {
21 #if defined(GRAPHIC_ENABLE_DASH_GENERATE_FLAG) && GRAPHIC_ENABLE_DASH_GENERATE_FLAG
VertexGenerateDash()22 VertexGenerateDash::VertexGenerateDash()
23     : totalDashLen_(0.0f),
24       numDashes_(0),
25       dashStart_(0.0f),
26       shorten_(0.0f),
27       currDashStart_(0.0f),
28       currDash_(0),
29       currRest_(0.0f),
30       srcVertices_(),
31       closed_(0),
32       status_(INITIAL),
33       srcVertex_(0) {}
34 
GetGenerateFlags()35 VertexGenerateFlags VertexGenerateDash::GetGenerateFlags()
36 {
37     return GENERATE_DASH;
38 }
39 
RemoveAllDashes()40 void VertexGenerateDash::RemoveAllDashes()
41 {
42     totalDashLen_ = 0.0;
43     numDashes_ = 0;
44     currDashStart_ = 0.0;
45     currDash_ = 0;
46 }
47 
AddDash(float dashLen,float gapLen)48 void VertexGenerateDash::AddDash(float dashLen, float gapLen)
49 {
50     if (numDashes_ < MAX_DASHES) {
51         totalDashLen_ += dashLen + gapLen;
52         dashes_[numDashes_++] = dashLen;
53         dashes_[numDashes_++] = gapLen;
54     }
55 }
56 
DashStart(float ds)57 void VertexGenerateDash::DashStart(float ds)
58 {
59     dashStart_ = ds;
60     CalcDashStart(MATH_ABS(ds));
61 }
62 
CalcDashStart(float ds)63 void VertexGenerateDash::CalcDashStart(float ds)
64 {
65     currDash_ = 0;
66     currDashStart_ = 0.0f;
67     for (; ds > 0.0f;) {
68         if (ds > dashes_[currDash_]) {
69             ds -= dashes_[currDash_];
70             ++currDash_;
71             currDashStart_ = 0.0f;
72             if (currDash_ >= numDashes_) {
73                 currDash_ = 0;
74             }
75         } else {
76             currDashStart_ = ds;
77             ds = 0.0f;
78         }
79     }
80 }
81 
RemoveAll()82 void VertexGenerateDash::RemoveAll()
83 {
84     status_ = INITIAL;
85     srcVertices_.Clear();
86     closed_ = 0;
87 }
88 
AddVertex(float x,float y,uint32_t cmd)89 void VertexGenerateDash::AddVertex(float x, float y, uint32_t cmd)
90 {
91     status_ = INITIAL;
92     if (IsMoveTo(cmd)) {
93         srcVertices_.ModifyLast(VertexDist(x, y));
94     } else {
95         if (IsVertex(cmd)) {
96             srcVertices_.Add(VertexDist(x, y));
97         } else {
98             closed_ = GetCloseFlag(cmd);
99         }
100     }
101 }
102 
Rewind(uint32_t)103 void VertexGenerateDash::Rewind(uint32_t)
104 {
105     if (status_ == INITIAL) {
106         srcVertices_.Close(closed_ != 0);
107         ShortenPath(srcVertices_, shorten_, closed_);
108     }
109     status_ = READY;
110     srcVertex_ = 0;
111 }
112 
CompareSize()113 void VertexGenerateDash::CompareSize()
114 {
115     if (currDash_ >= numDashes_) {
116         currDash_ = 0;
117     }
118 }
119 
CompareVertexSize()120 void VertexGenerateDash::CompareVertexSize()
121 {
122     if (closed_) {
123         if (srcVertex_ > srcVertices_.Size()) {
124             status_ = STOP;
125         } else {
126             if (srcVertex_ >= srcVertices_.Size()) {
127                 vertexDist2_ = &srcVertices_[0];
128             } else {
129                 vertexDist2_ = &srcVertices_[srcVertex_];
130             }
131         }
132     } else {
133         if (srcVertex_ >= srcVertices_.Size()) {
134             status_ = STOP;
135         } else {
136             vertexDist2_ = &srcVertices_[srcVertex_];
137         }
138     }
139 }
140 
GenerateVertex(float * x,float * y)141 uint32_t VertexGenerateDash::GenerateVertex(float* x, float* y)
142 {
143     uint32_t cmd = PATH_CMD_MOVE_TO;
144     while (!IsStop(cmd)) {
145         switch (status_) {
146             case INITIAL:
147                 Rewind(0); // fall-through
148             case READY:
149                 if (numDashes_ < FLOATNUM || srcVertices_.Size() < FLOATNUM) {
150                     return PATH_CMD_STOP;
151                 }
152                 status_ = POLYLINE;
153                 srcVertex_ = 1;
154                 vertexDist1_ = &srcVertices_[0];
155                 vertexDist2_ = &srcVertices_[1];
156                 currRest_ = vertexDist1_->vertexDistance;
157                 *x = vertexDist1_->vertexXCoord;
158                 *y = vertexDist1_->vertexYCoord;
159                 if (dashStart_ >= 0.0f) {
160                     CalcDashStart(dashStart_);
161                 };
162                 return PATH_CMD_MOVE_TO;
163             case POLYLINE: {
164                 float dashRest = dashes_[currDash_] - currDashStart_;
165                 if (currDash_ & 1) {
166                     cmd = PATH_CMD_MOVE_TO;
167                 } else {
168                     cmd = PATH_CMD_LINE_TO;
169                 }
170                 if (currRest_ > dashRest) {
171                     currRest_ -= dashRest;
172                     ++currDash_;
173                     CompareSize();
174                     currDashStart_ = 0.0f;
175                     *x = vertexDist2_->vertexXCoord -
176                             (vertexDist2_->vertexXCoord - vertexDist1_->vertexXCoord) * currRest_
177                             / vertexDist1_->vertexDistance;
178                     *y = vertexDist2_->vertexYCoord -
179                             (vertexDist2_->vertexYCoord - vertexDist1_->vertexYCoord) * currRest_
180                             / vertexDist1_->vertexDistance;
181                 } else {
182                     currDashStart_ += currRest_;
183                     *x = vertexDist2_->vertexXCoord;
184                     *y = vertexDist2_->vertexYCoord;
185                     ++srcVertex_;
186                     vertexDist1_ = vertexDist2_;
187                     currRest_ = vertexDist1_->vertexDistance;
188                     CompareVertexSize();
189                 }
190                 return cmd;
191             }
192             case STOP:
193                 return PATH_CMD_STOP;
194         }
195     }
196     return PATH_CMD_STOP;
197 }
198 #endif
199 } // namespace OHOS
200