From d301943d282a8fc322403a0821e110bba8d0fce9 Mon Sep 17 00:00:00 2001 From: glenlow Date: Thu, 22 Apr 2010 13:24:31 +0000 Subject: [PATCH] - fix incorrect bitmap format rendered (missing initializer causing off-by-one error) - rendering bitmaps on iPhoneOS now uses memory-mapped scratch files - text layout better abstracted between Mac OS X and iPhoneOS - more robust environment detection at build time --- plugin/quartz/GVTextLayout.h | 7 +- plugin/quartz/GVTextLayout.m | 78 ++++++---------- plugin/quartz/gvdevice_quartz.c | 2 +- plugin/quartz/gvplugin_quartz.c | 5 +- plugin/quartz/gvplugin_quartz.h | 27 ++---- plugin/quartz/gvrender_quartz.c | 119 +++++++++++++++++++++--- plugin/quartz/gvtextlayout_quartz.c | 136 +++++++++++----------------- 7 files changed, 202 insertions(+), 172 deletions(-) diff --git a/plugin/quartz/GVTextLayout.h b/plugin/quartz/GVTextLayout.h index 1926846e7..fcf41f978 100644 --- a/plugin/quartz/GVTextLayout.h +++ b/plugin/quartz/GVTextLayout.h @@ -22,13 +22,10 @@ NSString* _text; } -@property (readonly, nonatomic) UIFont* font; -@property (readonly, nonatomic) NSString* text; -@property (readonly, nonatomic) CGSize size; - - (id)initWithFontName:(char*)fontName fontSize:(CGFloat)fontSize text:(char*)text; -- (void)drawAtPoint:(CGPoint)point inContext:(CGContextRef)context; +- (void)sizeUpWidth:(double*)width height:(double*)height yoffset:(double*)yoffset; +- (void)drawInContext:(CGContextRef)context atPosition:(CGPoint)position; - (void)dealloc; diff --git a/plugin/quartz/GVTextLayout.m b/plugin/quartz/GVTextLayout.m index 6e2232e3d..17293ea01 100644 --- a/plugin/quartz/GVTextLayout.m +++ b/plugin/quartz/GVTextLayout.m @@ -26,72 +26,34 @@ #include "gvplugin_quartz.h" -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 20000 +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 #import "GVTextLayout.h" -boolean quartz_textlayout(textpara_t *para, char **fontpath) +void *quartz_new_layout(char* fontname, double fontsize, char* text) { - GVTextLayout* layout = [[GVTextLayout alloc] initWithFontName:para->fontname fontSize:para->fontsize text:para->str]; - CGSize size = layout.size; - - para->layout = layout; - para->free_layout = &quartz_free_layout; - para->width = size.width; - para->height = size.height; - para->yoffset_layout = layout.font.ascender; - para->yoffset_centerline = 0; - - return TRUE; + return [[GVTextLayout alloc] initWithFontName:fontname fontSize:fontsize text:text]; } -void quartz_free_layout(void *layout) +void quartz_size_layout(void *layout, double* width, double* height, double* yoffset_layout) { - [(GVTextLayout*)layout release]; + [(GVTextLayout*)layout sizeUpWidth:width height:height yoffset:yoffset_layout]; } -void quartzgen_textpara(GVJ_t *job, pointf p, textpara_t *para) +void quartz_draw_layout(void *layout, CGContextRef context, CGPoint position) { - CGContextRef context = (CGContextRef)job->context; - - /* adjust text position */ - switch (para->just) { - case 'r': - p.x -= para->width; - break; - case 'l': - p.x -= 0.0; - break; - case 'n': - default: - p.x -= para->width / 2.0; - break; - } - p.y += para->yoffset_centerline; - - GVTextLayout* layout; - if (para->free_layout == &quartz_free_layout) - layout = (GVTextLayout*)para->layout; - else - layout = [[GVTextLayout alloc] initWithFontName:para->fontname fontSize:para->fontsize text:para->str]; - - CGContextSaveGState(context); - CGContextScaleCTM(context, 1.0, -1.0); - CGContextSetRGBFillColor(context, job->obj->pencolor.u.RGBA [0], job->obj->pencolor.u.RGBA [1], job->obj->pencolor.u.RGBA [2], job->obj->pencolor.u.RGBA [3]); - [layout drawAtPoint:CGPointMake(p.x, -p.y - para->yoffset_layout) inContext:context]; - CGContextRestoreGState(context); - - if (para->free_layout != &quartz_free_layout) - [layout release]; + [(GVTextLayout*)layout drawInContext:context atPosition:position]; +} + +void quartz_free_layout(void *layout) +{ + [(GVTextLayout*)layout release]; } static NSString* _defaultFontName = @"TimesNewRomanPSMT"; @implementation GVTextLayout -@synthesize font = _font; -@synthesize text = _text; - - (id)initWithFontName:(char*)fontName fontSize:(CGFloat)fontSize text:(char*)text { if (self = [super init]) @@ -107,6 +69,16 @@ static NSString* _defaultFontName = @"TimesNewRomanPSMT"; return self; } +- (void)sizeUpWidth:(double*)width height:(double*)height yoffset:(double*)yoffset +{ + CGSize size = [_text sizeWithFont:_font]; + CGFloat ascender = _font.ascender; + + *width = size.width; + *height = size.height; + *yoffset = ascender; +} + - (void)drawAtPoint:(CGPoint)point inContext:(CGContextRef)context { UIGraphicsPushContext(context); @@ -114,9 +86,11 @@ static NSString* _defaultFontName = @"TimesNewRomanPSMT"; UIGraphicsPopContext(); } -- (CGSize)size +- (void)drawInContext:(CGContextRef)context atPosition:(CGPoint)position { - return [_text sizeWithFont:_font]; + UIGraphicsPushContext(context); + [_text drawAtPoint:position withFont:_font]; + UIGraphicsPopContext(); } - (void)dealloc diff --git a/plugin/quartz/gvdevice_quartz.c b/plugin/quartz/gvdevice_quartz.c index 28174eabd..d3459465c 100644 --- a/plugin/quartz/gvdevice_quartz.c +++ b/plugin/quartz/gvdevice_quartz.c @@ -22,7 +22,7 @@ #include "gvplugin_quartz.h" -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040 && defined(HAVE_PANGOCAIRO) +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 && defined(HAVE_PANGOCAIRO) const void *memory_data_consumer_get_byte_pointer(void *info) { diff --git a/plugin/quartz/gvplugin_quartz.c b/plugin/quartz/gvplugin_quartz.c index f9c8ff214..059d803d8 100644 --- a/plugin/quartz/gvplugin_quartz.c +++ b/plugin/quartz/gvplugin_quartz.c @@ -23,11 +23,12 @@ extern gvplugin_installed_t gvtextlayout_quartz_types; extern gvplugin_installed_t gvloadimage_quartz_types; extern gvplugin_installed_t gvdevice_quartz_types; -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 extern gvplugin_installed_t gvdevice_quartz_types_for_cairo; /* Uniform Type Identifiers corresponding to each format_type */ CFStringRef format_uti [] = { + NULL, NULL, CFSTR("com.microsoft.bmp"), CFSTR("com.ilm.openexr-image"), @@ -61,7 +62,7 @@ static gvplugin_api_t apis[] = { {API_textlayout, &gvtextlayout_quartz_types}, {API_loadimage, &gvloadimage_quartz_types}, {API_device, &gvdevice_quartz_types}, -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040 && defined(HAVE_PANGOCAIRO) +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 && defined(HAVE_PANGOCAIRO) {API_device, &gvdevice_quartz_types_for_cairo}, #endif {(api_t)0, 0}, diff --git a/plugin/quartz/gvplugin_quartz.h b/plugin/quartz/gvplugin_quartz.h index 0b5ddbac4..dba821c3a 100644 --- a/plugin/quartz/gvplugin_quartz.h +++ b/plugin/quartz/gvplugin_quartz.h @@ -19,10 +19,10 @@ #include -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -#include -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) #include +#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#include #endif #include "types.h" @@ -52,28 +52,19 @@ static const int BYTE_ALIGN = 15; /* align to 16 bytes */ static const int BITS_PER_COMPONENT = 8; /* bits per color component */ static const int BYTES_PER_PIXEL = 4; /* bytes per pixel */ -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 extern CFStringRef format_uti []; #endif extern CGDataConsumerCallbacks device_data_consumer_callbacks; -typedef struct { - CGFontRef font; - CGGlyph* glyphs; - size_t glyph_count; -} quartz_layout; - -/* gvtextlayout_quartz.c in Mac OS X */ -/* GVTextLayout.m in iPhoneOS */ +/* gvtextlayout_quartz.c in Mac OS X: layout is a CoreText CTLineRef */ +/* GVTextLayout.m in iPhoneOS: layout is a custom Objective-C GVTextLayout */ +void *quartz_new_layout(char* fontname, double fontsize, char* text); +void quartz_size_layout(void *layout, double* width, double* height, double* yoffset_layout); +void quartz_draw_layout(void *layout, CGContextRef context, CGPoint position); void quartz_free_layout(void *layout); -boolean quartz_textlayout(textpara_t *para, char **fontpath); - -/* gvrender_quartz.c in Mac OS X */ -/* GVTextLayout.m in iPhoneOS */ - -void quartzgen_textpara(GVJ_t *job, pointf p, textpara_t *para); #ifdef __cplusplus } diff --git a/plugin/quartz/gvrender_quartz.c b/plugin/quartz/gvrender_quartz.c index 33246e55e..e15257514 100644 --- a/plugin/quartz/gvrender_quartz.c +++ b/plugin/quartz/gvrender_quartz.c @@ -21,6 +21,11 @@ #include #include +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 +#include +#include +#endif + #include "gvplugin_device.h" #include "gvplugin_render.h" #include "graph.h" @@ -57,7 +62,7 @@ static void quartzgen_end_job(GVJ_t *job) case FORMAT_CGIMAGE: break; -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 default: /* bitmap formats */ { /* create an image destination */ @@ -84,7 +89,14 @@ static void quartzgen_end_job(GVJ_t *job) { /* create an image and save it where the window field is, which was set to the passed-in context at begin job */ *((CGImageRef*)job->window) = CGBitmapContextCreateImage(context); +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 + void* context_data = CGBitmapContextGetData(context); + size_t context_datalen = CGBitmapContextGetBytesPerRow(context) * CGBitmapContextGetHeight(context); +#endif CGContextRelease(context); +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 + munmap(context_data, context_datalen); +#endif } } @@ -133,16 +145,60 @@ static void quartzgen_begin_page(GVJ_t *job) default: /* bitmap formats */ { + size_t bytes_per_row = (job->width * BYTES_PER_PIXEL + BYTE_ALIGN) & ~BYTE_ALIGN; + + void* buffer = NULL; + +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 + + /* iPhoneOS has no swap files for memory, so if we're short of memory we need to make our own temp scratch file to back it */ + + size_t buffer_size = job->height * bytes_per_row; + mach_msg_type_number_t vm_info_size = HOST_VM_INFO_COUNT; + vm_statistics_data_t vm_info; + + if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_info, &vm_info_size) != KERN_SUCCESS + || buffer_size * 2 > vm_info.free_count * vm_page_size) + { + FILE* temp_file = tmpfile(); + if (temp_file) + { + int temp_file_descriptor = fileno(temp_file); + if (temp_file_descriptor >= 0 && ftruncate(temp_file_descriptor, buffer_size) == 0) + { + buffer = mmap( + NULL, + buffer_size, + PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, + temp_file_descriptor, + 0); + if (buffer == (void*)-1) + buffer = NULL; + } + fclose(temp_file); + } + } + if (!buffer) + buffer = mmap( + NULL, + buffer_size, + PROT_READ | PROT_WRITE, + MAP_ANON| MAP_SHARED, + -1, + 0); +#endif + /* create a true color bitmap for drawing into */ CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); job->context = CGBitmapContextCreate( - NULL, /* data: let Quartz take care of memory management */ - job->width, /* width in pixels */ - job->height, /* height in pixels */ - BITS_PER_COMPONENT, /* bits per component */ - (job->width * BYTES_PER_PIXEL + BYTE_ALIGN) & ~BYTE_ALIGN, /* bytes per row: align to 16 byte boundary */ - color_space, /* color space: device RGB */ - kCGImageAlphaPremultipliedFirst /* bitmap info: premul ARGB has best support in OS X */ + buffer, /* data: MacOSX lets system allocate, iPhoneOS use manual memory mapping */ + job->width, /* width in pixels */ + job->height, /* height in pixels */ + BITS_PER_COMPONENT, /* bits per component */ + bytes_per_row, /* bytes per row: align to 16 byte boundary */ + color_space, /* color space: device RGB */ + kCGImageAlphaPremultipliedFirst /* bitmap info: premul ARGB has best support in OS X */ ); job->imagedata = CGBitmapContextGetData((CGContextRef)job->context); @@ -228,6 +284,47 @@ static void quartzgen_path(GVJ_t *job, int filled) CGContextDrawPath(context, filled ? kCGPathFillStroke : kCGPathStroke); } +void quartzgen_textpara(GVJ_t *job, pointf p, textpara_t *para) +{ + CGContextRef context = (CGContextRef)job->context; + + /* adjust text position */ + switch (para->just) { + case 'r': + p.x -= para->width; + break; + case 'l': + p.x -= 0.0; + break; + case 'n': + default: + p.x -= para->width / 2.0; + break; + } + p.y += para->yoffset_centerline; + + void* layout; + if (para->free_layout == &quartz_free_layout) + layout = para->layout; + else + layout = quartz_new_layout(para->fontname, para->fontsize, para->str); + +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 + CGContextSaveGState(context); + CGContextScaleCTM(context, 1.0, -1.0); + p.y = -p.y - para->yoffset_layout; +#endif + CGContextSetRGBFillColor(context, job->obj->pencolor.u.RGBA[0], job->obj->pencolor.u.RGBA[1], job->obj->pencolor.u.RGBA[2], job->obj->pencolor.u.RGBA[3]); + quartz_draw_layout(layout, context, CGPointMake(p.x, p.y)); + +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 + CGContextRestoreGState(context); +#endif + + if (para->free_layout != &quartz_free_layout) + quartz_free_layout(layout); +} + static void quartzgen_ellipse(GVJ_t *job, pointf *A, int filled) { /* convert ellipse into the current path */ @@ -325,7 +422,7 @@ static gvrender_features_t render_features_quartz = { RGBA_DOUBLE /* color_type */ }; -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040 || __IPHONE_OS_VERSION_MIN_REQUIRED >= 20000 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 || __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 static gvdevice_features_t device_features_quartz = { GVDEVICE_BINARY_FORMAT | GVDEVICE_DOES_TRUECOLOR,/* flags */ @@ -352,10 +449,10 @@ gvplugin_installed_t gvrender_quartz_types[] = { gvplugin_installed_t gvdevice_quartz_types[] = { {FORMAT_PDF, "pdf:quartz", 8, NULL, &device_features_quartz_paged}, -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040 || __IPHONE_OS_VERSION_MIN_REQUIRED >= 20000 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 || __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 {FORMAT_CGIMAGE, "cgimage:quartz", 8, NULL, &device_features_quartz}, #endif -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1040 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 {FORMAT_BMP, "bmp:quartz", 8, NULL, &device_features_quartz}, {FORMAT_GIF, "gif:quartz", 8, NULL, &device_features_quartz}, {FORMAT_EXR, "exr:quartz", 8, NULL, &device_features_quartz}, diff --git a/plugin/quartz/gvtextlayout_quartz.c b/plugin/quartz/gvtextlayout_quartz.c index 10b64c495..ff4c1c4aa 100644 --- a/plugin/quartz/gvtextlayout_quartz.c +++ b/plugin/quartz/gvtextlayout_quartz.c @@ -24,9 +24,9 @@ #include "gvplugin_textlayout.h" #include "gvplugin_quartz.h" -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 -static CTLineRef quartz_new_layout(char* fontname, CGFloat fontsize, char* text) +void *quartz_new_layout(char* fontname, double fontsize, char* text) { CFStringRef fontnameref = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)fontname, strlen(fontname), kCFStringEncodingUTF8, FALSE); CFStringRef textref = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)text, strlen(text), kCFStringEncodingUTF8, FALSE); @@ -55,103 +55,73 @@ static CTLineRef quartz_new_layout(char* fontname, CGFloat fontsize, char* text) CFRelease(textref); if (fontnameref) CFRelease(fontnameref); - return line; + return (void *)line; } +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; +} -boolean quartz_textlayout(textpara_t *para, char **fontpath) +void quartz_draw_layout(void *layout, CGContextRef context, CGPoint position) { - CTLineRef line = quartz_new_layout(para->fontname, para->fontsize, para->str); - if (line) + CGContextSetTextPosition(context, position.x, position.y); + + CFArrayRef runs = CTLineGetGlyphRuns((CTLineRef)layout); + CFIndex run_count = CFArrayGetCount(runs); + CFIndex run_index; + for (run_index = 0; run_index < run_count; ++run_index) { - /* get the typographic bounds */ - CGFloat ascent = 0.0; - CGFloat descent = 0.0; - CGFloat leading = 0.0; - double width = CTLineGetTypographicBounds(line, &ascent, &descent, &leading); - CGFloat height = ascent + descent; + CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, run_index); + CTFontRef run_font = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName); + CGFontRef glyph_font = CTFontCopyGraphicsFont(run_font, NULL); + CFIndex glyph_count = CTRunGetGlyphCount(run); + CGGlyph glyphs[glyph_count]; + CGPoint positions[glyph_count]; + CFRange everything = CFRangeMake(0, 0); + CTRunGetGlyphs(run, everything, glyphs); + CTRunGetPositions(run, everything, positions); - /* report the layout */ - para->layout = (void*)line; - para->free_layout = &quartz_free_layout; - para->width = width; - para->height = leading == 0.0 ? height * 1.2 : height + leading; /* if no leading, use 20% of height */ - para->yoffset_layout = ascent; - para->yoffset_centerline = 0; - return TRUE; + CGContextSetFont(context, glyph_font); + CGContextSetFontSize(context, CTFontGetSize(run_font)); + CGContextShowGlyphsAtPositions(context, glyphs, positions, glyph_count); + + CGFontRelease(glyph_font); } - else - return FALSE; -}; +} void quartz_free_layout(void *layout) { if (layout) - CFRelease(layout); + CFRelease((CTLineRef)layout); }; -void quartzgen_textpara(GVJ_t *job, pointf p, textpara_t *para) -{ - CGContextRef context = (CGContextRef)job->context; +#endif - /* adjust text position */ - switch (para->just) { - case 'r': - p.x -= para->width; - break; - case 'l': - p.x -= 0.0; - break; - case 'n': - default: - p.x -= para->width / 2.0; - break; - } - p.y += para->yoffset_centerline; - - CTLineRef layout; - if (para->free_layout == &quartz_free_layout) - layout = (CTLineRef)para->layout; - else - layout = quartz_new_layout(para->fontname, para->fontsize, para->str); - - /* draw it */ - CGContextSetTextPosition(context, p.x, p.y); - if (job->obj->pencolor.u.RGBA [0] == 0.0 && job->obj->pencolor.u.RGBA [1] == 0.0 && job->obj->pencolor.u.RGBA [2] == 0.0 && job->obj->pencolor.u.RGBA [3] == 1.0) - /* optimized case for foreground color black */ - CTLineDraw(layout, context); - else +boolean quartz_textlayout(textpara_t *para, char **fontpath) +{ + void *line = quartz_new_layout(para->fontname, para->fontsize, para->str); + if (line) { - /* non-black foreground color, need to disassemble line manually and color it */ - CFArrayRef runs = CTLineGetGlyphRuns(layout); - CFIndex run_count = CFArrayGetCount(runs); - CFIndex run_index; - for (run_index = 0; run_index < run_count; ++run_index) - { - CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, run_index); - CTFontRef run_font = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName); - CGFontRef glyph_font = CTFontCopyGraphicsFont(run_font, NULL); - CFIndex glyph_count = CTRunGetGlyphCount(run); - CGGlyph glyphs[glyph_count]; - CGPoint positions[glyph_count]; - CFRange everything = CFRangeMake(0, 0); - CTRunGetGlyphs(run, everything, glyphs); - CTRunGetPositions(run, everything, positions); - - CGContextSetFont(context, glyph_font); - CGContextSetFontSize(context, CTFontGetSize(run_font)); - CGContextSetRGBFillColor(context, job->obj->pencolor.u.RGBA [0], job->obj->pencolor.u.RGBA [1], job->obj->pencolor.u.RGBA [2], job->obj->pencolor.u.RGBA [3]); - CGContextShowGlyphsAtPositions(context, glyphs, positions, glyph_count); - - CGFontRelease(glyph_font); - } + /* report the layout */ + para->layout = (void*)line; + para->free_layout = &quartz_free_layout; + para->yoffset_centerline = 0; + quartz_size_layout((void*)line, ¶->width, ¶->height, ¶->yoffset_layout); + return TRUE; } - - if (para->free_layout != &quartz_free_layout) - CFRelease(layout); -} - -#endif + else + return FALSE; +}; static gvtextlayout_engine_t quartz_textlayout_engine = { quartz_textlayout -- 2.40.0