From 9a1ceaa5c8487efe6b139436a2a0b237ecd2d66e Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 1 Aug 2016 12:27:29 +0000 Subject: [PATCH] Unbreak TTF metrics. In 2.0, the distance between the points in the TTF request specified cap height. In 2.1, that was accidentally changed to some arbitrary value near cap height instead, due to a 72pt factor mess-up. This commit restores the old behavior. --- CHANGELOG.md | 1 + src/ttf.cpp | 29 +++++++++++++++++++++-------- test/request/ttf_text/normal.png | Bin 5390 -> 6138 bytes 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c553b6d..d0c1c73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Bug fixes: * OS X: do not completely hide main window when defocused. * GTK: unbreak 3Dconnexion support. * When pasting transformed entities, multiply constraint values by scale. + * Fix TTF font metrics (restore the behavior from version 2.0). 2.1 --- diff --git a/src/ttf.cpp b/src/ttf.cpp index c1555fc..32cd1f6 100644 --- a/src/ttf.cpp +++ b/src/ttf.cpp @@ -211,15 +211,19 @@ static int CubicTo(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *p, return 0; } -static const FT_Outline_Funcs outline_funcs = { - MoveTo, LineTo, ConicTo, CubicTo, 0, 0 -}; - void TtfFont::PlotString(const std::string &str, SBezierList *sbl, Vector origin, Vector u, Vector v) { ssassert(fontFace != NULL, "Expected font face to be loaded"); + FT_Outline_Funcs outlineFuncs; + outlineFuncs.move_to = MoveTo; + outlineFuncs.line_to = LineTo; + outlineFuncs.conic_to = ConicTo; + outlineFuncs.cubic_to = CubicTo; + outlineFuncs.shift = 0; + outlineFuncs.delta = 0; + FT_Pos dx = 0; for(char32_t chr : ReadUTF8(str)) { uint32_t gid = FT_Get_Char_Index(fontFace, chr); @@ -228,8 +232,17 @@ void TtfFont::PlotString(const std::string &str, chr, ft_error_string(gid)); } - FT_F26Dot6 scale = fontFace->units_per_EM; - if(int fterr = FT_Set_Char_Size(fontFace, scale, scale, 72, 72)) { + // We always ask Freetype to give us a unit size character. + // It uses fixed point; put the unit size somewhere in the middle of the dynamic + // range of its 26.6 fixed point type, and adjust the factors so that the unit + // matches cap height. + FT_Size_RequestRec sizeRequest; + sizeRequest.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; + sizeRequest.width = 1 << 16; + sizeRequest.height = 1 << 16; + sizeRequest.horiResolution = 128; + sizeRequest.vertResolution = 128; + if(int fterr = FT_Request_Size(fontFace, &sizeRequest)) { dbp("freetype: cannot set character size: %s", ft_error_string(fterr)); return; @@ -274,9 +287,9 @@ void TtfFont::PlotString(const std::string &str, data.u = u; data.v = v; data.beziers = sbl; - data.factor = 1.0f/(float)scale; + data.factor = 1.0f/(float)(1 << 16); data.bx = bx; - if(int fterr = FT_Outline_Decompose(&fontFace->glyph->outline, &outline_funcs, &data)) { + if(int fterr = FT_Outline_Decompose(&fontFace->glyph->outline, &outlineFuncs, &data)) { dbp("freetype: bezier decomposition failed (gid %d): %s", gid, ft_error_string(fterr)); } diff --git a/test/request/ttf_text/normal.png b/test/request/ttf_text/normal.png index 1e35997ef5c70cc4a9dddcdecc8f1ef1f2ae6934..f97213cf1ec09b7f5e77d76826c897440482d833 100644 GIT binary patch literal 6138 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 literal 5390 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 M6YD*>yU>yU22fj42><{9