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 #ifndef GRAPHIC_LTE_GEOMERTY_PATH_STORAGE_H 17 #define GRAPHIC_LTE_GEOMERTY_PATH_STORAGE_H 18 19 #include "geometry_bezier_arc.h" 20 #include "gfx_utils/diagram/common/common_math.h" 21 #include "gfx_utils/diagram/vertexprimitive/geometry_plaindata_array.h" 22 23 namespace OHOS { 24 /** 25 * @brief Vertex source data block 26 * @since 1.0 27 * @version 1.0 28 */ 29 class VertexBlockStorage { 30 public: 31 enum BlockScale { 32 BLOCK_SCALE_SHIFT = THIRTY_TWO_COLOR_NUM, 33 BLOCK_SCALE_SIZE = 1 << BLOCK_SCALE_SHIFT, 34 BLOCK_SCALE_MASK = BLOCK_SCALE_SIZE - 1, 35 BLOCK_SCALE_POOL = MAX_COLOR_SIZE 36 }; 37 ~VertexBlockStorage()38 ~VertexBlockStorage() 39 { 40 FreeAll(); 41 } 42 VertexBlockStorage()43 VertexBlockStorage() : totalVertices_(0), totalBlocks_(0), maxBlocks_(0), croodBlocks_(0), cmdBlocks_(0) {} 44 45 const VertexBlockStorage& operator=(const VertexBlockStorage& vertexBlockStorage) 46 { 47 RemoveAll(); 48 for (uint32_t iIndex = 0; iIndex < vertexBlockStorage.GetTotalVertices(); iIndex++) { 49 float x; 50 float y; 51 uint32_t cmd = vertexBlockStorage.GenerateVertex(iIndex, &x, &y); 52 AddVertex(x, y, cmd); 53 } 54 this->totalBlocks_ = vertexBlockStorage.totalBlocks_; 55 maxBlocks_ = vertexBlockStorage.maxBlocks_; 56 croodBlocks_ = vertexBlockStorage.croodBlocks_; 57 cmdBlocks_ = vertexBlockStorage.cmdBlocks_; 58 return *this; 59 } 60 VertexBlockStorage(const VertexBlockStorage & vertexBlockStorage)61 VertexBlockStorage(const VertexBlockStorage& vertexBlockStorage) 62 { 63 *this = vertexBlockStorage; 64 } 65 66 /** 67 * @brief Remove all vertices. 68 * 69 * @since 1.0 70 * @version 1.0 71 */ RemoveAll()72 void RemoveAll() 73 { 74 totalVertices_ = 0; 75 } 76 /** 77 * @brief Free up space 78 * @since 1.0 79 * @version 1.0 80 */ FreeAll()81 void FreeAll() 82 { 83 if (totalBlocks_ > 0) { 84 float** coordBLK = croodBlocks_ + totalBlocks_ - 1; 85 for (; totalBlocks_ > 0; totalBlocks_--) { 86 GeometryArrayAllocator<float>::Deallocate( 87 *coordBLK, BLOCK_SCALE_SIZE * TWO_TIMES + BLOCK_SCALE_SIZE / (sizeof(float) / sizeof(uint8_t))); 88 --coordBLK; 89 } 90 GeometryArrayAllocator<float*>::Deallocate(croodBlocks_, maxBlocks_ * TWO_TIMES); 91 totalBlocks_ = 0; 92 maxBlocks_ = 0; 93 croodBlocks_ = 0; 94 cmdBlocks_ = 0; 95 totalVertices_ = 0; 96 } 97 } 98 /** 99 * @brief add vertex. 100 * 101 * @param x Vertex X-axis coordinates. 102 * @param y Vertex Y-axis coordinates. 103 * @param cmd Instruction type. 104 * @since 1.0 105 * @version 1.0 106 */ AddVertex(float x,float y,uint32_t cmd)107 void AddVertex(float x, float y, uint32_t cmd) 108 { 109 float* coordPtr = 0; 110 *StoragePtrs(&coordPtr) = static_cast<uint8_t>(cmd); 111 coordPtr[0] = float(x); 112 coordPtr[1] = float(y); 113 totalVertices_++; 114 } 115 /** 116 * @brief Returns the last instruction. 117 * @return Returns the last instruction type. 118 * @since 1.0 119 * @version 1.0 120 */ LastCommand()121 uint32_t LastCommand() const 122 { 123 if (totalVertices_) { 124 return Command(totalVertices_ - 1); 125 } 126 return PATH_CMD_STOP; 127 } 128 /** 129 * @brief Returns the coordinates of the last vertex. 130 * @param x Used to obtain the x-axis coordinates of the last vertex. 131 * @param y Used to obtain the y-axis coordinates of the last vertex. 132 * @return Returns the instruction type corresponding to the vertex. 133 * @since 1.0 134 * @version 1.0 135 */ LastVertex(float * x,float * y)136 uint32_t LastVertex(float* x, float* y) const 137 { 138 if (totalVertices_) { 139 return GenerateVertex(totalVertices_ - 1, x, y); 140 } 141 return PATH_CMD_STOP; 142 } 143 /** 144 * @brief Returns the number of vertices. 145 * @return Returns the number of vertices. 146 * @since 1.0 147 * @version 1.0 148 */ GetTotalVertices()149 uint32_t GetTotalVertices() const 150 { 151 return totalVertices_; 152 } 153 /** 154 * @brief Gets the coordinates of a particular vertex. 155 * @param idx Vertex subscript. 156 * @param x Used to obtain the x-axis coordinates of vertices. 157 * @param y Used to obtain the y-axis coordinates of vertices. 158 * @return Returns the instruction type corresponding to the vertex. 159 * @since 1.0 160 * @version 1.0 161 */ GenerateVertex(uint32_t idx,float * x,float * y)162 uint32_t GenerateVertex(uint32_t idx, float* x, float* y) const 163 { 164 uint32_t nb = idx >> BLOCK_SCALE_SHIFT; 165 const float* pv = croodBlocks_[nb] + ((idx & BLOCK_SCALE_MASK) << 1); 166 *x = pv[0]; 167 *y = pv[1]; 168 return cmdBlocks_[nb][idx & BLOCK_SCALE_MASK]; 169 } 170 /** 171 * @brief ets the instruction type corresponding to a specific vertex. 172 * @param index Vertex subscript. 173 * @return Returns the instruction type corresponding to the vertex. 174 * @since 1.0 175 * @version 1.0 176 */ Command(uint32_t index)177 uint32_t Command(uint32_t index) const 178 { 179 return cmdBlocks_[index >> BLOCK_SCALE_SHIFT][index & BLOCK_SCALE_MASK]; 180 } 181 182 private: AllocateBlock(uint32_t nb)183 void AllocateBlock(uint32_t nb) 184 { 185 if (nb >= maxBlocks_) { 186 float** new_coords = GeometryArrayAllocator<float*>::Allocate((maxBlocks_ + BLOCK_SCALE_POOL) * TWO_TIMES); 187 if (new_coords == nullptr) { 188 return; 189 } 190 191 uint8_t** new_cmds = (uint8_t**)(new_coords + maxBlocks_ + BLOCK_SCALE_POOL); 192 if (new_cmds == nullptr) { 193 return; 194 } 195 196 if (croodBlocks_) { 197 if (memcpy_s(new_coords, maxBlocks_ * sizeof(float*), 198 croodBlocks_, maxBlocks_ * sizeof(float*)) != EOK) { 199 } 200 if (memcpy_s(new_cmds, maxBlocks_ * sizeof(float*), 201 cmdBlocks_, maxBlocks_ * sizeof(uint8_t*)) != EOK) { 202 } 203 GeometryArrayAllocator<float*>::Deallocate(croodBlocks_, maxBlocks_ * TWO_TIMES); 204 } 205 croodBlocks_ = new_coords; 206 cmdBlocks_ = new_cmds; 207 maxBlocks_ += BLOCK_SCALE_POOL; 208 } 209 croodBlocks_[nb] = GeometryArrayAllocator<float>::Allocate( 210 BLOCK_SCALE_SIZE * TWO_TIMES + BLOCK_SCALE_SIZE / (sizeof(float) / sizeof(uint8_t))); 211 212 cmdBlocks_[nb] = (uint8_t*)(croodBlocks_[nb] + BLOCK_SCALE_SIZE * TWO_TIMES); 213 214 totalBlocks_++; 215 } StoragePtrs(float ** xy_ptr)216 uint8_t* StoragePtrs(float** xy_ptr) 217 { 218 uint32_t nb = totalVertices_ >> BLOCK_SCALE_SHIFT; 219 if (nb >= totalBlocks_) { 220 AllocateBlock(nb); 221 } 222 *xy_ptr = croodBlocks_[nb] + ((totalVertices_ & BLOCK_SCALE_MASK) << 1); 223 return cmdBlocks_[nb] + (totalVertices_ & BLOCK_SCALE_MASK); 224 } 225 226 private: 227 uint32_t totalVertices_; 228 uint32_t totalBlocks_; 229 uint32_t maxBlocks_; 230 float** croodBlocks_; // Input points 231 uint8_t** cmdBlocks_; // Mark point status 232 }; 233 234 class UICanvasVertices : public HeapBase { 235 public: UICanvasVertices()236 UICanvasVertices() : vertices_(), iterator_(0) {} 237 238 /** 239 * @brief Remove all vertices 240 * 241 * @since 1.0 242 * @version 1.0 243 */ RemoveAll()244 void RemoveAll() 245 { 246 vertices_.RemoveAll(); 247 iterator_ = 0; 248 } 249 /** 250 * @brief Free up space 251 * @since 1.0 252 * @version 1.0 253 */ FreeAll()254 void FreeAll() 255 { 256 vertices_.FreeAll(); 257 iterator_ = 0; 258 } 259 260 /** 261 * @brief Move a point to the set coordinates 262 * @param x Vertex X-axis coordinates 263 * @param y Vertex Y-axis coordinates 264 * @since 1.0 265 * @version 1.0 266 */ MoveTo(float x,float y)267 void MoveTo(float x, float y) 268 { 269 vertices_.AddVertex(x, y, PATH_CMD_MOVE_TO); 270 } 271 /** 272 * @brief Connect the line to the entered coordinates 273 * @param x Vertex X-axis coordinates 274 * @param y Vertex Y-axis coordinates 275 * @since 1.0 276 * @version 1.0 277 */ LineTo(float x,float y)278 void LineTo(float x, float y) 279 { 280 vertices_.AddVertex(x, y, PATH_CMD_LINE_TO); 281 } 282 CubicBezierCurve(double xCtrl1,double yCtrl1,double xCtrl2,double yCtrl2,double xEnd,double yEnd)283 void CubicBezierCurve(double xCtrl1, double yCtrl1, 284 double xCtrl2, double yCtrl2, 285 double xEnd, double yEnd) 286 { 287 vertices_.AddVertex(xCtrl1, yCtrl1, PATH_CMD_CURVE4); 288 vertices_.AddVertex(xCtrl2, yCtrl2, PATH_CMD_CURVE4); 289 vertices_.AddVertex(xEnd, yEnd, PATH_CMD_CURVE4); 290 } 291 292 /** 293 * @brief Draw an arc 294 * @param rx Long and short axle 295 * @param ry Long and short axle 296 * @param angle angle 297 * @param largeArcFlag Superior inferior arc 298 * @param sweepFlag Clockwise and counterclockwise 299 * @param x End X coordinate 300 * @param y End Y-axis coordinates 301 * @since 1.0 302 * @version 1.0 303 */ ArcTo(float rx,float ry,float angle,bool largeArcFlag,bool sweepFlag,float x,float y)304 void ArcTo(float rx, float ry, 305 float angle, 306 bool largeArcFlag, 307 bool sweepFlag, 308 float x, float y) 309 { 310 if (vertices_.GetTotalVertices() && IsVertex(vertices_.LastCommand())) { 311 const float epsilon = 1e-30; 312 float x0 = 0.0f; 313 float y0 = 0.0f; 314 vertices_.LastVertex(&x0, &y0); 315 316 rx = MATH_ABS(rx); 317 ry = MATH_ABS(ry); 318 if (rx < epsilon || ry < epsilon) { 319 LineTo(x, y); 320 return; 321 } 322 if (CalcDistance(x0, y0, x, y) < epsilon) { 323 return; 324 } 325 #if defined(GRAPHIC_ENABLE_BEZIER_ARC_FLAG) && GRAPHIC_ENABLE_BEZIER_ARC_FLAG 326 BezierArcSvg bezierArcSvg(x0, y0, rx, ry, angle, largeArcFlag, sweepFlag, x, y); 327 if (bezierArcSvg.RadiiOK()) { 328 JoinPath(bezierArcSvg); 329 } else { 330 LineTo(x, y); 331 } 332 #else 333 LineTo(x, y); 334 #endif 335 } else { 336 MoveTo(x, y); 337 } 338 } 339 340 void EndPoly(uint32_t flags = PATH_FLAGS_CLOSE) 341 { 342 if (IsVertex(vertices_.LastCommand())) { 343 vertices_.AddVertex(0.0f, 0.0f, PATH_CMD_END_POLY | flags); 344 } 345 } 346 /** 347 * @brief ClosePolygon Closed polygon path 348 * @param flags 349 */ 350 void ClosePolygon(uint32_t flags = PATH_FLAGS_NONE) 351 { 352 EndPoly(PATH_FLAGS_CLOSE | flags); 353 } 354 355 /** 356 * @brief Returns the number of vertices. 357 * @return Returns the number of vertices. 358 * @since 1.0 359 * @version 1.0 360 */ GetTotalVertices()361 uint32_t GetTotalVertices() const 362 { 363 return vertices_.GetTotalVertices(); 364 } 365 366 /** 367 * @brief Returns the coordinates of the last vertex. 368 * @param x Used to obtain the x-axis coordinates of the last vertex. 369 * @param y Used to obtain the y-axis coordinates of the last vertex. 370 * @return Returns the instruction type corresponding to the vertex. 371 * @since 1.0 372 * @version 1.0 373 */ LastVertex(float * x,float * y)374 uint32_t LastVertex(float* x, float* y) const 375 { 376 return vertices_.LastVertex(x, y); 377 } 378 /** 379 * @brief Gets the coordinates of a particular vertex. 380 * @param idx Vertex subscript. 381 * @param x Used to obtain the x-axis coordinates of vertices. 382 * @param y Used to obtain the y-axis coordinates of vertices. 383 * @return Returns the instruction type corresponding to the vertex. 384 * @since 1.0 385 * @version 1.0 386 */ 387 uint32_t GenerateVertex(uint32_t idx, float* x, float* y) const; 388 389 /** 390 * @brief Iterator fallback to a vertex。 391 * @param pathId The vertex sequence number of the fallback. 392 * @since 1.0 393 * @version 1.0 394 */ Rewind(uint32_t pathId)395 void Rewind(uint32_t pathId) 396 { 397 iterator_ = pathId; 398 } 399 400 /** 401 * @brief Gets the coordinates of the next vertex. 402 * @param x Used to obtain the x-axis coordinates of vertices. 403 * @param y Used to obtain the y-axis coordinates of vertices. 404 * @return Returns the instruction type corresponding to the next vertex. 405 * @since 1.0 406 * @version 1.0 407 */ GenerateVertex(float * x,float * y)408 uint32_t GenerateVertex(float* x, float* y) 409 { 410 if (iterator_ >= vertices_.GetTotalVertices()) { 411 return PATH_CMD_STOP; 412 } 413 return vertices_.GenerateVertex(iterator_++, x, y); 414 } 415 #if defined(GRAPHIC_ENABLE_BEZIER_ARC_FLAG) && GRAPHIC_ENABLE_BEZIER_ARC_FLAG 416 /** 417 * @brief Connection path. 418 * @param vs Vertex source to connect. 419 * @param pathId Connection location. 420 * @since 1.0 421 * @version 1.0 422 */ 423 void ConcatPath(BezierArc& path, uint32_t pathId = 0) 424 { 425 float x; 426 float y; 427 uint32_t cmd; 428 path.Rewind(pathId); 429 while (!IsStop(cmd = path.GenerateVertex(&x, &y))) { 430 vertices_.AddVertex(x, y, cmd); 431 } 432 } 433 434 /** 435 * @brief Add vertex source to existing source. 436 * @param vs Vertex source to join. 437 * @param pathId Join location. 438 * @since 1.0 439 * @version 1.0 440 */ 441 void JoinPath(BezierArcSvg& path, uint32_t pathId = 0) 442 { 443 float x; 444 float y; 445 uint32_t pathCommand; 446 path.Rewind(pathId); 447 pathCommand = path.GenerateVertex(&x, &y); 448 if (!IsStop(pathCommand)) { 449 if (IsVertex(pathCommand)) { 450 float x0; 451 float y0; 452 uint32_t cmd0 = LastVertex(&x0, &y0); 453 if (IsVertex(cmd0) && (CalcDistance(x, y, x0, y0) > VERTEX_DIST_EPSILON)) { 454 if (IsMoveTo(pathCommand)) { 455 pathCommand = PATH_CMD_LINE_TO; 456 } 457 vertices_.AddVertex(x, y, pathCommand); 458 } else if (IsStop(cmd0)) { 459 pathCommand = PATH_CMD_MOVE_TO; 460 vertices_.AddVertex(x, y, pathCommand); 461 } else { 462 if (IsMoveTo(pathCommand)) { 463 pathCommand = PATH_CMD_LINE_TO; 464 } 465 vertices_.AddVertex(x, y, pathCommand); 466 } 467 } 468 for (; !IsStop(pathCommand = path.GenerateVertex(&x, &y));) { 469 uint32_t pathCmd; 470 if (IsMoveTo(pathCommand)) { 471 pathCmd = uint32_t(PATH_CMD_LINE_TO); 472 } else { 473 pathCmd = pathCommand; 474 } 475 vertices_.AddVertex(x, y, pathCmd); 476 } 477 } 478 } 479 #endif 480 private: 481 VertexBlockStorage vertices_; 482 uint32_t iterator_; 483 }; 484 } // namespace OHOS 485 #endif 486