1 /* 2 * Copyright (c) 2021-2024 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 PATH_H 17 #define PATH_H 18 19 #include <memory> 20 #include <vector> 21 22 #include "common/rs_macros.h" 23 #include "drawing/engine_adapter/impl_interface/path_impl.h" 24 #include "utils/drawing_macros.h" 25 #include "utils/matrix.h" 26 #include "utils/point.h" 27 #include "utils/rect.h" 28 29 #ifdef WINDOWS_PLATFORM 30 #ifdef DIFFERENCE 31 #undef DIFFERENCE 32 #endif 33 #ifdef WINDING 34 #undef WINDING 35 #endif 36 #endif 37 38 namespace OHOS { 39 namespace Rosen { 40 namespace Drawing { 41 enum class PathDirection { 42 CW_DIRECTION, 43 CCW_DIRECTION, 44 }; 45 46 enum class PathFillType { 47 WINDING, 48 EVENTODD, 49 INVERSE_WINDING, 50 INVERSE_EVENTODD, 51 }; 52 53 enum class PathOp { 54 DIFFERENCE, 55 INTERSECT, 56 UNION, 57 XOR, 58 REVERSE_DIFFERENCE, 59 }; 60 61 enum class PathAddMode { 62 APPEND_PATH_ADD_MODE, 63 EXTEND_PATH_ADD_MODE, 64 }; 65 66 enum class PathMeasureMatrixFlags { 67 GET_POSITION_MATRIX, 68 GET_TANGENT_MATRIX, 69 GET_POS_AND_TAN_MATRIX, 70 }; 71 72 class DRAWING_API Path { 73 public: 74 Path() noexcept; 75 Path(const Path& p) noexcept; 76 Path &operator=(const Path& p) noexcept; 77 virtual ~Path(); 78 GetDrawingType()79 virtual DrawingType GetDrawingType() const 80 { 81 return DrawingType::COMMON; 82 } 83 84 /** 85 * @brief Parses the SVG format string that describes the drawing path, and sets the Path. 86 * 87 * @param str A string in SVG format that describes the drawing path. 88 * @return true if build succeeded, otherwise false. 89 */ 90 virtual bool BuildFromSVGString(const std::string& str); 91 92 /** 93 * @brief Parses into a string in SVG format that describes the Path. 94 * @return Returns a string in SVG format. 95 */ 96 std::string ConvertToSVGString() const; 97 98 /** 99 * @brief Adds beginning of contour at (x, y). 100 * 101 * @param x contour start x-axis 102 * @param y contour start y-axis 103 */ 104 virtual void MoveTo(scalar x, scalar y); 105 106 /** 107 * @brief Adds line from last point to Point(x, y). 108 * 109 * @param x x-axis of end point of added line 110 * @param y y-axis of end point of added line 111 */ 112 virtual void LineTo(scalar x, scalar y); 113 114 /** 115 * @brief Appends arc to Path. Arc added is part of ellipse bounded by oval, from startAngle through sweepAngle. 116 * Both startAngle and sweepAngle are measured in degrees, where zero degrees is aligned with the positive x-axis, 117 * and positive sweeps extends arc clockwise. ArcTo() adds line connecting Path last Point to initial arc Point if 118 * forceMoveTo is false and Path is not empty. Otherwise, added contour begins with first point of arc. 119 * Angles greater than -360 and less than 360 are treated modulo 360. 120 * 121 * @param pt1X left of bounds of ellipse containing arc 122 * @param pt1Y top of bounds of ellipse containing arc 123 * @param pt2X right of bounds of ellipse containing arc 124 * @param pt2Y bottom of bounds of ellipse containing arc 125 * @param startAngle starting angle of arc in degrees 126 * @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360 127 */ 128 virtual void ArcTo(scalar pt1X, scalar pt1Y, scalar pt2X, scalar pt2Y, scalar startAngle, scalar sweepAngle); 129 virtual void ArcTo(const Point& pt1, const Point& pt2, scalar startAngle, scalar sweepAngle); 130 /** 131 * @brief Appends arc to Path. Arc is implemented by one or more conics weighted to describe part of oval 132 * with radii (rx, ry) rotated by xAxisRotate degrees. Arc curves from last Path Point to (endX, endY), choosing 133 * one of four possible routes: clockwise or counterclockwise, and smaller or larger. Arc sweep is always 134 * less than 360 degrees. ArcTo() appends line to (endX, endY) if either radii are zero, or if last Path Point 135 * equals (endX, endY). ArcTo() scales radii (rx, ry) to fit last Path Point and (endX, endY) if both are greater 136 * than zero but too small. 137 * 138 * @param rx radius on x-axis before x-axis rotation 139 * @param ry radius on y-axis before x-axis rotation 140 * @param angle x-axis rotation in degrees; positive values are clockwise 141 * @param direction chooses clockwise or counterclockwise arc 142 * @param endX x-axis end of arc 143 * @param endY y-axis end of arc 144 */ 145 virtual void ArcTo(scalar rx, scalar ry, scalar angle, PathDirection direction, scalar endX, scalar endY); 146 147 /** 148 * @brief Appends arc to Path, after appending line if needed. Arc is implemented by conic weighted 149 * to describe part of circle. Arc is contained by tangent from last Path point to (x1, y1), and tangent 150 * from (x1, y1) to (x2, y2). Arc is part of circle sized to radius, positioned so it touches both tangent lines. 151 * If last Path Point does not start Arc, ArcTo appends connecting Line to Path. The length of Vector from 152 * (x1, y1) to (x2, y2) does not affect Arc. Arc sweep is always less than 180 degrees. If radius is zero, 153 * or if tangents are nearly parallel, ArcTo appends Line from last Path Point to (x1, y1). 154 * 155 * @param x1 x-axis value common to pair of tangents 156 * @param y1 y-axis value common to pair of tangents 157 * @param x2 x-axis value end of second tangent 158 * @param y2 y-axis value end of second tangent 159 * @param radius distance from arc to circle center 160 */ 161 virtual void ArcTo(scalar x1, scalar y1, scalar x2, scalar y2, scalar radius); 162 163 /** 164 * @brief Adds cubic from last point towards (ctrlPt1X, ctrlPt1Y), then towards (ctrlPt2X, ctrlPt2Y), 165 * ending at (endPtX, endPtY). 166 * 167 * @param ctrlPt1X x-axis of first control Point of cubic 168 * @param ctrlPt1Y y-axis of first control Point of cubic 169 * @param ctrlPt2X x-axis of second control Point of cubic 170 * @param ctrlPt2Y y-axis of second control Point of cubic 171 * @param endPtX x-axis of end Point of cubic 172 * @param endPtY y-axis of end Point of cubic 173 */ 174 virtual void CubicTo( 175 scalar ctrlPt1X, scalar ctrlPt1Y, scalar ctrlPt2X, scalar ctrlPt2Y, scalar endPtX, scalar endPtY); 176 177 /** 178 * @brief Adds cubic from last point towards Point ctrlPt1, then towards Point ctrlPt2, ending at Point endPt. 179 * 180 * @param ctrlPt1 first control Point of cubic 181 * @param ctrlPt2 second control Point of cubic 182 * @param endPt end Point of cubic 183 */ 184 virtual void CubicTo(const Point& ctrlPt1, const Point& ctrlPt2, const Point& endPt); 185 186 /** 187 * @brief Adds quad from last point towards (ctrlPtX, ctrlPtY), to (endPtX, endPtY). 188 * 189 * @param ctrlPtX control Point of quad on x-axis 190 * @param ctrlPtY control Point of quad on y-axis 191 * @param endPtX end Point of quad on x-axis 192 * @param endPtY end Point of quad on y-axis 193 */ 194 virtual void QuadTo(scalar ctrlPtX, scalar ctrlPtY, scalar endPtX, scalar endPtY); 195 196 /** 197 * @brief Adds quad from last point towards control Point, to end Point. 198 * 199 * @param ctrlPt control Point of added quad 200 * @param endPt end Point of added quad 201 */ 202 virtual void QuadTo(const Point& ctrlPt, const Point endPt); 203 /** 204 * @brief Draws a conic from the last point of a path to the target point. 205 * 206 * @param ctrlX Indicates the x coordinate of the control point 207 * @param ctrlY Indicates the y coordinate of the control point 208 * @param endX Indicates the x coordinate of the target point 209 * @param endY Indicates the y coordinate of the target point 210 * @param weight Indicates the weight of added conic. 211 */ 212 virtual void ConicTo(scalar ctrlX, scalar ctrlY, scalar endX, scalar endY, scalar weight); 213 214 /** 215 * @brief Adds beginning of contour relative to last point. If Path is empty, 216 * starts contour at (dx, dy). Otherwise, start contour at last point offset by (dx, dy). 217 * Function name stands for "relative move to". 218 * 219 * @param dx offset from last point to contour start on x-axis 220 * @param dy offset from last point to contour start on y-axis 221 */ 222 virtual void RMoveTo(scalar dx, scalar dy); 223 224 /** 225 * @brief Adds line from last point to vector (dx, dy). 226 * 227 * @param dx offset from last point to line end on x-axis 228 * @param dy offset from last point to line end on y-axis 229 */ 230 virtual void RLineTo(scalar dx, scalar dy); 231 232 /** 233 * @brief Appends arc to Path, relative to last Path Point. 234 * 235 * @param rx radius before x-axis rotation 236 * @param ry radius before y-axis rotation 237 * @param angle x-axis rotation in degrees; positive values are clockwise 238 * @param direction chooses clockwise or counterclockwise arc 239 * @param dx x-axis offset end of arc from last Path Point 240 * @param dy y-axis offset end of arc from last Path Point 241 */ 242 virtual void RArcTo(scalar rx, scalar ry, scalar angle, PathDirection direction, scalar dx, scalar dy); 243 244 /** 245 * @brief Adds cubic from last point towards vector (dx1, dy1), then towards vector (dx2, dy2), 246 * to vector (dx3, dy3). 247 * 248 * @param dx1 offset from last point to first cubic control on x-axis 249 * @param dy1 offset from last point to first cubic control on y-axis 250 * @param dx2 offset from last point to second cubic control on x-axis 251 * @param dy2 offset from last point to second cubic control on y-axis 252 * @param dx3 offset from last point to cubic end on x-axis 253 * @param dy3 offset from last point to cubic end on y-axis 254 */ 255 virtual void RCubicTo(scalar dx1, scalar dy1, scalar dx2, scalar dy2, scalar dx3, scalar dy3); 256 257 /** 258 * @brief Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2). 259 * 260 * @param dx1 offset from last point to quad control on x-axis 261 * @param dy1 offset from last point to quad control on y-axis 262 * @param dx2 offset from last point to quad end on x-axis 263 * @param dy2 offset from last point to quad end on y-axis 264 */ 265 virtual void RQuadTo(scalar dx1, scalar dy1, scalar dx2, scalar dy2); 266 267 /** 268 * @brief Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2), 269 * weighted by w. If Path is empty, or last Path::Verb is kClose_Verb, 270 * last point is set to (0, 0) before adding conic. 271 * 272 * @param ctrlPtX offset from last point to conic control on x-axis 273 * @param ctrlPtY offset from last point to conic control on y-axis 274 * @param endPtX offset from last point to conic end on x-axis 275 * @param endPtY offset from last point to conic end on y-axis 276 * @param weight weight of added conic 277 */ 278 virtual void RConicTo(scalar ctrlPtX, scalar ctrlPtY, scalar endPtX, scalar endPtY, scalar weight); 279 280 /** 281 * @brief Adds a new contour to the path, defined by the rect, and wound in the specified direction. 282 * 283 * @param rect Rect to add as a closed contour 284 * @param dir Path::PathDirection to orient the new contour 285 */ 286 virtual void AddRect(const Rect& rect, PathDirection dir = PathDirection::CW_DIRECTION); 287 288 /** 289 * @brief Adds a new contour to the path, defined by the rect, and wound in the specified direction. 290 * 291 * @param rect Rect to add as a closed contour 292 * @param dir Path::PathDirection to orient the new contour 293 * @param start Initial corner of Rect to add 294 */ 295 virtual void AddRect(const Rect& rect, unsigned start, PathDirection dir = PathDirection::CW_DIRECTION); 296 virtual void AddRect( 297 scalar left, scalar top, scalar right, scalar bottom, PathDirection dir = PathDirection::CW_DIRECTION); 298 299 /** 300 * @brief Adds oval to Path. Oval is upright ellipse bounded by Rect oval with radii equal to 301 * half oval width and half oval height. Oval begins at start and continues clockwise if dir is 302 * PathDirection::CW_DIRECTION, counterclockwise if dir is PathDirection::CCW_DIRECTION. 303 * 304 * @param oval bounds of ellipse added 305 * @param dir Path::PathDirection to wind ellipse 306 */ 307 virtual void AddOval(const Rect& oval, PathDirection dir = PathDirection::CW_DIRECTION); 308 309 /** 310 * @brief Adds oval to Path. Oval is upright ellipse bounded by Rect oval with radii equal to 311 * half oval width and half oval height. Oval begins at start and continues clockwise if dir is 312 * PathDirection::CW_DIRECTION, counterclockwise if dir is PathDirection::CCW_DIRECTION. 313 * 314 * @param oval bounds of ellipse added 315 * @param start Index of initial point of ellipse 316 * @param dir Path::PathDirection to wind ellipse 317 */ 318 virtual void AddOval(const Rect& oval, unsigned start, PathDirection dir = PathDirection::CCW_DIRECTION); 319 320 /** 321 * @brief Appends arc to Path, as the start of new contour. Arc added is part of ellipse bounded by oval, 322 * from startAngle through sweepAngle. Both startAngle and sweepAngle are measured in degrees, where zero 323 * degrees is aligned with the positive x-axis, and positive sweeps extends arc clockwise. If sweepAngle <= -360, 324 * or sweepAngle >= 360; and startAngle modulo 90 is nearly zero, append oval instead of arc. Otherwise, sweepAngle 325 * values are treated modulo 360, and arc may or may not draw depending on numeric rounding. 326 * 327 * @param oval bounds of ellipse containing arc 328 * @param startAngle starting angle of arc in degrees 329 * @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360 330 */ 331 virtual void AddArc(const Rect& oval, scalar startAngle, scalar sweepAngle); 332 333 /** 334 * @brief Adds contour created from line array, adding (count - 1) line segments. 335 * 336 * @param points array of line sharing end and start Point 337 * @param count length of Point array 338 * @param close true to add line connecting contour end and start 339 */ 340 virtual void AddPoly(const std::vector<Point>& points, int count, bool close); 341 virtual void AddCircle(scalar x, scalar y, scalar radius, PathDirection dir = PathDirection::CW_DIRECTION); 342 virtual void AddRoundRect( 343 const Rect& rect, scalar xRadius, scalar yRadius, PathDirection dir = PathDirection::CW_DIRECTION); 344 345 /** 346 * @brief Adds the circle rectangle to the Path. 347 * @param roundRect The boundary and radius of a roundRect. 348 * @param dir Direction of rotation. 349 */ 350 virtual void AddRoundRect(const RoundRect& roundRect, PathDirection dir = PathDirection::CW_DIRECTION); 351 352 /** 353 * @brief Appends src to Path, offset by (dx, dy). 354 * 355 * @param src Path Point, and conic weights to add 356 * @param dx offset added to src Point array x-axis coordinates 357 * @param dy offset added to src Point array y-axis coordinates 358 * @param mode the add path's add mode 359 */ 360 virtual void AddPath(const Path& src, scalar dx, scalar dy, PathAddMode mode = PathAddMode::APPEND_PATH_ADD_MODE); 361 362 /** 363 * @brief Appends src to Path. 364 * 365 * @param src Path Point, and conic weights to add 366 * @param mode the add path's add mode 367 */ 368 virtual void AddPath(const Path& src, PathAddMode mode = PathAddMode::APPEND_PATH_ADD_MODE); 369 370 /** 371 * @brief Appends src to Path, transformed by matrix. 372 * Transformed curves may have different verbs, Point, and conic weights. 373 * 374 * @param src Path Point, and conic weights to add 375 * @param matrix transform applied to src 376 * @param mode the add path's add mode 377 */ 378 virtual void AddPath(const Path& src, const Matrix& matrix, PathAddMode mode = PathAddMode::APPEND_PATH_ADD_MODE); 379 virtual bool Contains(scalar x, scalar y) const; 380 381 /** 382 * @brief Adds the src from back forward to the Path. 383 * @param src To add Path. 384 */ 385 virtual void ReverseAddPath(const Path& src); 386 387 /** 388 * @brief Returns minimum and maximum axes values of Point array. Returns (0, 0, 0, 0) 389 * if Path contains no points. Returned bounds width and height may be larger or smaller 390 * than area affected when Path is drawn. 391 * 392 * @return Rect bounds of all Point in Point array 393 */ 394 Rect GetBounds() const; 395 396 /** 397 * @brief Sets PathFillType, the rule used to fill Path. While there is no check that ft is legal, 398 * values outside of PathFillType are not supported. 399 * 400 * @param fillstyle enum PathFillType 401 */ 402 virtual void SetFillStyle(PathFillType fillstyle); 403 404 /** 405 * @brief Interpolates between Path with Point array of equal size. 406 * 407 * @param ending Point array averaged with this Point array 408 * @param weight contribution of this Point array, and one minus contribution of ending Point array 409 * @param out Path replaced by interpolated averages 410 * @return true if Path contain same number of Point 411 */ 412 bool Interpolate(const Path& ending, scalar weight, Path& out); 413 414 /** 415 * @brief Two equal number of point set path objects are weighted interpolated, and the sets Path. 416 * @param src The number of point sets of the src Path. 417 * @param ending The number of point sets of the ending Path. 418 * @param weight The weight value is between 0 and 1. 419 * @return true if build succeeded, otherwise false. 420 */ 421 virtual bool BuildFromInterpolate(const Path& src, const Path& ending, scalar weight); 422 423 /** 424 * @brief Transforms Point array, and weight by matrix. Path is replaced by transformed data. 425 * 426 * @param matrix Matrix to apply to Path 427 */ 428 virtual void Transform(const Matrix& matrix); 429 430 /** 431 * @brief Transforms verb array, Point array, and weight by matrix. 432 * Transform may change verbs and increase their number. 433 * Transformed Path replaces dst; if dst is nullptr, original data is replaced. 434 * 435 * @param matrix Matrix to apply to Path 436 * @param dst Overwritten, transformed copy of Path; may be nullptr 437 * @param applyPerspectiveClip Whether to apply perspective clipping 438 */ 439 virtual void TransformWithPerspectiveClip(const Matrix& matrix, Path* dst, bool applyPerspectiveClip); 440 441 /** 442 * @brief Offsets Point array by (dx, dy). Path is replaced by offset data. 443 * 444 * @param dx offset added to Point array x-axis coordinates 445 * @param dy offset added to Point array y-axis coordinates 446 */ 447 virtual void Offset(scalar dx, scalar dy); 448 449 /** 450 * @brief Offsets Point array by (dx, dy). Path is replaced by offset data. 451 * 452 * @param dst The pointer of point sets of the dst Path 453 * @param dx offset added to Point array x-axis coordinates 454 * @param dy offset added to Point array y-axis coordinates 455 */ 456 virtual void Offset(Path* dst, scalar dx, scalar dy); 457 458 virtual bool Op(const Path& path1, Path& path2, PathOp op); 459 460 /** 461 * @brief Checks whether the Path is valid. 462 */ 463 bool IsValid() const; 464 465 /** 466 * @brief Sets Path to its initial state. Removes Point array, and weights, and sets PathFillType to 467 * PathFillType::Winding. Internal storage associated with Path is released. 468 */ 469 virtual void Reset(); 470 471 /** 472 * @brief A closed contour connects the first and last Point with line, forming a continuous loop. 473 */ 474 virtual void Close(); 475 476 /** 477 * @brief Gets the length of the current path object. 478 * @param forceClosed Whether to close the Path. 479 * @return Returns the length of the current path object. 480 */ 481 scalar GetLength(bool forceClosed) const; 482 483 /** 484 * @brief Gets the position and tangent of the distance from the starting position of the Path. 485 * @param distance The distance from the start of the Path, should be greater than 0 and less than 'GetLength()' 486 * @param position Sets to the position of distance from the starting position of the Path. 487 * @param tangent Sets to the tangent of distance from the starting position of the Path. 488 * @param forceClosed Whether to close the Path. 489 * @return Returns true if succeeded, otherwise false. 490 */ 491 bool GetPositionAndTangent(scalar distance, Point& position, Point& tangent, bool forceClosed) const; 492 493 /** 494 * @brief Determines whether the current contour is closed. 495 * @param forceClosed Whether to close the Path. 496 * @return Returns true if the current contour is closed, otherwise false. 497 */ 498 bool IsClosed(bool forceClosed) const; 499 500 bool GetMatrix(bool forceClosed, float distance, Matrix* matrix, 501 PathMeasureMatrixFlags flags = PathMeasureMatrixFlags::GET_POS_AND_TAN_MATRIX); 502 503 std::shared_ptr<Data> Serialize() const; 504 bool Deserialize(std::shared_ptr<Data> data); 505 506 template<typename T> GetImpl()507 T* GetImpl() const 508 { 509 return impl_->DowncastingTo<T>(); 510 } 511 512 private: 513 std::shared_ptr<PathImpl> impl_; 514 }; 515 } // namespace Drawing 516 } // namespace Rosen 517 } // namespace OHOS 518 #endif 519