UIBezierPath+YYAdd.m 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. //
  2. // UIBezierPath+YYAdd.m
  3. // YYKit <https://github.com/ibireme/YYKit>
  4. //
  5. // Created by ibireme on 14/10/30.
  6. // Copyright (c) 2015 ibireme.
  7. //
  8. // This source code is licensed under the MIT-style license found in the
  9. // LICENSE file in the root directory of this source tree.
  10. //
  11. #import "UIBezierPath+YYAdd.h"
  12. #import "UIFont+YYAdd.h"
  13. #import <CoreText/CoreText.h>
  14. #import "YYKitMacro.h"
  15. YYSYNTH_DUMMY_CLASS(UIBezierPath_YYAdd)
  16. @implementation UIBezierPath (YYAdd)
  17. + (UIBezierPath *)bezierPathWithText:(NSString *)text font:(UIFont *)font {
  18. CTFontRef ctFont = font.CTFontRef;
  19. if (!ctFont) return nil;
  20. NSDictionary *attrs = @{ (__bridge id)kCTFontAttributeName:(__bridge id)ctFont };
  21. NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:text attributes:attrs];
  22. CFRelease(ctFont);
  23. CTLineRef line = CTLineCreateWithAttributedString((__bridge CFTypeRef)attrString);
  24. if (!line) return nil;
  25. CGMutablePathRef cgPath = CGPathCreateMutable();
  26. CFArrayRef runs = CTLineGetGlyphRuns(line);
  27. for (CFIndex iRun = 0, iRunMax = CFArrayGetCount(runs); iRun < iRunMax; iRun++) {
  28. CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, iRun);
  29. CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);
  30. for (CFIndex iGlyph = 0, iGlyphMax = CTRunGetGlyphCount(run); iGlyph < iGlyphMax; iGlyph++) {
  31. CFRange glyphRange = CFRangeMake(iGlyph, 1);
  32. CGGlyph glyph;
  33. CGPoint position;
  34. CTRunGetGlyphs(run, glyphRange, &glyph);
  35. CTRunGetPositions(run, glyphRange, &position);
  36. CGPathRef glyphPath = CTFontCreatePathForGlyph(runFont, glyph, NULL);
  37. if (glyphPath) {
  38. CGAffineTransform transform = CGAffineTransformMakeTranslation(position.x, position.y);
  39. CGPathAddPath(cgPath, &transform, glyphPath);
  40. CGPathRelease(glyphPath);
  41. }
  42. }
  43. }
  44. UIBezierPath *path = [UIBezierPath bezierPathWithCGPath:cgPath];
  45. CGRect boundingBox = CGPathGetPathBoundingBox(cgPath);
  46. CFRelease(cgPath);
  47. CFRelease(line);
  48. [path applyTransform:CGAffineTransformMakeScale(1.0, -1.0)];
  49. [path applyTransform:CGAffineTransformMakeTranslation(0.0, boundingBox.size.height)];
  50. return path;
  51. }
  52. @end