【问题标题】:Why can't I draw a dashed line with different line caps/joins on OS X using Quartz?为什么我不能使用 Quartz 在 OS X 上绘制具有不同线帽/连接的虚线?
【发布时间】:2015-10-15 22:03:20
【问题描述】:

我正在尝试为this question 构建一个测试用例。为此,我需要绘制一条带有与默认值不同的大写和连接的虚线;例如,带有圆形线帽。 Gelphman 和 Laden 的 Programming with Quartz 一书说我应该能够做到;第 125 页谈了很多关于用不同的大写和连接绘制虚线的内容,甚至还有一个图显示了不同大写的虚线的样子。

但是,当我跑步时

CGFloat lengths[2] = { 5, 3 };
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);

我看到的是实线,而不是虚线。如果我注释掉以下两行:

CGContextSetLineJoin(c, kCGLineJoinBevel);
CGContextSetLineCap(c, kCGLineCapRound);

然后我看到了我的潇洒。其中一条线本身会使绘图恢复为实线。

我不知道发生了什么。提供了一个示例程序。这是在 OS X 10.10 上;我需要将目标追溯到 10.7。

这是针对 OS X,而不是 iOS。

谢谢。

// 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] = { 5, 3 };
    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);

    CGContextTranslateCTM(c, 0, 100);
    putstr(c, "Dash With CGPath Functions", 10, 10);

    CGContextTranslateCTM(c, 0, 100);
    putstr(c, "Dash + Stroke With CGPath Functions", 10, 10);

    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, 240)
        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;
}

【问题讨论】:

    标签: macos cocoa core-graphics quartz-graphics


    【解决方案1】:

    问题在于 CGFloat lengths 的值不够大,无法从其路径中辨别出来。增加浮点值将使斜角和大写的间距更充分:

    CGFloat lengths[2] = { 10, 13 };
    

    你现在得到它的方式实际上是绘制(而不是还原),尽管它是如此微小以至于它自身重叠,基本上形成了一条实线。

    【讨论】:

    • 是的,就是这样。圆线帽太大,所以它们重叠 =P 谢谢!
    • @andlabs:不客气!您可能会考虑的另一件事是使用kCGLineJoinRound 而不是kCGLineJoinBevel,因为它可能会给您带来更平滑的边缘。
    • 这只是为了演示;我选择了斜角连接,以便与盖子有不同的外观。演示完成;你可以看到我的结果here
    猜你喜欢
    • 1970-01-01
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 2014-11-19
    • 2020-06-06
    • 2016-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多