CGPathAdditions.m 3.9 KB

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