2012-06-23 54 views
12

Giả sử tôi có phông chữ tùy chỉnh "Foo" mà tôi đang sử dụng trong Ứng dụng iOS của mình. Tôi đã thêm nó vào dự án của tôi, plist, vv và tôi có thể làm cho UILabel s và như vậy với nó chỉ tốt.Nhận đường dẫn để theo dõi một ký tự trong iOS UIFont

Bây giờ, nếu tôi muốn tìm ra một chuỗi các điểm sẽ "vạch ra" chữ cái "P" trong phông chữ đó, làm cách nào tôi nhận được chuỗi điểm đó? Ví dụ: giả sử tôi muốn sử dụng một số CGPath để vẽ chữ 'P' chậm chạp như một máy vẽ ...

Tôi chỉ cần một chuỗi CGPoints trong một mảng nếu được vẽ dưới dạng đường dẫn sẽ vẽ 'P '.

Tôi nhận ra rằng đối với một số chữ cái như 'T', điều này có thể không có ý nghĩa, vì cây bút sẽ phải được dỡ bỏ để vượt qua chữ 'T'. Vì vậy, có thể tôi cần một chuỗi gồm CGPath s ...

Bất kỳ gợi ý nào về cách thực hiện điều này?

Cảm ơn!

+1

[Bạn đã thử gì?] (Http://whathaveyoutried.com) – EmilioPelaez

Trả lời

29

Đi từ chữ "P" đến một chuỗi các điểm liên quan đến một vài bước. Bạn sẽ cần phải sử dụng Core Text.

  1. Tạo CTFont. Vì iOS 7, bạn có thể sử dụng số UIFont trong đó cần CTFont (chúng là “cầu nối miễn phí”). Bạn cũng có thể tạo một số CTFont trực tiếp từ một số CGFont bằng cách sử dụng chức năng CTFontCreateWithGraphicsFont hoặc bằng tên sử dụng CTFontCreateWithName (hoặc sử dụng một vài phương pháp khác).

  2. Nhận glyph cho chữ cái bằng cách sử dụng chức năng CTFontGetGlyphsForCharacters. Đối với chữ cái "P", chỉ nên có một glyph. Đối với một số ký tự trong các tập lệnh không phải tiếng Anh, bạn có thể nhận được nhiều (kết hợp) glyph.

  3. Sử dụng hàm CTFontCreatePathForGlyph để nhận số CGPath cho hình tượng.

  4. Sử dụng CGPathApply để liệt kê các phần tử của đường dẫn.

  5. Chuyển đổi từng dòng, đường cong bốn và phần tử đường cong khối của đường dẫn thành một chuỗi các điểm. Apple không cung cấp bất kỳ API công cộng nào để thực hiện việc này. Bạn sẽ cần phải làm điều đó cho mình. Đối với các yếu tố đường thẳng thì thật dễ dàng. Đối với các yếu tố đường cong, bạn sẽ cần thực hiện một số nghiên cứu nếu bạn chưa biết cách vẽ đường cong Bézier. Ví dụ: xem convert bezier curve to polygonal chain?.

Chúng tôi có thể thử nghiệm với điều này một cách dễ dàng trong một sân chơi Swift:

import UIKit 
import CoreText 
import XCPlayground 

let font = UIFont(name: "HelveticaNeue", size: 64)! 

var unichars = [UniChar]("P".utf16) 
var glyphs = [CGGlyph](count: unichars.count, repeatedValue: 0) 
let gotGlyphs = CTFontGetGlyphsForCharacters(font, &unichars, &glyphs, unichars.count) 
if gotGlyphs { 
    let cgpath = CTFontCreatePathForGlyph(font, glyphs[0], nil)! 
    let path = UIBezierPath(CGPath: cgpath) 
    print(path) 
    XCPlaygroundPage.currentPage.captureValue(path, withIdentifier: "glyph \(glyphs[0])") 
} 

Kết quả:

<UIBezierPath: 0x7fbc89e0d370; <MoveTo {11.072000000000001, 23.808}>, 
<LineTo {11.072000000000001, 40.576000000000001}>, 
<LineTo {22.975999999999999, 40.576000000000001}>, 
<QuadCurveTo {30.560000000000002, 38.432000000000002} - {28.16, 40.576000000000001}>, 
<QuadCurveTo {32.960000000000001, 32.192} - {32.960000000000001, 36.288000000000004}>, 
<QuadCurveTo {30.560000000000002, 25.920000000000002} - {32.960000000000001, 28.096}>, 
<QuadCurveTo {22.975999999999999, 23.808} - {28.16, 23.744}>, 
<Close>, 
<MoveTo {4.992, 45.695999999999998}>, 
<LineTo {4.992, 0}>, 
<LineTo {11.072000000000001, 0}>, 
<LineTo {11.072000000000001, 18.687999999999999}>, 
<LineTo {25.024000000000001, 18.687999999999999}>, 
<QuadCurveTo {35.488, 22.208000000000002} - {31.936, 18.623999999999999}>, 
<QuadCurveTo {39.039999999999999, 32.192} - {39.039999999999999, 25.792000000000002}>, 
<QuadCurveTo {35.488, 42.143999999999998} - {39.039999999999999, 38.591999999999999}>, 
<QuadCurveTo {25.024000000000001, 45.695999999999998} - {31.936, 45.695999999999998}>, 
<Close> 

P glyph path

+0

Cảm ơn! Tôi sẽ quay lại và báo cáo lại ... – Joel

+0

@RobMayoff Câu trả lời hay!Chỉ là những gì tôi cũng đang tìm kiếm! Vì bạn có vẻ biết CGPath của bạn, bạn có biết cách tôi có thể thêm một dòng vào đường dẫn vừa tạo không? Ví dụ: quay lại điểm bắt đầu. Đơn giản chỉ cần thêm: 'let pathP = CGPathCreateMutableCopy (CGPathCreateMutableCopy (cgpath)) CGPathAddLineToPoint (pathP, nil, 0, 0)' dường như không hoạt động.' – user594883

+0

"Không có vẻ hoạt động" nghĩa là gì? Bạn cần phải đăng một câu hỏi mới chứa mã của bạn, đầu ra (của việc bán phá giá đường dẫn đã sửa đổi của bạn), và giải thích những gì là sai với đầu ra. –

2

Đối với những người đang tìm kiếm các giải pháp tương tự trong Objective C

UIFont *font = [UIFont fontWithName:@"HelveticaNeue" size:64]; 
    CGFontRef fontref = CGFontCreateWithFontName((__bridge CFStringRef)font.fontName); 
    NSString *unichars = @"I"; 
    CFStringRef yourFriendlyCFString = (__bridge CFStringRef)unichars; 
    CGGlyph glyphs = CGFontGetGlyphWithGlyphName(fontref, yourFriendlyCFString); 
    CTFontRef fontCT = CTFontCreateWithName((__bridge CFStringRef)font.fontName, font.pointSize, NULL); 
    CGPathRef cgpath = CTFontCreatePathForGlyph(fontCT, glyphs, nil); 
    UIBezierPath *path = [UIBezierPath bezierPathWithCGPath:cgpath]; 
    NSLog(@"Complete path For p is %@", path); 
    CGPathApply(cgpath, (__bridge void * _Nullable)(bezierPoints), MyCGPathApplierFunc); 
    NSLog(@"Points on path %@", bezierPoints); 
    for(NSValue *point in bezierPoints){ 

     //Do your work 
    }