Implement CTFontCreatePathForGlyph#1330
Conversation
- Minor style changes to CTFont.mm Fixes microsoft#922
| fontTransformWithoutTranslate.ty = 0; | ||
| CGAffineTransform totalTransform = CGAffineTransformConcat(fontTransformWithoutTranslate, scaleByFontSize); | ||
|
|
||
| // Compare against a transformed version of expectedElements |
There was a problem hiding this comment.
a transformed version of expectedElements [](start = 23, length = 41)
i wanted to use CGPathCreateCopyByTransformingPath, but we don't have that yet :( #Resolved
| } | ||
|
|
||
| HRESULT CGPathGeometrySink::RuntimeClassInitialize() { | ||
| return S_OK; |
There was a problem hiding this comment.
nit: These two could be in the body of the class, right? #Resolved
There was a problem hiding this comment.
yeah, I copied the template from mnithish's code above
In reply to: 86887974 [](ancestors = 86887974)
| break; | ||
|
|
||
| default: | ||
| EXPECT_TRUE_MSG(false, @"An invalid CGPathElementType was returned from CTFontCreatePathForGlyph"); |
There was a problem hiding this comment.
EXPECT_TRUE_MSG [](start = 16, length = 15)
you could FAIL() << "message" for this to escape the weird EXPECT_TRUE(false) #Resolved
There was a problem hiding this comment.
Or, ADD_FAILURE_AT() << "msg" to make it a non-fatal failure.
In reply to: 86888788 [](ancestors = 86888788)
There was a problem hiding this comment.
| CGPathAddCurveToPoint(_cgPath.get(), | ||
| _transform, | ||
| beziers[i].point1.x, | ||
| -beziers[i].point1.y, |
There was a problem hiding this comment.
-beziers[i].point1.y [](start = 34, length = 20)
nit: maybe add parens around this so the unary - sticks out more, right now it's super sneaky #WontFix
There was a problem hiding this comment.
Mm, tried it, it looks funky to me, and I called these out in the class comment anyway. Going to leave as-is.
In reply to: 86891299 [](ancestors = 86891299)
| } | ||
|
|
||
| void STDMETHODCALLTYPE AddLines(_In_ const D2D1_POINT_2F* points, unsigned int pointsCount) { | ||
| // Could have used CGPathAddLines instead, |
There was a problem hiding this comment.
// Could have used CGPathAddLines instead, [](start = 8, length = 42)
nit: feels more like a commit comment than in-code #Resolved
There was a problem hiding this comment.
|
|
||
| /** | ||
| * Custom IDWriteGeometrySink class that captures the glyph runs generated by | ||
| * DWrite for the given TextLayout and TextRenderer constraints. |
| * IDWriteFontFace::GetGlyphRunOutline uses this class in a single-threaded manner (dumping the draw instructions from the font linearly) | ||
| * As such, this class is deliberately left thread-unsafe. | ||
| */ | ||
| class CGPathGeometrySink : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IDWriteGeometrySink> { |
There was a problem hiding this comment.
CGPathGeometrySink [](start = 6, length = 18)
nit: class name should follow framework naming convention #Resolved
There was a problem hiding this comment.
There was a problem hiding this comment.
__CTPathGeometrySink if it's only going to be used here #Resolved
|
|
||
| CGPathGeometrySink::CGPathGeometrySink(const CGAffineTransform* transform) { | ||
| _cgPath.reset(CGPathCreateMutable()); | ||
| _transform = transform; |
There was a problem hiding this comment.
_transform [](start = 4, length = 10)
leaking? #ByDesign
There was a problem hiding this comment.
| EXPECT_TRUE_MSG(false, @"An invalid CGPathElementType was returned from CTFontCreatePathForGlyph"); | ||
| break; | ||
| } | ||
| ++comparePathContext->count; |
There was a problem hiding this comment.
comparePathContext [](start = 10, length = 18)
nit: parens for clear operator precedence #Resolved
|
|
| switch (element->type) { | ||
| case kCGPathElementMoveToPoint: | ||
| case kCGPathElementAddLineToPoint: | ||
| EXPECT_NEAR(comparePathContext->expectedElements[comparePathContext->count].point.x, element->points[0].x, 0.002f); |
There was a problem hiding this comment.
0.002f [](start = 123, length = 6)
nit: make this a constant #Resolved
|
|
||
| CGPathGeometrySink::CGPathGeometrySink(const CGAffineTransform* transform) { | ||
| _cgPath.reset(CGPathCreateMutable()); | ||
| _transform = transform; |
There was a problem hiding this comment.
Transform is stored by pointer, thereby requiring the caller manages its lifetime. could you make a copy here instead, so this class can be free-standing? #Resolved
| static const CFStringRef c_courierNewBoldName = CFSTR("Courier New Bold"); | ||
| static const CFStringRef c_courierNewBoldItalicName = CFSTR("Courier New Bold Italic"); | ||
| static const CFStringRef c_trebuchetMSItalicName = CFSTR("Trebuchet MS Italic"); | ||
| static const CFStringRef c_timesNewRomanName = CFSTR("Times New Roman"); |
There was a problem hiding this comment.
Are we sure these fonts exist on the build server/phone? #ByDesign
There was a problem hiding this comment.
|
|
||
| // CGPath has support for both orders of Bezier curve, | ||
| // but DWrite's GeometrySink only supports cubic Bezier curves, and approximates any quadratic curves in terms of a cubic curve | ||
| // Eg: Reference platform quadratic curve: (previous endpoint), (512, 632), (480, 632) |
There was a problem hiding this comment.
The comments until this point are immensely useful in the context of the implementation code as well, would help to duplicate it there. #Resolved
| _invalidState = true; | ||
| } | ||
|
|
||
| return _invalidState ? E_INVALIDARG : S_OK; |
There was a problem hiding this comment.
E_UNEXPECTED is probably more appropriate given there are no args to this method. #Resolved
There was a problem hiding this comment.
isn't E_UNEXPECTED generally kind of scary? I was trying to go for something a bit lighter.
In reply to: 86893574 [](ancestors = 86893574)
There was a problem hiding this comment.
It is essentially saying that the object wasn't expecting the call at this point. E_FAIL is scarier. #Resolved
rajsesh
left a comment
There was a problem hiding this comment.
Per offline discussion, lets add a visual verification test as well, just to be complete. I am changing my status back to request changes so we get the sample work as well.
| * IDWriteFontFace::GetGlyphRunOutline uses this class in a single-threaded manner (dumping the draw instructions from the font linearly) | ||
| * As such, this class is deliberately left thread-unsafe. | ||
| */ | ||
| class CGPathGeometrySink : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IDWriteGeometrySink> { |
There was a problem hiding this comment.
__CTPathGeometrySink if it's only going to be used here #Resolved
| private: | ||
| woc::unique_cf<CGMutablePathRef> _cgPath; | ||
| const CGAffineTransform* _transform; | ||
| bool _figureInProgress = false; // Keeps track of whether this class is currently between a BeginFigure and EndFigure call |
There was a problem hiding this comment.
nit: maybe just an enum to hold the state rather than two bools #WontFix
| isa = PBXGroup; | ||
| children = ( | ||
| 1ED8201D1DD28D4D00DF2DD7 /* CTCPathForGlyphTestViewController.h */, | ||
| 1ED8201A1DD28D2700DF2DD7 /* CTCPathForGlyphTestViewController.h */, |
There was a problem hiding this comment.
oops I might've added it twice apparently? let me check #Resolved
| // - (void)drawRect:(CGRect)rect { | ||
| // } | ||
|
|
||
| // @end |
|
ping! |
Fixes #922
This change is