From 1bd2ca22c234b8e6d56cdffd0e741871a4e08364 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Fri, 6 Jan 2017 23:53:23 -0500 Subject: [PATCH] Some more work on the new Cocoa text drawing code. --- darwin/CMakeLists.txt | 1 + darwin/_old_drawtext.m | 48 ------------------------------------------ darwin/draw.h | 6 ++++++ darwin/draw.m | 6 +----- darwin/drawtext.m | 25 +++++++++++++++++++++- 5 files changed, 32 insertions(+), 54 deletions(-) create mode 100644 darwin/draw.h diff --git a/darwin/CMakeLists.txt b/darwin/CMakeLists.txt index 385a4a53..32d1b45e 100644 --- a/darwin/CMakeLists.txt +++ b/darwin/CMakeLists.txt @@ -44,6 +44,7 @@ list(APPEND _LIBUI_SOURCES ) set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE) +// TODO is this correct? list(APPEND _LIBUI_INCLUDEDIRS darwin ) diff --git a/darwin/_old_drawtext.m b/darwin/_old_drawtext.m index 14346784..72a8d2e6 100644 --- a/darwin/_old_drawtext.m +++ b/darwin/_old_drawtext.m @@ -227,54 +227,6 @@ void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *he freeFramesetter(&fs); } -// Core Text doesn't draw onto a flipped view correctly; we have to do this -// see the iOS bits of the first example at https://developer.apple.com/library/mac/documentation/StringsTextFonts/Conceptual/CoreText_Programming/LayoutOperations/LayoutOperations.html#//apple_ref/doc/uid/TP40005533-CH12-SW1 (iOS is naturally flipped) -// TODO how is this affected by the CTM? -static void prepareContextForText(CGContextRef c, CGFloat cheight, double *y) -{ - CGContextSaveGState(c); - CGContextTranslateCTM(c, 0, cheight); - CGContextScaleCTM(c, 1.0, -1.0); - CGContextSetTextMatrix(c, CGAffineTransformIdentity); - - // wait, that's not enough; we need to offset y values to account for our new flipping - *y = cheight - *y; -} - -// TODO placement is incorrect for Helvetica -void doDrawText(CGContextRef c, CGFloat cheight, double x, double y, uiDrawTextLayout *layout) -{ - struct framesetter fs; - CGRect rect; - CGPathRef path; - CTFrameRef frame; - - prepareContextForText(c, cheight, &y); - mkFramesetter(layout, &fs); - - // oh, and since we're flipped, y is the bottom-left coordinate of the rectangle, not the top-left - // since we are flipped, we subtract - y -= fs.extents.height; - - rect.origin = CGPointMake(x, y); - rect.size = fs.extents; - path = CGPathCreateWithRect(rect, NULL); - - frame = CTFramesetterCreateFrame(fs.fs, - CFRangeMake(0, 0), - path, - fs.frameAttrib); - if (frame == NULL) - complain("error creating CTFrame object in doDrawText()"); - CTFrameDraw(frame, c); - CFRelease(frame); - - CFRelease(path); - - freeFramesetter(&fs); - CGContextRestoreGState(c); -} - // LONGTERM provide an equivalent to CTLineGetTypographicBounds() on uiDrawTextLayout? // LONGTERM keep this for later features and documentation purposes diff --git a/darwin/draw.h b/darwin/draw.h new file mode 100644 index 00000000..41629809 --- /dev/null +++ b/darwin/draw.h @@ -0,0 +1,6 @@ +// 6 january 2017 + +struct uiDrawContext { + CGContextRef c; + CGFloat height; // needed for text; see below +}; diff --git a/darwin/draw.m b/darwin/draw.m index 262ad3e2..231b4dfd 100644 --- a/darwin/draw.m +++ b/darwin/draw.m @@ -1,5 +1,6 @@ // 6 september 2015 #import "uipriv_darwin.h" +#import "draw.h" struct uiDrawPath { CGMutablePathRef path; @@ -103,11 +104,6 @@ void uiDrawPathEnd(uiDrawPath *p) p->ended = TRUE; } -struct uiDrawContext { - CGContextRef c; - CGFloat height; // needed for text; see below -}; - uiDrawContext *newContext(CGContextRef ctxt, CGFloat height) { uiDrawContext *c; diff --git a/darwin/drawtext.m b/darwin/drawtext.m index cdf766f5..a7a400f7 100644 --- a/darwin/drawtext.m +++ b/darwin/drawtext.m @@ -1,5 +1,6 @@ // 2 january 2017 #import "uipriv_darwin.h" +#import "draw.h" struct uiDrawTextLayout { CFAttributedStringRef attrstr; @@ -124,9 +125,31 @@ void uiDrawFreeTextLayout(uiDrawTextLayout *tl) uiFree(tl); } -// TODO what is y, the top-left corner, bottom-left corner, topmost baseline, or bottommost baseline? +// TODO double-check helvetica +// TODO document that (x,y) is the top-left corner of the *entire frame* void uiDrawText(uiDrawContext *c, uiDrawTextLayout *tl, double x, double y) { + CGContextSaveGState(c->c); + + // Core Text doesn't draw onto a flipped view correctly; we have to pretend it was unflipped + // see the iOS bits of the first example at https://developer.apple.com/library/mac/documentation/StringsTextFonts/Conceptual/CoreText_Programming/LayoutOperations/LayoutOperations.html#//apple_ref/doc/uid/TP40005533-CH12-SW1 (iOS is naturally flipped) + // TODO how is this affected by a non-identity CTM? + CGContextTranslateCTM(c->c, 0, cheight); + CGContextScaleCTM(c->c, 1.0, -1.0); + CGContextSetTextMatrix(c->c, CGAffineTransformIdentity); + + // wait, that's not enough; we need to offset y values to account for our new flipping + y = c->height - y; + + // CTFrameDraw() draws in the path we specified when creating the frame + // this means that in our usage, CTFrameDraw() will draw at (0,0) + // so move the origin to be at (x,y) instead + // TODO are the signs correct? + CGContextTranslateCTM(c->c, x, y); + + CTFrameDraw(tl->frame, c->c); + + CGContextRestoreGState(c->c); } // TODO document that the width and height of a layout is not necessarily the sum of the widths and heights of its constituent lines; this is definitely untrue on OS X, where lines are placed in such a way that the distance between baselines is always integral