2015-10-14 24 views
0

核心圖形有兩個功能,CGPathCreateCopyByDashingPath()CGPathCreateCopyByStrokingPath(),這兩個函數都需要一個CGPath,您想要筆劃並將其轉換爲其等效填充。我需要這樣做,例如,我可以用漸變描邊線條:調用CGPathCreateCopyByStrokingPath(),將路徑加載到CGContext中,調用CGContextClip(),然後繪製漸變。如何將CGPathCreateCopyByDashingPath()和CGPathCreateCopyByStrokingPath()組合起來在OS X上描畫虛線的CGPath?

但是,CGPathCreateCopyByStrokingPath()接受線條線條,線條連接等線條線條參數,而CGPathCreateCopyByDashingPath()沒有。我希望能夠用自定義線帽/連接衝刺。

特別地,這兩個函數具有在他們的單證以下:創建

新路徑,使得加註新路徑繪製像素相同的像素與指定的破折號參數撫摸原始路徑。

創建新路徑以便填充新路徑繪製與撫摸原始路徑相同的像素。

強調我的。所以我從中得出的結論是,一旦你調用了任何一個函數,你就會得到一個由包含所請求的筆劃的行組成的新路徑。所以,如果我打電話ByDashing,然後ByStroking,第一個將創建一個由一串小矩形組成的路徑,然後第二個將形成矩形形成這些小矩形的周長線,這不是我想要的。 (我可以測試這個,並在稍後張貼圖片。)

我見過的一切指向Core Graphics可以直接使用CGContext來做到這一點;例如,「Programming with Quartz」書籍在其瀟灑的例子中顯示了圓形和方形的線條上限。有沒有任何理由我不能用獨立的CGPath做到這一點?

我錯過了什麼嗎?或者我只是堅持這一點?

這是用於OS X,不適用於iOS。

謝謝。

回答

1

原來的文檔CGPathCreateCopyByDashingPath()是錯誤的。

眼下,它說

創建新的路徑,以便加註新路徑得出相同的像素與指定的儀表參數撫摸着原始路徑。

這意味着它會產生具有默認筆畫參數的合成路徑。但它不!相反,你會得到一個新的路徑,這個路徑就是現有的由破折號參數分解的路徑。您需要撥打CGPathCreateCopyByStrokingPath()才能生成填寫路徑。

以下程序有三個部分。首先通過使用CGContext函數而不是CGPath函數來顯示路徑應該看起來像什麼。其次,它只繪製CGPathCreateCopyByDashingPath()。請注意,如何撫摸路徑不會產生破折號曾經是一堆盒子,而是一堆破折號。如果仔細觀察,你會發現線條連接處的藍色小病。最後,它調用CGPathCreateCopyByDashingPath(),然後是CGPathCreateCopyByStrokingPath(),你會看到填充產生正確的輸出。再次

Screenshot

謝謝,bhaller!我不確定文件的變更內容,或者如何請求這樣的變更。

// 15 october 2015 
#import <Cocoa/Cocoa.h> 

@interface dashStrokeView : NSView 
@end 

void putstr(CGContextRef c, const char *str, double x, double y) 
{ 
    NSFont *sysfont; 
    CFStringRef string; 
    CTFontRef font; 
    CFStringRef keys[1]; 
    CFTypeRef values[1]; 
    CFDictionaryRef attrs; 
    CFAttributedStringRef attrstr; 
    CTLineRef line; 

    sysfont = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; 
    font = (CTFontRef) sysfont;  // toll-free bridge 

    string = CFStringCreateWithCString(kCFAllocatorDefault, 
     str, kCFStringEncodingUTF8); 
    keys[0] = kCTFontAttributeName; 
    values[0] = font; 
    attrs = CFDictionaryCreate(kCFAllocatorDefault, 
     keys, values, 
     1, 
     &kCFTypeDictionaryKeyCallBacks, 
     &kCFTypeDictionaryValueCallBacks); 
    attrstr = CFAttributedStringCreate(kCFAllocatorDefault, string, attrs); 

    line = CTLineCreateWithAttributedString(attrstr); 
    CGContextSetTextPosition(c, x, y); 
    CTLineDraw(line, c); 

    CFRelease(line); 
    CFRelease(attrstr); 
    CFRelease(attrs); 
    CFRelease(string); 
} 

@implementation dashStrokeView 

