From c0914a0c875862cb3ca44be672ee252eacb300fe Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Aug 2017 12:20:36 -0700 Subject: [PATCH] Fix a bunch of text layout issues --- demo/client/src/index.ts | 11 +++++++++-- font-renderer/src/lib.rs | 25 ++++++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/demo/client/src/index.ts b/demo/client/src/index.ts index dcfeb2b8..df343475 100644 --- a/demo/client/src/index.ts +++ b/demo/client/src/index.ts @@ -709,12 +709,18 @@ class PathfinderView { for (let textGlyphIndex = 0; textGlyphIndex < textGlyphs.length; textGlyphIndex++) { const textGlyph = textGlyphs[textGlyphIndex]; + const textGlyphMetrics = textGlyph.getMetrics(); const atlasGlyphIndex = _.sortedIndexOf(atlasGlyphIndices, textGlyph.getIndex()); const atlasGlyph = atlasGlyphs[atlasGlyphIndex]; // Set positions. - const textGlyphBL = currentPosition, textGlyphTR = glmatrix.vec2.create(); + const textGlyphBL = glmatrix.vec2.create(), textGlyphTR = glmatrix.vec2.create(); + const offset = glmatrix.vec2.fromValues(textGlyphMetrics.leftSideBearing, + textGlyphMetrics.yMin); + glmatrix.vec2.scale(offset, offset, this.pixelsPerUnit); + glmatrix.vec2.add(textGlyphBL, currentPosition, offset); + glmatrix.vec2.round(textGlyphBL, textGlyphBL); glmatrix.vec2.add(textGlyphTR, textGlyphBL, atlasGlyph.atlasSize); glyphPositions.set([ @@ -743,7 +749,7 @@ class PathfinderView { textGlyphIndex * 6); // Advance. - currentPosition[0] += Math.round(textGlyph.advanceWidth * this.pixelsPerUnit); + currentPosition[0] += textGlyph.advanceWidth * this.pixelsPerUnit; } this.glyphPositionsBuffer = unwrapNull(this.gl.createBuffer()); @@ -2037,6 +2043,7 @@ class Atlas { for (const glyph of glyphs) { const metrics = glyph.metrics; + const glyphSize = glmatrix.vec2.fromValues(metrics.xMax - metrics.xMin, metrics.yMax - metrics.yMin); glmatrix.vec2.scale(glyphSize, glyphSize, pixelsPerUnit); diff --git a/font-renderer/src/lib.rs b/font-renderer/src/lib.rs index 0f23364e..bdef8c1e 100644 --- a/font-renderer/src/lib.rs +++ b/font-renderer/src/lib.rs @@ -35,6 +35,8 @@ const GLYPH_LOAD_FLAGS: FT_Int32 = FT_LOAD_TARGET_LIGHT; const FREETYPE_POINT_ON_CURVE: i8 = 0x01; +const DPI: u32 = 72; + pub struct FontContext { library: FT_Library, faces: BTreeMap, @@ -113,8 +115,8 @@ impl FontContext { }; unsafe { - let point_size = (font_instance.size.to_f64_px() / 72.0).to_ft_f26dot6(); - FT_Set_Char_Size(face.face, point_size, 0, 72, 0); + let point_size = (font_instance.size.to_f64_px() / (DPI as f64)).to_ft_f26dot6(); + FT_Set_Char_Size(face.face, point_size, 0, DPI, 0); if FT_Load_Glyph(face.face, glyph_key.glyph_index as FT_UInt, GLYPH_LOAD_FLAGS) != 0 { return None @@ -188,13 +190,12 @@ impl FontContext { let mut current_control_point_index = None; let last_point_index = *outline.contours.offset(contour_index as isize) as u32 + 1; for point_index in first_point_index..last_point_index { - // FIXME(pcwalton): Use `units_per_EM` to do this conversion? // TODO(pcwalton): Approximate cubic Béziers with quadratics. - // FIXME(pcwalton): Does FreeType produce multiple consecutive off-curve points - // in a row like raw TrueType does? let point = *outline.points.offset(point_index as isize); - let point_position = transform.transform_point(&Point2D::new(point.x as f32, - point.y as f32)); + let point_position = Point2D::new(f32::from_ft_f26dot6(point.x as FT_F26Dot6), + f32::from_ft_f26dot6(point.y as FT_F26Dot6)); + let point_position = point_position * (DPI as f32); + let point_position = transform.transform_point(&point_position); if (*outline.tags.offset(point_index as isize) & FREETYPE_POINT_ON_CURVE) != 0 { glyph_outline_buffer.endpoints.push(Endpoint { position: point_position, @@ -314,6 +315,16 @@ impl Drop for Face { } } +trait FromFtF26Dot6 { + fn from_ft_f26dot6(value: FT_F26Dot6) -> Self; +} + +impl FromFtF26Dot6 for f32 { + fn from_ft_f26dot6(value: FT_F26Dot6) -> f32 { + (value as f32) / 64.0 + } +} + trait ToFtF26Dot6 { fn to_ft_f26dot6(&self) -> FT_F26Dot6; }