Autodesk Graphic(旧iDraw)は、図形からCore Graphicsのコードを書き出せることを先日知ったので、記します。
言語を選択
環境設定 > 読み込み / 書き出し
で、SwiftかObjective-Cかを選択
クリップボードへ書き出し
必要なレイヤーを選択して、Ctrl+クリック(もしくは編集メニュー)から、
別名でコピー > Core Graphics Codeを選択。
これでクリッブボードにコードがコピーされています。
ペースト(Ctrl + Vなど)すると、以下のようなコードが貼り付けられます。
#if os(iOS) let ctx = UIGraphicsGetCurrentContext() // iOS #else let contextPtr = NSGraphicsContext.currentContext()!.graphicsPort // OS X let opaqueCtx = COpaquePointer(contextPtr) let ctx = Unmanaged<CGContext>.fromOpaque(opaqueCtx).takeUnretainedValue() #endif // enable the following lines for flipped coordinate systems // CGContextTranslateCTM(ctx, 0, self.bounds.size.height) // CGContextScaleCTM(ctx, 1, -1) let colorSpace = CGColorSpaceCreateDeviceRGB() let scaleFactor: CGFloat = 1; // CGContextScaleCTM(ctx, scaleFactor, scaleFactor); /* Shape */ let pathRef = CGPathCreateMutable() CGPathMoveToPoint(pathRef, nil, 10, -0) CGPathAddLineToPoint(pathRef, nil, 230, -0) CGPathAddCurveToPoint(pathRef, nil, 235.523, -0, 240, 4.477, 240, 10) CGPathAddLineToPoint(pathRef, nil, 240, 121) CGPathAddCurveToPoint(pathRef, nil, 240, 126.523, 235.523, 131, 230, 131) CGPathAddLineToPoint(pathRef, nil, 10, 131) CGPathAddCurveToPoint(pathRef, nil, 4.477, 131, 0, 126.523, 0, 121) CGPathAddLineToPoint(pathRef, nil, 0, 10) CGPathAddCurveToPoint(pathRef, nil, 0, 4.477, 4.477, -0, 10, -0) CGPathCloseSubpath(pathRef) // (以下略)
省略してしまいましたが、インナーシャドー、グラデーション、輪郭線を用いた角丸四角形と三角形を描くのに130行程度のコードになっています。
生成されたコードからUIImageを作成
生成されたコードでは、CurrentContextを用いて、そこに描画しています。
サイズを指定してContextを作成し、それをCurrentContextとするのには
UIGraphicsBeginImageContextWithOptionsが使えます。
// サイズを指定してContextを作成し、それをCurrentContextとする
// (sizeはCGSize型の変数)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
// (ここにAutodesk Graphicsが生成したコード)
// CurrentContextからUIImage?の作成
let image: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
// このContextをスタックから取り除く(CurrentContextではなくなる)
UIGraphicsEndImageContext()
こんなかんじで、UIImageに持ってくることができます。
スケールについて
let scaleFactor: CGFloat = 1; // CGContextScaleCTM(ctx, scaleFactor, scaleFactor);
生成されたコードではコメントアウトされているCGContextScaleCTMを生かしてscaleFactorを変えれば、スケールの変更ができます。
一部書き方があっていないところあり
Autodesk GraphicのVer 3.0.1を使用しているのですが、一部、書き方がSwift 2.1に適合していない部分がありました。
グラデーションのOption指定部分を修正しました。
// 修正前
CGContextDrawLinearGradient(ctx, gradientRef, CGPoint(x: 130.334, y: 82.171), CGPoint(x: 130.334, y: 44.818), CGGradientDrawingOptions(kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation))
// 修正後
CGContextDrawLinearGradient(ctx, gradientRef, CGPoint(x: 130.334, y: 82.171), CGPoint(x: 130.334, y: 44.818), [.DrawsBeforeStartLocation, .DrawsAfterEndLocation])
テキスト
テキスト部分を書き出してみるとCoreTextを使用したコードで書き出されました。
Path化されてしまうのではなく、テキスト情報が残っています。
#if os(iOS) let ctx = UIGraphicsGetCurrentContext() // iOS #else let contextPtr = NSGraphicsContext.currentContext()!.graphicsPort // OS X let opaqueCtx = COpaquePointer(contextPtr) let ctx = Unmanaged<CGContext>.fromOpaque(opaqueCtx).takeUnretainedValue() #endif // enable the following lines for flipped coordinate systems // CGContextTranslateCTM(ctx, 0, self.bounds.size.height) // CGContextScaleCTM(ctx, 1, -1) let colorSpace = CGColorSpaceCreateDeviceRGB() let scaleFactor: CGFloat = 1; // CGContextScaleCTM(ctx, scaleFactor, scaleFactor); /* Text */ let textBox = CGRect(x: 13.912, y: 5.804, width: 65.76, height: 38) let textStr: CFString = "ABC" let attributedStr = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0) CFAttributedStringReplaceString(attributedStr, CFRange(location: 0, length: 0), textStr) let fontRef = CTFontCreateWithName("HelveticaNeue", 32, nil) let textRange = CFRange(location: 0, length: CFAttributedStringGetLength(attributedStr)) CFAttributedStringSetAttribute(attributedStr, textRange, kCTFontAttributeName, fontRef) let textColorComps: [CGFloat] = [0.953, 0.388, 0.388, 1] let textColor = CGColorCreate(colorSpace, textColorComps) CFAttributedStringSetAttribute(attributedStr, textRange, kCTForegroundColorAttributeName, textColor) var alignment = CTTextAlignment.TextAlignmentCenter var paragraphSettings = CTParagraphStyleSetting(spec: CTParagraphStyleSpecifier.Alignment, valueSize: UInt(sizeof(UInt8)), value: &alignment) let paragraphStyle = CTParagraphStyleCreate(¶graphSettings, 1) CFAttributedStringSetAttribute(attributedStr, textRange, kCTParagraphStyleAttributeName, paragraphStyle) let textBoxPath = CGPathCreateWithRect(CGRect(x: 0, y: 0, width: textBox.size.width, height: textBox.size.height), nil) let framesetter = CTFramesetterCreateWithAttributedString(attributedStr) let frameRef = CTFramesetterCreateFrame(framesetter, CFRange(location: 0, length: 0), textBoxPath, nil) CGContextSaveGState(ctx) CGContextTranslateCTM(ctx, textBox.origin.x, textBox.origin.y) CGContextSetTextMatrix(ctx, CGAffineTransformIdentity) CGContextTranslateCTM(ctx, 0.0, textBox.size.height) CGContextScaleCTM(ctx, 1.0, -1.0) CTFrameDraw(frameRef, ctx) CGContextRestoreGState(ctx)
一部でエラーが出たので修正しました
// 修正前
var alignment = CTTextAlignment.TextAlignmentCenter
var paragraphSettings = CTParagraphStyleSetting(spec: CTParagraphStyleSpecifier.Alignment, valueSize: UInt(sizeof(UInt8)), value: &alignment)
// (略)
CTFrameDraw(frameRef, ctx)
// 修正後
var alignment = CTTextAlignment.Center
var paragraphSettings = CTParagraphStyleSetting(spec: CTParagraphStyleSpecifier.Alignment, valueSize: Int(sizeof(UInt8)), value: &alignment)
// (略)
CTFrameDraw(frameRef, ctx!)
ということで、Autodesk GraphicはCore Graphics Codeを書き出せます。