- (void)drawRect:(NSRect)r 
{ 
    CGContextRef c; 
    CGFloat lengths[2] = { 10, 13 }; 
    CGMutablePathRef buildpath; 
    CGPathRef copy, copy2; 

    c = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; 

    CGContextSaveGState(c); 

    putstr(c, "Dash + Stroke With CGContext Functions", 10, 10); 
    CGContextMoveToPoint(c, 50, 50); 
    CGContextAddLineToPoint(c, 100, 30); 
    CGContextAddLineToPoint(c, 150, 70); 
    CGContextAddLineToPoint(c, 200, 50); 
    CGContextSetLineWidth(c, 10); 
    CGContextSetLineJoin(c, kCGLineJoinBevel); 
    CGContextSetLineCap(c, kCGLineCapRound); 
    CGContextSetLineDash(c, 0, lengths, 2); 
    CGContextSetRGBStrokeColor(c, 0, 0, 0, 1); 
    CGContextStrokePath(c); 
    // and reset 
    CGContextSetLineWidth(c, 1); 
    CGContextSetLineJoin(c, kCGLineJoinMiter); 
    CGContextSetLineCap(c, kCGLineCapButt); 
    CGContextSetLineDash(c, 0, NULL, 0); 

    CGContextTranslateCTM(c, 0, 100); 
    putstr(c, "Dash With CGPath Functions", 10, 10); 
    buildpath = CGPathCreateMutable(); 
    CGPathMoveToPoint(buildpath, NULL, 50, 50); 
    CGPathAddLineToPoint(buildpath, NULL, 100, 30); 
    CGPathAddLineToPoint(buildpath, NULL, 150, 70); 
    CGPathAddLineToPoint(buildpath, NULL, 200, 50); 
    copy = CGPathCreateCopyByDashingPath(buildpath, NULL, 0, lengths, 2); 
    CGContextAddPath(c, copy); 
    CGContextStrokePath(c); 
    CGContextAddPath(c, copy); 
    CGContextSetRGBFillColor(c, 0, 0.25, 0.5, 1); 
    CGContextFillPath(c); 
    CGPathRelease(copy); 
    CGPathRelease((CGPathRef) buildpath); 

    CGContextTranslateCTM(c, 0, 100); 
    putstr(c, "Dash + Stroke With CGPath Functions", 10, 10); 
    buildpath = CGPathCreateMutable(); 
    CGPathMoveToPoint(buildpath, NULL, 50, 50); 
    CGPathAddLineToPoint(buildpath, NULL, 100, 30); 
    CGPathAddLineToPoint(buildpath, NULL, 150, 70); 
    CGPathAddLineToPoint(buildpath, NULL, 200, 50); 
    copy = CGPathCreateCopyByDashingPath(buildpath, NULL, 0, lengths, 2); 
    copy2 = CGPathCreateCopyByStrokingPath(copy, NULL, 10, kCGLineCapRound, kCGLineJoinBevel, 10); 
    CGContextAddPath(c, copy2); 
    CGContextSetRGBFillColor(c, 0, 0.25, 0.5, 1); 
    CGContextFillPath(c); 
    CGContextAddPath(c, copy2); 
    CGContextStrokePath(c); 
    CGPathRelease(copy2); 
    CGPathRelease(copy); 
    CGPathRelease((CGPathRef) buildpath); 

    CGContextRestoreGState(c); 
} 

- (BOOL)isFlipped 
{ 
    return YES; 
} 

@end 

@interface appDelegate : NSObject<NSApplicationDelegate> 
@end 

@implementation appDelegate 

- (void)applicationDidFinishLaunching:(NSNotification *)note 
{ 
    NSWindow *mainwin; 
    NSView *contentView; 
    dashStrokeView *view; 
    NSDictionary *views; 
    NSArray *constraints; 

    mainwin = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 320, 360) 
     styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) 
     backing:NSBackingStoreBuffered 
     defer:YES]; 
    [mainwin setTitle:@"Dash/Stroke Example"]; 
    contentView = [mainwin contentView]; 

    view = [[dashStrokeView alloc] initWithFrame:NSZeroRect]; 
    [view setTranslatesAutoresizingMaskIntoConstraints:NO]; 
    [contentView addSubview:view]; 

    views = NSDictionaryOfVariableBindings(view); 
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-|" 
     options:0 
     metrics:nil 
     views:views]; 
    [contentView addConstraints:constraints]; 
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]-|" 
     options:0 
     metrics:nil 
     views:views]; 
    [contentView addConstraints:constraints]; 

    [mainwin cascadeTopLeftFromPoint:NSMakePoint(20, 20)]; 
    [mainwin makeKeyAndOrderFront:nil]; 
} 

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app 
{ 
    return YES; 
} 

@end 

int main(void) 
{ 
    NSApplication *app; 

    app = [NSApplication sharedApplication]; 
    [app setActivationPolicy:NSApplicationActivationPolicyRegular]; 
    [app setDelegate:[appDelegate new]]; 
    [app run]; 
    return 0; 
} 
+1

您可以隨時向蘋果公司提交雷達(錯誤報告)以請求文檔更改:http://radar.apple.com/ –

1

我不確定問題是什麼,真的。你有一條開始的道路;我們稱之爲A。您撥打CGPathCreateCopyByDashingPath()A開闢一條您想要的嶄新路線;我們稱之爲BB沒有設置特定的行上限/連接,因爲它不是路徑的屬性,而是在撫摸路徑時使用的屬性。 (想象一下,通過從點到點繪製線段來手工繪製虛線路徑;在路徑描述中沒有任何概念的頂點或連接,只是每個段的起點和終點。)然後取B並調用CGPathCreateCopyByStrokingPath()就可以了獲得C,使用特定線寬/帽/連接特徵的B中風的可填充路徑。最後,使用漸變填充填充C。這不行嗎?好像你知道你需要解決你的問題的所有組件,所以我不確定問題實際在哪裏。你能澄清嗎?

+0

問題是,ByDashing的文檔顯示「新路徑已創建,因此**填充新路徑**會繪製與使用指定的破折號參數描繪原始路徑相同的像素。」強調我的。除非文檔是錯誤的,否則調用ByDrawing和ByStroking將產生一堆小矩形或橢圓,其中破折號曾經是。如果這個解釋不清楚,我可能應該編寫一個測試用例並將其效果可視化,但是我將在此期間將其添加到問題中。 – andlabs

+1

啊,我明白你的意思了。如果那真的是'ByDashing'所做的,那麼這看起來是一個糟糕的設計 - 它已經將ByDashing應該做的和ByStroking做了什麼。不幸的。是的,如果您對此進行測試,請在此處發佈結果,我很想知道。如果文檔是正確的,那麼我會在Apple上提出一個問題,要求提供一個沒有損壞的新API。 – bhaller

+0

O ... kay我似乎無法使用10.10上的CGContext函數在虛線上設置筆觸設置。完全奇怪。我想知道這個設施是否被徹底清除,因爲Quartz編程書上說我應該可以...... – andlabs