Skip to content
This repository was archived by the owner on Jan 3, 2025. It is now read-only.

Add CoreText renderer plugin#1

Merged
danpla merged 6 commits intodanpla:masterfrom
usr-sse2:master
Jun 20, 2020
Merged

Add CoreText renderer plugin#1
danpla merged 6 commits intodanpla:masterfrom
usr-sse2:master

Conversation

@usr-sse2
Copy link
Copy Markdown

@usr-sse2 usr-sse2 commented May 4, 2020

Uses native rendering engine on macOS.

I had to move Size and Point into Geometry namespace, because Size and Point are already defined in /usr/include/MacTypes.h which is included from CoreFoundation.h.

Michael Belyaev added 2 commits May 4, 2020 13:26
Copy link
Copy Markdown
Owner

@danpla danpla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the pull request!

Comment on lines +29 to +30
CFStringRef fontName = CFStringCreateWithCString(NULL, (const char*)args.data, kCFStringEncodingUTF8);
font = CTFontCreateWithName(fontName, args.pxSize, NULL);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with Core Text, but is it OK that you pass the whole font data as a name?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I forgot to look at this, though it worked for the font which I needed.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOL, it just used Helvetica as default font, because there is no font named ttcf, and I only needed Helvetica. Fixed with c7b8761, tested on Times and Helvetica.

Comment on lines +71 to +78
glyphMetrics.size.w = ceil(boundingRect.size.width) + ceil(boundingRect.origin.x);
#else
glyphMetrics.size.w = ceil(boundingRect.size.width);
#endif
glyphMetrics.offset.x = ceil(boundingRect.origin.x);

glyphMetrics.size.h = ceil(boundingRect.size.height);
glyphMetrics.offset.y = ceil(boundingRect.size.height) + ceil(boundingRect.origin.y);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why boundingRect.origin contributes to size of the glyph's bitmap? Have you tried to render the text with tools/draw-text.py?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about FreeType and STB, but CoreText draws and calculates everything in floating-point. Most glyphs have non-integer offsets, and if we shift them back so they are rendered from point 0 in our bitmap (by setting position.x=-origin.x), they are displayed slightly different from their original shape. That's why I set position.x=0, so the glyph is rendered starting at its origin.x. But then it's needed to increase the width, so it wouldn't get cut, and set our local origin to 0 (which I forgot to do and now fixed by 88c07d8), because the true origin (floating-point) is already included in our bitmap. I've illustrated it with a drawing:
IMG_5782

Here is an image which was generated by draw-text.py with CORETEXT_SHIFT_X_POSITION=0:
mhd_0
Here is an image which was generated by draw-text.py with CORETEXT_SHIFT_X_POSITION=1:
mhd_1
The second one looks almost like rendered by Core Text.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both x and y offsets should be in GlyphMetrics::offset, so that they are added during drawing and not baked right into a glyph bitmap.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are integer, we can't shift a bitmap by less than a pixel. It's done like you want when CORETEXT_SHIFT_POSITION=0 and you see what happens.

Comment on lines +98 to +104
CGPoint position = boundingRect.origin;
#if CORETEXT_SHIFT_X_POSITION
position.x = 0;
#else
position.x = -position.x;
#endif
position.y = -position.y;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can as well just set coordinates to 0.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x is explained in the upper conversation, and y should be subtracted, otherwise it's rendered outside of the provided area. dpFontBaker expects that the glyph image will be rendered from (0,0) to (width,height). If we ask CoreText to render a glyph at (0,0), it will be placed from (0+x,0+y) to (x+width,y+height).

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry, I mixed it up with -= operator.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The renderGlyph() method fills an image of GlyphMetrics::size size, which should be boundingRect.size in your case; the size should not include drawing offsets.

@vit9696
Copy link
Copy Markdown

vit9696 commented Jun 19, 2020

Ping, we are interested in that landing upstream.

@danpla danpla merged commit 6fcfccf into danpla:master Jun 20, 2020
@danpla
Copy link
Copy Markdown
Owner

danpla commented Jun 20, 2020

I made some changes and fixes, fell free to review:

6fcfccf...89c4ff8

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants