CGPathAdditions.m 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //
  2. // CGPathAdditions.m
  3. // SVGPad
  4. //
  5. // Copyright Matt Rajca 2011. All rights reserved.
  6. //
  7. #import "CGPathAdditions.h"
  8. void applier (void *info, const CGPathElement *element);
  9. typedef struct {
  10. CGMutablePathRef path;
  11. CGFloat offX;
  12. CGFloat offY;
  13. } PathInfo;
  14. CGFloat fixInfinity(CGFloat inputFloat){
  15. if(inputFloat>CGFLOAT_MAX) inputFloat=CGFLOAT_MAX;
  16. if(inputFloat<(-1)*CGFLOAT_MAX) inputFloat=(-1)*CGFLOAT_MAX;
  17. return inputFloat;
  18. }
  19. CGPoint *fixPointsInfinity(const CGPathElement *element){
  20. int i,total;
  21. switch (element->type) {
  22. case kCGPathElementMoveToPoint:
  23. total=1;
  24. break;
  25. case kCGPathElementAddLineToPoint:
  26. total=1;
  27. break;
  28. case kCGPathElementAddQuadCurveToPoint:
  29. total=2;
  30. break;
  31. case kCGPathElementAddCurveToPoint:
  32. total=3;
  33. break;
  34. default:
  35. total=0;
  36. break;
  37. }
  38. if( total == 0 )
  39. return NULL; // Avoid malloc(0); keep C compilers happy
  40. CGPoint* returnArray = malloc(sizeof(CGPoint) * total);
  41. for (i = 0; i < total; i++)
  42. {
  43. returnArray[i].x=fixInfinity(element->points[i].x);
  44. returnArray[i].y=fixInfinity(element->points[i].y);
  45. }
  46. return returnArray;
  47. }
  48. void applier (void *info, const CGPathElement *element) {
  49. PathInfo *pathInfo = (PathInfo *) info;
  50. CGMutablePathRef path = pathInfo->path;
  51. CGFloat x = fixInfinity(pathInfo->offX);
  52. CGFloat y = fixInfinity(pathInfo->offY);
  53. CGPoint *points = fixPointsInfinity(element);
  54. switch (element->type) {
  55. case kCGPathElementMoveToPoint:
  56. CGPathMoveToPoint(path, NULL, points[0].x - x, points[0].y - y);
  57. break;
  58. case kCGPathElementAddLineToPoint:
  59. CGPathAddLineToPoint(path, NULL, points[0].x - x, points[0].y - y);
  60. break;
  61. case kCGPathElementAddQuadCurveToPoint:
  62. CGPathAddQuadCurveToPoint(path, NULL, points[0].x - x, points[0].y - y,
  63. points[1].x - x, points[1].y - y);
  64. break;
  65. case kCGPathElementAddCurveToPoint:
  66. CGPathAddCurveToPoint(path, NULL, points[0].x - x, points[0].y - y,
  67. points[1].x - x, points[1].y - y,
  68. points[2].x - x, points[2].y - y);
  69. break;
  70. case kCGPathElementCloseSubpath:
  71. CGPathCloseSubpath(path);
  72. break;
  73. }
  74. free(points);
  75. }
  76. CGPathRef CGPathCreateByOffsettingPath (CGPathRef aPath, CGFloat x, CGFloat y) {
  77. CGMutablePathRef path = CGPathCreateMutable();
  78. PathInfo *info = (PathInfo *) malloc(sizeof(PathInfo));
  79. info->path = path;
  80. info->offX = fixInfinity(x);
  81. info->offY = fixInfinity(y);
  82. CGPathApply(aPath, info, &applier);
  83. free(info);
  84. return path;
  85. }
  86. void applyPathTranslation (void *info, const CGPathElement *element) {
  87. PathInfo *pathInfo = (PathInfo *) info;
  88. CGMutablePathRef path = pathInfo->path;
  89. CGFloat x = fixInfinity(pathInfo->offX);
  90. CGFloat y = fixInfinity(pathInfo->offY);
  91. CGPoint *points = fixPointsInfinity(element);
  92. switch (element->type) {
  93. case kCGPathElementMoveToPoint:
  94. CGPathMoveToPoint(path, NULL, points[0].x + x, points[0].y + y);
  95. break;
  96. case kCGPathElementAddLineToPoint:
  97. CGPathAddLineToPoint(path, NULL, points[0].x + x, points[0].y + y);
  98. break;
  99. case kCGPathElementAddQuadCurveToPoint:
  100. CGPathAddQuadCurveToPoint(path, NULL, points[0].x + x, points[0].y + y,
  101. points[1].x + x, points[1].y + y);
  102. break;
  103. case kCGPathElementAddCurveToPoint:
  104. CGPathAddCurveToPoint(path, NULL, points[0].x + x, points[0].y + y,
  105. points[1].x + x, points[1].y + y,
  106. points[2].x + x, points[2].y + y);
  107. break;
  108. case kCGPathElementCloseSubpath:
  109. CGPathCloseSubpath(path);
  110. break;
  111. }
  112. free(points);
  113. }
  114. CGPathRef CGPathCreateByTranslatingPath (CGPathRef aPath, CGFloat x, CGFloat y) {
  115. CGMutablePathRef path = CGPathCreateMutable();
  116. PathInfo *info = (PathInfo *) malloc(sizeof(PathInfo));
  117. info->path = path;
  118. info->offX = fixInfinity(x);
  119. info->offY = fixInfinity(y);
  120. CGPathApply(aPath, info, &applyPathTranslation);
  121. free(info);
  122. return path;
  123. }