Skip to content

Commit 75539a0

Browse files
committed
chore: change rasterization baseline constant to maintain existing behavior
1 parent 86d0705 commit 75539a0

1 file changed

Lines changed: 34 additions & 9 deletions

File tree

plotters/src/style/font/ttf.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,14 @@ impl FontData for FontDataInternal {
189189
let glyph_metrics = font_ref.glyph_metrics(&[]).scale(em);
190190
let charmap = font_ref.charmap();
191191

192-
base_y -= (0.24 * em) as i32;
192+
// Place the swash pen at the baseline. font-kit rasterized into a
193+
// `size`-square canvas whose top sat at `pos.y - 0.24*em`, then
194+
// applied a `(0, em)` rasterization translation, putting the
195+
// effective baseline at `pos.y + 0.76*em`. Swash places glyphs
196+
// relative to the pen directly, so we shift the pen to that same
197+
// baseline; otherwise glyphs render ~one em above where callers
198+
// expect them.
199+
base_y += (0.76 * em) as i32;
193200

194201
let mut prev = None;
195202
let place_holder = glyph_for_char(&charmap, PLACEHOLDER_CHAR);
@@ -277,13 +284,15 @@ mod test {
277284
}
278285

279286
fn assert_draw_sanity(family: FontFamily<'_>, style: FontStyle) -> FontResult<()> {
280-
let size = 32.0;
281-
let em = size / 1.24;
282-
let baseline = (size as i32) - (0.24 * em as f32) as i32;
287+
let size = 32.0_f64;
288+
let em = (size / 1.24) as f32;
289+
let pos_y = size as i32;
290+
// Baseline must match the pen position chosen in `draw`.
291+
let baseline = pos_y + (0.76 * em) as i32;
283292
let font = FontDataInternal::new(family, style)?;
284293
let mut samples = Vec::new();
285294

286-
let draw_result = font.draw((0, size as i32), size, "Hg", |x, y, alpha| {
295+
let draw_result = font.draw((0, pos_y), size, "Hg", |x, y, alpha| {
287296
samples.push((x, y, alpha));
288297
Ok::<(), ()>(())
289298
})?;
@@ -311,16 +320,24 @@ mod test {
311320
let min_y = touched.iter().map(|(_, y, _)| *y).min().unwrap();
312321
let max_y = touched.iter().map(|(_, y, _)| *y).max().unwrap();
313322

323+
// Baseline-anchored bounds. The pen is at output y = `baseline`,
324+
// ascenders extend up by ~em and descenders down by ~0.3*em.
314325
assert!(min_x >= 0, "glyphs drifted left: min_x={}", min_x);
315-
assert!(min_y >= 0, "glyphs drifted above canvas: min_y={}", min_y);
326+
assert!(
327+
min_y >= baseline - (1.2 * em) as i32,
328+
"glyphs drifted too high above baseline {}: min_y={}",
329+
baseline,
330+
min_y
331+
);
316332
assert!(
317333
max_x <= (3.0 * em) as i32,
318334
"glyphs drifted right: max_x={}",
319335
max_x
320336
);
321337
assert!(
322-
max_y <= (1.5 * em) as i32,
323-
"glyphs drifted below canvas: max_y={}",
338+
max_y <= baseline + (0.6 * em) as i32,
339+
"glyphs drifted too far below baseline {}: max_y={}",
340+
baseline,
324341
max_y
325342
);
326343

@@ -334,11 +351,19 @@ mod test {
334351
max_y
335352
);
336353

354+
// Cap height should sit above the baseline by a meaningful amount.
355+
assert!(
356+
min_y < baseline,
357+
"expected glyph tops above baseline {}: min_y={}",
358+
baseline,
359+
min_y
360+
);
361+
337362
// The touched bbox should span roughly one em vertically; this
338363
// guards against placement.top being applied with the wrong scale.
339364
let bbox_height = (max_y - min_y) as f32;
340365
assert!(
341-
(0.5 * em as f32..=1.5 * em as f32).contains(&bbox_height),
366+
(0.5 * em..=1.5 * em).contains(&bbox_height),
342367
"bbox height {} not within [0.5*em, 1.5*em] (em={})",
343368
bbox_height,
344369
em

0 commit comments

Comments
 (0)