Skip to content

Commit

Permalink
Implement CTFontGetVerticalTranslationsForGlyphs (#2104)
Browse files Browse the repository at this point in the history
Fixes #2025

There is a magic number that the reference platform adds to every vertical glyph translation independent of font. With this constant added to all vertical translations we are within 1 design unit of reference platform values.
  • Loading branch information
aballway authored Mar 1, 2017
1 parent 5e79572 commit 3740a7e
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 10 deletions.
29 changes: 24 additions & 5 deletions Frameworks/CoreText/CTFont.mm
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@
const CFStringRef kCTFontDefaultItalicFontName = CFSTR("Arial Italic");
const CFStringRef kCTFontDefaultMonospacedFontName = CFSTR("Courier New");

// Reference platform adds a constant amount of space (scaled by font size) to each glyph's vertical translation
static const int sc_verticalTranslationSpace = 102;

using namespace Microsoft::WRL;

struct __CTFont {
Expand Down Expand Up @@ -710,8 +713,8 @@ CGPathRef CTFontCreatePathForGlyph(CTFontRef font, CGGlyph glyph, const CGAffine
}

/**
@Status Stub
@Notes
@Status NotInPlan
@Notes Not much usage, can be easily replaced with CTFontGetGlyphsForCharacters in most common uses
*/
CGGlyph CTFontGetGlyphWithName(CTFontRef font, CFStringRef glyphName) {
UNIMPLEMENTED();
Expand Down Expand Up @@ -796,11 +799,27 @@ CGRect CTFontGetBoundingRectsForGlyphs(
}

/**
@Status Stub
@Status Interoperable
@Notes
*/
void CTFontGetVerticalTranslationsForGlyphs(CTFontRef font, const CGGlyph glyphs[], CGSize translations[], CFIndex count) {
UNIMPLEMENTED();
if (font && glyphs && translations && count > 0L) {
DWRITE_GLYPH_METRICS metrics[count];
if (FAILED(font->_dwriteFontFace->GetDesignGlyphMetrics(glyphs, count, metrics, false))) {
TraceError(g_logTag, L"Unable to get glyph metrics");
return;
}

std::transform(metrics, metrics + count, translations, [font](const DWRITE_GLYPH_METRICS& metrics) {
if (metrics.advanceWidth == metrics.rightSideBearing && metrics.verticalOriginY == metrics.topSideBearing) {
// Special case of empty glyph, should just return CGRectZero;
return CGSizeZero;
}

return CGSize{ -__CTFontScaleMetric(font, (metrics.advanceWidth / 2)),
-__CTFontScaleMetric(font, metrics.verticalOriginY - metrics.topSideBearing + sc_verticalTranslationSpace) };
});
}
}

/**
Expand Down Expand Up @@ -951,4 +970,4 @@ DWRITE_FONT_STYLE _CTFontGetDWriteStyle(CTFontRef font) {
return fontFace3->GetStyle();
}
return DWRITE_FONT_STYLE_NORMAL;
}
}
5 changes: 2 additions & 3 deletions include/CoreText/CTFont.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,12 @@ CORETEXT_EXPORT CGFloat CTFontGetSlantAngle(CTFontRef font);
CORETEXT_EXPORT CGFloat CTFontGetCapHeight(CTFontRef font);
CORETEXT_EXPORT CGFloat CTFontGetXHeight(CTFontRef font);
CORETEXT_EXPORT CGPathRef CTFontCreatePathForGlyph(CTFontRef font, CGGlyph glyph, const CGAffineTransform* matrix);
CORETEXT_EXPORT CGGlyph CTFontGetGlyphWithName(CTFontRef font, CFStringRef glyphName) STUB_METHOD;
CORETEXT_EXPORT CGGlyph CTFontGetGlyphWithName(CTFontRef font, CFStringRef glyphName) NOTINPLAN_METHOD;
CORETEXT_EXPORT CGRect CTFontGetBoundingRectsForGlyphs(
CTFontRef font, CTFontOrientation orientation, const CGGlyph glyphs[], CGRect* boundingRects, CFIndex count);
CORETEXT_EXPORT double CTFontGetAdvancesForGlyphs(
CTFontRef font, CTFontOrientation orientation, const CGGlyph glyphs[], CGSize* advances, CFIndex count);
CORETEXT_EXPORT void CTFontGetVerticalTranslationsForGlyphs(CTFontRef font, const CGGlyph glyphs[], CGSize translations[], CFIndex count)
STUB_METHOD;
CORETEXT_EXPORT void CTFontGetVerticalTranslationsForGlyphs(CTFontRef font, const CGGlyph glyphs[], CGSize translations[], CFIndex count);
CORETEXT_EXPORT CFArrayRef CTFontCopyVariationAxes(CTFontRef font) STUB_METHOD;
CORETEXT_EXPORT CFDictionaryRef CTFontCopyVariation(CTFontRef font) STUB_METHOD;
CORETEXT_EXPORT CFArrayRef CTFontCopyFeatures(CTFontRef font) STUB_METHOD;
Expand Down
26 changes: 24 additions & 2 deletions tests/unittests/CoreText/CTFontTests.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//******************************************************************************
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
Expand Down Expand Up @@ -740,4 +740,26 @@ virtual void TearDown() {
});
CGPathApply(pathWithFontSizeAndTransforms, &comparePathContext, comparePathToExpected);
ASSERT_EQ(expectedElements.size(), comparePathContext.count);
}
}

TEST(CTFont, GetVerticalTranslationsForGLyphs) {
auto font = woc::MakeAutoCF<CTFontRef>(CTFontCreateWithName(CFSTR("Arial"), 20, nullptr));
UniChar chars[6] = { 'T', 'e', 's', 't', ' ', '_' };
CGGlyph glyphs[6];
CTFontGetGlyphsForCharacters(font, chars, glyphs, 6);

CGSize translations[6];
CTFontGetVerticalTranslationsForGlyphs(font, glyphs, translations, 6);
EXPECT_NEAR(-6.1035, translations[0].width, c_errorMargin);
EXPECT_NEAR(-5.5566, translations[1].width, c_errorMargin);
EXPECT_NEAR(-5.000, translations[2].width, c_errorMargin);
EXPECT_NEAR(-2.7734, translations[3].width, c_errorMargin);
EXPECT_NEAR(0, translations[4].width, c_errorMargin);
EXPECT_NEAR(-5.5566, translations[5].width, c_errorMargin);
EXPECT_NEAR(-15.3125, translations[0].height, c_errorMargin);
EXPECT_NEAR(-11.6016, translations[1].height, c_errorMargin);
EXPECT_NEAR(-11.6016, translations[2].height, c_errorMargin);
EXPECT_NEAR(-14.9902, translations[3].height, c_errorMargin);
EXPECT_NEAR(0, translations[4].height, c_errorMargin);
EXPECT_NEAR(1.70898, translations[5].height, c_errorMargin);
}

0 comments on commit 3740a7e

Please sign in to comment.