Some more work on the new Cocoa text drawing code.

This commit is contained in:
Pietro Gagliardi 2017-01-06 23:53:23 -05:00
parent 6212ac7238
commit 1bd2ca22c2
5 changed files with 32 additions and 54 deletions

View File

@ -44,6 +44,7 @@ list(APPEND _LIBUI_SOURCES
)
set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE)
// TODO is this correct?
list(APPEND _LIBUI_INCLUDEDIRS
darwin
)

View File

@ -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

6
darwin/draw.h Normal file
View File

@ -0,0 +1,6 @@
// 6 january 2017
struct uiDrawContext {
CGContextRef c;
CGFloat height; // needed for text; see below
};

View File

@ -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;

View File

@ -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