void quartz_size_layout(void *layout, double* width, double* height, double* yoffset_layout) { /* get the typographic bounds */ CGFloat ascent = 0.0; CGFloat descent = 0.0; CGFloat leading = 0.0; double typowidth = CTLineGetTypographicBounds((CTLineRef)layout, &ascent, &descent, &leading); CGFloat typoheight = ascent + descent; *width = typowidth; *height = leading == 0.0 ? typoheight * 1.2 : typoheight + leading; /* if no leading, use 20% of height */ *yoffset_layout = ascent; }
xy__Float draw__string(const char *s, int x, int y, int w, float pos) { CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, s, kCFStringEncodingUTF8); if (font == NULL || font_color == NULL) { fprintf(stderr, "Error in %s: need both font & font_color to be non-NULL.\n", __FUNCTION__); return x; } CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName }; CFTypeRef values[] = { font, font_color }; CFDictionaryRef attributes = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, (const void**)&values, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes); CFRelease(string); CFRelease(attributes); CTLineRef line = CTLineCreateWithAttributedString(attrString); // This position set is needed to get a useful x_pos value on the next line. CGContextSetTextPosition(ctx, x, y); double x_pos = CTLineGetPenOffsetForFlush(line, pos, w); CGFloat descent; double line_width = CTLineGetTypographicBounds(line, NULL, &descent, NULL); CGContextSetTextPosition(ctx, x + x_pos, y + descent); CTLineDraw(line, ctx); CFRelease(line); return x + x_pos + line_width; }