1 module skia.SKPath; 2 3 import skia.Definitions; 4 import skia.Exceptions; 5 import skia.MathTypes; 6 import skia.SKObject; 7 import skia.SkiaApi; 8 import skia.SKRoundRect; 9 import skia.SKMatrix; 10 import skia.SKString; 11 12 import std.experimental.logger; 13 14 class SKPath : SKObject, ISKSkipObjectRegistration { 15 this(void* handle, bool owns) { 16 super(handle, owns); 17 } 18 19 this() { 20 this(SkiaApi.sk_path_new(), true); 21 if (Handle is null) { 22 throw new InvalidOperationException("Unable to create a new SKPath instance."); 23 } 24 } 25 26 this(SKPath path) { 27 this(SkiaApi.sk_path_clone(cast(sk_path_t*) path.Handle), true); 28 if (Handle is null) { 29 throw new InvalidOperationException("Unable to copy the SKPath instance."); 30 } 31 } 32 33 // protected override void Dispose (bool disposing) 34 // { 35 // return super.Dispose (disposing); 36 // } 37 38 // override void Dispose() 39 // { 40 // return super.Dispose(); 41 // } 42 43 protected override void DisposeNative() { 44 return SkiaApi.sk_path_delete(cast(sk_path_t*) Handle); 45 } 46 47 SKPathFillType FillType() { 48 return SkiaApi.sk_path_get_filltype(cast(sk_path_t*) Handle); 49 } 50 51 void FillType(SKPathFillType value) { 52 SkiaApi.sk_path_set_filltype(cast(sk_path_t*) Handle, value); 53 } 54 55 SKPathConvexity Convexity() { 56 return SkiaApi.sk_path_get_convexity(cast(sk_path_t*) Handle); 57 } 58 59 void Convexity(SKPathConvexity value) { 60 SkiaApi.sk_path_set_convexity(cast(sk_path_t*) Handle, value); 61 } 62 63 bool IsConcave() { 64 return Convexity == SKPathConvexity.Concave; 65 } 66 67 bool IsEmpty() { 68 return VerbCount == 0; 69 } 70 71 bool IsOval() { 72 return SkiaApi.sk_path_is_oval(cast(sk_path_t*) Handle, null); 73 } 74 75 bool IsRoundRect() { 76 return SkiaApi.sk_path_is_rrect(cast(sk_path_t*) Handle, null); 77 } 78 79 bool IsLine() { 80 return SkiaApi.sk_path_is_line(cast(sk_path_t*) Handle, null); 81 } 82 83 bool IsRect() { 84 return SkiaApi.sk_path_is_rect(cast(sk_path_t*) Handle, null, null, null); 85 } 86 87 SKPathSegmentMask SegmentMasks() { 88 return cast(SKPathSegmentMask) SkiaApi.sk_path_get_segment_masks(cast(sk_path_t*) Handle); 89 } 90 91 int VerbCount() { 92 return SkiaApi.sk_path_count_verbs(cast(sk_path_t*) Handle); 93 } 94 95 int PointCount() { 96 return SkiaApi.sk_path_count_points(cast(sk_path_t*) Handle); 97 } 98 99 // SKPoint this[int index]() 100 // { 101 // return GetPoint (index); 102 // } 103 104 SKPoint[] Points() { 105 return GetPoints(PointCount); 106 } 107 108 SKPoint LastPoint() { 109 SKPoint point; 110 SkiaApi.sk_path_get_last_point(cast(sk_path_t*) Handle, &point); 111 return point; 112 } 113 114 SKRect Bounds() { 115 SKRect rect; 116 SkiaApi.sk_path_get_bounds(cast(sk_path_t*) Handle, &rect); 117 return rect; 118 } 119 120 SKRect TightBounds() { 121 SKRect rect; 122 if (GetTightBounds(rect)) { 123 return rect; 124 } else { 125 return SKRect.Empty; 126 } 127 128 } 129 130 SKRect GetOvalBounds() { 131 SKRect bounds; 132 if (SkiaApi.sk_path_is_oval(cast(sk_path_t*) Handle, &bounds)) { 133 return bounds; 134 } else { 135 return SKRect.Empty; 136 } 137 } 138 139 SKRoundRect GetRoundRect() { 140 auto rrect = new SKRoundRect(); 141 auto result = SkiaApi.sk_path_is_rrect(cast(sk_path_t*) Handle, 142 cast(sk_rrect_t*) rrect.Handle); 143 if (result) { 144 return rrect; 145 } else { 146 rrect.Dispose(); 147 return null; 148 } 149 } 150 151 SKPoint[] GetLine() { 152 auto temp = new SKPoint[2]; 153 SKPoint* t = temp.ptr; 154 { 155 auto result = SkiaApi.sk_path_is_line(cast(sk_path_t*) Handle, t); 156 if (result) { 157 return temp; 158 } else { 159 return null; 160 } 161 } 162 } 163 164 SKRect GetRect() { 165 bool isClosed; 166 SKPathDirection direction; 167 return GetRect(isClosed, direction); 168 } 169 170 SKRect GetRect(out bool isClosed, out SKPathDirection direction) { 171 byte c; 172 SKPathDirection* d = &direction; 173 { 174 SKRect rect; 175 auto result = SkiaApi.sk_path_is_rect(cast(sk_path_t*) Handle, 176 &rect, cast(bool*)&c, d); 177 isClosed = c > 0; 178 if (result) { 179 return rect; 180 } else { 181 return SKRect.Empty; 182 } 183 } 184 } 185 186 SKPoint GetPoint(int index) { 187 if (index < 0 || index >= PointCount) 188 throw new ArgumentOutOfRangeException(index.stringof); 189 190 SKPoint point; 191 SkiaApi.sk_path_get_point(cast(sk_path_t*) Handle, index, &point); 192 return point; 193 } 194 195 SKPoint[] GetPoints(int max) { 196 auto points = new SKPoint[max]; 197 GetPoints(points, max); 198 return points; 199 } 200 201 int GetPoints(SKPoint[] points, int max) { 202 SKPoint* p = points.ptr; 203 return SkiaApi.sk_path_get_points(cast(sk_path_t*) Handle, p, max); 204 } 205 206 bool Contains(float x, float y) { 207 return SkiaApi.sk_path_contains(cast(sk_path_t*) Handle, x, y); 208 } 209 210 void Offset(SKPoint offset) { 211 return Offset(offset.X, offset.Y); 212 } 213 214 void Offset(float dx, float dy) { 215 return Transform(SKMatrix.CreateTranslation(dx, dy)); 216 } 217 218 void MoveTo(SKPoint point) { 219 return SkiaApi.sk_path_move_to(cast(sk_path_t*) Handle, point.X, point.Y); 220 } 221 222 void MoveTo(float x, float y) { 223 return SkiaApi.sk_path_move_to(cast(sk_path_t*) Handle, x, y); 224 } 225 226 void RMoveTo(SKPoint point) { 227 return SkiaApi.sk_path_rmove_to(cast(sk_path_t*) Handle, point.X, point.Y); 228 } 229 230 void RMoveTo(float dx, float dy) { 231 return SkiaApi.sk_path_rmove_to(cast(sk_path_t*) Handle, dx, dy); 232 } 233 234 void LineTo(SKPoint point) { 235 return SkiaApi.sk_path_line_to(cast(sk_path_t*) Handle, point.X, point.Y); 236 } 237 238 void LineTo(float x, float y) { 239 return SkiaApi.sk_path_line_to(cast(sk_path_t*) Handle, x, y); 240 } 241 242 void RLineTo(SKPoint point) { 243 return SkiaApi.sk_path_rline_to(cast(sk_path_t*) Handle, point.X, point.Y); 244 } 245 246 void RLineTo(float dx, float dy) { 247 return SkiaApi.sk_path_rline_to(cast(sk_path_t*) Handle, dx, dy); 248 } 249 250 void QuadTo(SKPoint point0, SKPoint point1) { 251 return SkiaApi.sk_path_quad_to(cast(sk_path_t*) Handle, point0.X, 252 point0.Y, point1.X, point1.Y); 253 } 254 255 void QuadTo(float x0, float y0, float x1, float y1) { 256 return SkiaApi.sk_path_quad_to(cast(sk_path_t*) Handle, x0, y0, x1, y1); 257 } 258 259 void RQuadTo(SKPoint point0, SKPoint point1) { 260 return SkiaApi.sk_path_rquad_to(cast(sk_path_t*) Handle, point0.X, 261 point0.Y, point1.X, point1.Y); 262 } 263 264 void RQuadTo(float dx0, float dy0, float dx1, float dy1) { 265 return SkiaApi.sk_path_rquad_to(cast(sk_path_t*) Handle, dx0, dy0, dx1, dy1); 266 } 267 268 void ConicTo(SKPoint point0, SKPoint point1, float w) { 269 return SkiaApi.sk_path_conic_to(cast(sk_path_t*) Handle, point0.X, 270 point0.Y, point1.X, point1.Y, w); 271 } 272 273 void ConicTo(float x0, float y0, float x1, float y1, float w) { 274 return SkiaApi.sk_path_conic_to(cast(sk_path_t*) Handle, x0, y0, x1, y1, w); 275 } 276 277 void RConicTo(SKPoint point0, SKPoint point1, float w) { 278 return SkiaApi.sk_path_rconic_to(cast(sk_path_t*) Handle, point0.X, 279 point0.Y, point1.X, point1.Y, w); 280 } 281 282 void RConicTo(float dx0, float dy0, float dx1, float dy1, float w) { 283 return SkiaApi.sk_path_rconic_to(cast(sk_path_t*) Handle, dx0, dy0, dx1, dy1, w); 284 } 285 286 void CubicTo(SKPoint point0, SKPoint point1, SKPoint point2) { 287 return SkiaApi.sk_path_cubic_to(cast(sk_path_t*) Handle, point0.X, 288 point0.Y, point1.X, point1.Y, point2.X, point2.Y); 289 } 290 291 void CubicTo(float x0, float y0, float x1, float y1, float x2, float y2) { 292 return SkiaApi.sk_path_cubic_to(cast(sk_path_t*) Handle, x0, y0, x1, y1, x2, y2); 293 } 294 295 void RCubicTo(SKPoint point0, SKPoint point1, SKPoint point2) { 296 return SkiaApi.sk_path_rcubic_to(cast(sk_path_t*) Handle, point0.X, 297 point0.Y, point1.X, point1.Y, point2.X, point2.Y); 298 } 299 300 void RCubicTo(float dx0, float dy0, float dx1, float dy1, float dx2, float dy2) { 301 return SkiaApi.sk_path_rcubic_to(cast(sk_path_t*) Handle, dx0, dy0, dx1, dy1, dx2, dy2); 302 } 303 304 void ArcTo(SKPoint r, float xAxisRotate, SKPathArcSize largeArc, 305 SKPathDirection sweep, SKPoint xy) { 306 return SkiaApi.sk_path_arc_to(cast(sk_path_t*) Handle, r.X, r.Y, 307 xAxisRotate, largeArc, sweep, xy.X, xy.Y); 308 } 309 310 void ArcTo(float rx, float ry, float xAxisRotate, SKPathArcSize largeArc, 311 SKPathDirection sweep, float x, float y) { 312 return SkiaApi.sk_path_arc_to(cast(sk_path_t*) Handle, rx, ry, 313 xAxisRotate, largeArc, sweep, x, y); 314 } 315 316 void ArcTo(SKRect oval, float startAngle, float sweepAngle, bool forceMoveTo) { 317 return SkiaApi.sk_path_arc_to_with_oval(cast(sk_path_t*) Handle, 318 &oval, startAngle, sweepAngle, forceMoveTo); 319 } 320 321 void ArcTo(SKPoint point1, SKPoint point2, float radius) { 322 return SkiaApi.sk_path_arc_to_with_points(cast(sk_path_t*) Handle, 323 point1.X, point1.Y, point2.X, point2.Y, radius); 324 } 325 326 void ArcTo(float x1, float y1, float x2, float y2, float radius) { 327 return SkiaApi.sk_path_arc_to_with_points(cast(sk_path_t*) Handle, x1, y1, x2, y2, radius); 328 } 329 330 void RArcTo(SKPoint r, float xAxisRotate, SKPathArcSize largeArc, 331 SKPathDirection sweep, SKPoint xy) { 332 return SkiaApi.sk_path_rarc_to(cast(sk_path_t*) Handle, r.X, r.Y, 333 xAxisRotate, largeArc, sweep, xy.X, xy.Y); 334 } 335 336 void RArcTo(float rx, float ry, float xAxisRotate, SKPathArcSize largeArc, 337 SKPathDirection sweep, float x, float y) { 338 return SkiaApi.sk_path_rarc_to(cast(sk_path_t*) Handle, rx, ry, 339 xAxisRotate, largeArc, sweep, x, y); 340 } 341 342 void Close() { 343 return SkiaApi.sk_path_close(cast(sk_path_t*) Handle); 344 } 345 346 void Rewind() { 347 return SkiaApi.sk_path_rewind(cast(sk_path_t*) Handle); 348 } 349 350 void Reset() { 351 return SkiaApi.sk_path_reset(cast(sk_path_t*) Handle); 352 } 353 354 void AddRect(SKRect rect, SKPathDirection direction = SKPathDirection.Clockwise) { 355 return SkiaApi.sk_path_add_rect(cast(sk_path_t*) Handle, &rect, direction); 356 } 357 358 void AddRect(SKRect rect, SKPathDirection direction, uint startIndex) { 359 if (startIndex > 3) 360 throw new ArgumentOutOfRangeException(startIndex.stringof, 361 "Starting index must be in the range of 0..3 (inclusive)."); 362 363 SkiaApi.sk_path_add_rect_start(cast(sk_path_t*) Handle, &rect, direction, startIndex); 364 } 365 366 void AddRoundRect(SKRoundRect rect, SKPathDirection direction = SKPathDirection.Clockwise) { 367 if (rect is null) 368 throw new ArgumentNullException(rect.stringof); 369 SkiaApi.sk_path_add_rrect(cast(sk_path_t*) Handle, 370 cast(sk_rrect_t*) rect.Handle, direction); 371 } 372 373 void AddRoundRect(SKRoundRect rect, SKPathDirection direction, uint startIndex) { 374 if (rect is null) 375 throw new ArgumentNullException(rect.stringof); 376 SkiaApi.sk_path_add_rrect_start(cast(sk_path_t*) Handle, 377 cast(sk_rrect_t*) rect.Handle, direction, startIndex); 378 } 379 380 void AddOval(SKRect rect, SKPathDirection direction = SKPathDirection.Clockwise) { 381 return SkiaApi.sk_path_add_oval(cast(sk_path_t*) Handle, &rect, direction); 382 } 383 384 void AddArc(SKRect oval, float startAngle, float sweepAngle) { 385 return SkiaApi.sk_path_add_arc(cast(sk_path_t*) Handle, &oval, startAngle, sweepAngle); 386 } 387 388 bool GetBounds(out SKRect rect) { 389 auto isEmpty = IsEmpty; 390 if (isEmpty) { 391 rect = SKRect.Empty; 392 } else { 393 SKRect* r = ▭ 394 SkiaApi.sk_path_get_bounds(cast(sk_path_t*) Handle, r); 395 } 396 return !isEmpty; 397 } 398 399 SKRect ComputeTightBounds() { 400 SKRect rect; 401 SkiaApi.sk_path_compute_tight_bounds(cast(sk_path_t*) Handle, &rect); 402 return rect; 403 } 404 405 void Transform(SKMatrix matrix) { 406 return SkiaApi.sk_path_transform(cast(sk_path_t*) Handle, &matrix); 407 } 408 409 void Transform(SKMatrix matrix, SKPath destination) { 410 if (destination is null) 411 throw new ArgumentNullException(destination.stringof); 412 413 SkiaApi.sk_path_transform_to_dest(cast(sk_path_t*) Handle, &matrix, 414 cast(sk_path_t*) destination.Handle); 415 } 416 417 void AddPath(SKPath other, float dx, float dy, SKPathAddMode mode = SKPathAddMode.Append) { 418 if (other is null) 419 throw new ArgumentNullException(other.stringof); 420 421 SkiaApi.sk_path_add_path_offset(cast(sk_path_t*) Handle, 422 cast(sk_path_t*) other.Handle, dx, dy, mode); 423 } 424 425 void AddPath(SKPath other, ref SKMatrix matrix, SKPathAddMode mode = SKPathAddMode.Append) { 426 if (other is null) 427 throw new ArgumentNullException(other.stringof); 428 429 SKMatrix* m = &matrix; 430 SkiaApi.sk_path_add_path_matrix(cast(sk_path_t*) Handle, 431 cast(sk_path_t*) other.Handle, m, mode); 432 } 433 434 void AddPath(SKPath other, SKPathAddMode mode = SKPathAddMode.Append) { 435 if (other is null) 436 throw new ArgumentNullException(other.stringof); 437 438 SkiaApi.sk_path_add_path(cast(sk_path_t*) Handle, cast(sk_path_t*) other.Handle, mode); 439 } 440 441 void AddPathReverse(SKPath other) { 442 if (other is null) 443 throw new ArgumentNullException(other.stringof); 444 445 SkiaApi.sk_path_add_path_reverse(cast(sk_path_t*) Handle, cast(sk_path_t*) other.Handle); 446 } 447 448 void AddRoundRect(SKRect rect, float rx, float ry, 449 SKPathDirection dir = SKPathDirection.Clockwise) { 450 return SkiaApi.sk_path_add_rounded_rect(cast(sk_path_t*) Handle, &rect, rx, ry, dir); 451 } 452 453 void AddRoundedRect(SKRect rect, float rx, float ry, 454 SKPathDirection dir = SKPathDirection.Clockwise) { 455 return AddRoundRect(rect, rx, ry, dir); 456 } 457 458 void AddCircle(float x, float y, float radius, SKPathDirection dir = SKPathDirection.Clockwise) { 459 return SkiaApi.sk_path_add_circle(cast(sk_path_t*) Handle, x, y, radius, dir); 460 } 461 462 void AddPoly(SKPoint[] points, bool close = true) { 463 if (points is null) 464 throw new ArgumentNullException(points.stringof); 465 SKPoint* p = points.ptr; 466 SkiaApi.sk_path_add_poly(cast(sk_path_t*) Handle, p, cast(int) points.length, close); 467 } 468 469 Iterator CreateIterator(bool forceClose) { 470 return new Iterator(this, forceClose); 471 } 472 473 RawIterator CreateRawIterator() { 474 return new RawIterator(this); 475 } 476 477 bool Op(SKPath other, SKPathOp op, SKPath result) { 478 if (other is null) 479 throw new ArgumentNullException(other.stringof); 480 if (result is null) 481 throw new ArgumentNullException(result.stringof); 482 483 return SkiaApi.sk_pathop_op(cast(sk_path_t*) Handle, 484 cast(sk_path_t*) other.Handle, op, cast(sk_path_t*) result.Handle); 485 } 486 487 SKPath Op(SKPath other, SKPathOp op) { 488 auto result = new SKPath(); 489 if (Op(other, op, result)) { 490 return result; 491 } else { 492 result.Dispose(); 493 return null; 494 } 495 } 496 497 bool Simplify(SKPath result) { 498 if (result is null) 499 throw new ArgumentNullException(result.stringof); 500 501 return SkiaApi.sk_pathop_simplify(cast(sk_path_t*) Handle, cast(sk_path_t*) result.Handle); 502 } 503 504 SKPath Simplify() { 505 auto result = new SKPath(); 506 if (Simplify(result)) { 507 return result; 508 } else { 509 result.Dispose(); 510 return null; 511 } 512 } 513 514 bool GetTightBounds(out SKRect result) { 515 SKRect* r = &result; 516 return SkiaApi.sk_pathop_tight_bounds(cast(sk_path_t*) Handle, r); 517 } 518 519 bool ToWinding(SKPath result) { 520 if (result is null) 521 throw new ArgumentNullException(result.stringof); 522 523 return SkiaApi.sk_pathop_as_winding(cast(sk_path_t*) Handle, 524 cast(sk_path_t*) result.Handle); 525 } 526 527 SKPath ToWinding() { 528 SKPath result = new SKPath(); 529 if (ToWinding(result)) { 530 return result; 531 } else { 532 result.Dispose(); 533 return null; 534 } 535 } 536 537 string ToSvgPathData() { 538 SKString str = new SKString(); 539 SkiaApi.sk_path_to_svg_string(cast(sk_path_t*) Handle, cast(sk_string_t*) str.Handle); 540 return cast(string) str; 541 } 542 543 static SKPath ParseSvgPathData(string svgPath) { 544 auto path = new SKPath(); 545 auto success = SkiaApi.sk_path_parse_svg_string(cast(sk_path_t*) path.Handle, svgPath); 546 if (!success) { 547 path.Dispose(); 548 path = null; 549 } 550 return path; 551 } 552 553 static SKPoint[] ConvertConicToQuads(SKPoint p0, SKPoint p1, SKPoint p2, float w, int pow2) { 554 SKPoint[] pts; 555 ConvertConicToQuads(p0, p1, p2, w, pts, pow2); 556 return pts; 557 } 558 559 static int ConvertConicToQuads(SKPoint p0, SKPoint p1, SKPoint p2, float w, 560 out SKPoint[] pts, int pow2) { 561 auto quadCount = 1 << pow2; 562 auto ptCount = 2 * quadCount + 1; 563 pts = new SKPoint[ptCount]; 564 return ConvertConicToQuads(p0, p1, p2, w, pts, pow2); 565 } 566 567 static int ConvertConicToQuads(SKPoint p0, SKPoint p1, SKPoint p2, float w, 568 SKPoint[] pts, int pow2) { 569 if (pts is null) 570 throw new ArgumentNullException(pts.stringof); 571 SKPoint* ptsptr = pts.ptr; 572 return SkiaApi.sk_path_convert_conic_to_quads(&p0, &p1, &p2, w, ptsptr, pow2); 573 } 574 575 // 576 577 static SKPath GetObject(void* handle, bool owns = true) { 578 return handle is null ? null : new SKPath(handle, owns); 579 } 580 581 // 582 583 class Iterator : SKObject, ISKSkipObjectRegistration { 584 private const SKPath path; 585 586 this(SKPath path, bool forceClose) { 587 super(SkiaApi.sk_path_create_iter(cast(sk_path_t*) path.Handle, forceClose ? 1 : 0), 588 true); 589 this.path = path; 590 } 591 592 protected override void Dispose(bool disposing) { 593 return super.Dispose(disposing); 594 } 595 596 override void Dispose() { 597 return super.Dispose(); 598 } 599 600 protected override void DisposeNative() { 601 return SkiaApi.sk_path_iter_destroy(cast(sk_path_iterator_t*) Handle); 602 } 603 604 // [Obsolete ("Use Next(SKPoint[]) instead.")] 605 SKPathVerb Next(SKPoint[] points, bool doConsumeDegenerates, bool exact) { 606 return Next(points); 607 } 608 609 SKPathVerb Next(SKPoint[] points) { 610 if (points is null) 611 throw new ArgumentNullException(points.stringof); 612 if (points.length != 4) 613 throw new ArgumentException("Must be an array of four elements.", points.stringof); 614 615 SKPoint* p = points.ptr; 616 return SkiaApi.sk_path_iter_next(cast(sk_path_iterator_t*) Handle, p); 617 } 618 619 float ConicWeight() { 620 return SkiaApi.sk_path_iter_conic_weight(cast(sk_path_iterator_t*) Handle); 621 } 622 623 bool IsCloseLine() { 624 return SkiaApi.sk_path_iter_is_close_line(cast(sk_path_iterator_t*) Handle) != 0; 625 } 626 627 bool IsCloseContour() { 628 return SkiaApi.sk_path_iter_is_closed_contour(cast(sk_path_iterator_t*) Handle) != 0; 629 } 630 631 } 632 633 class RawIterator : SKObject, ISKSkipObjectRegistration { 634 private const SKPath path; 635 636 this(SKPath path) { 637 super(SkiaApi.sk_path_create_rawiter(cast(sk_path_t*) path.Handle), true); 638 this.path = path; 639 } 640 641 protected override void Dispose(bool disposing) { 642 return super.Dispose(disposing); 643 } 644 645 protected override void DisposeNative() { 646 return SkiaApi.sk_path_rawiter_destroy(cast(sk_path_rawiterator_t*) Handle); 647 } 648 649 SKPathVerb Next(SKPoint[] points) { 650 if (points is null) 651 throw new ArgumentNullException(points.stringof); 652 if (points.length != 4) 653 throw new ArgumentException("Must be an array of four elements.", points.stringof); 654 SKPoint* p = points.ptr; 655 return SkiaApi.sk_path_rawiter_next(cast(sk_path_rawiterator_t*) Handle, p); 656 } 657 658 float ConicWeight() { 659 return SkiaApi.sk_path_rawiter_conic_weight(cast(sk_path_rawiterator_t*) Handle); 660 } 661 662 SKPathVerb Peek() { 663 return SkiaApi.sk_path_rawiter_peek(cast(sk_path_rawiterator_t*) Handle); 664 } 665 666 } 667 668 class OpBuilder : SKObject, ISKSkipObjectRegistration { 669 this() { 670 super(SkiaApi.sk_opbuilder_new(), true); 671 } 672 673 void Add(SKPath path, SKPathOp op) { 674 return SkiaApi.sk_opbuilder_add(cast(sk_opbuilder_t*) Handle, 675 cast(sk_path_t*) path.Handle, op); 676 } 677 678 bool Resolve(SKPath result) { 679 if (result is null) 680 throw new ArgumentNullException(result.stringof); 681 682 return SkiaApi.sk_opbuilder_resolve(cast(sk_opbuilder_t*) Handle, 683 cast(sk_path_t*) result.Handle); 684 } 685 686 protected override void Dispose(bool disposing) { 687 return super.Dispose(disposing); 688 } 689 690 protected override void DisposeNative() { 691 return SkiaApi.sk_opbuilder_destroy(cast(sk_opbuilder_t*) Handle); 692 } 693 694 } 695 }