Skip to content

Commit

Permalink
[TTF] Model ascent and descent metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
codyd51 committed Feb 7, 2024
1 parent 09a7890 commit 2d8b1fd
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 29 deletions.
2 changes: 1 addition & 1 deletion rust_programs/ttf_renderer/src/character_map.rs
Expand Up @@ -232,7 +232,7 @@ pub(crate) fn parse_character_map(parser: &FontParser) -> BTreeMap<usize, usize>
.find_map(|_| {
let character_map_subtable =
CharacterMapSubtable::from_in_place_buf(parser.read_with_cursor(&mut cursor));
println!("Character map subtable {character_map_subtable:?}");
//println!("Character map subtable {character_map_subtable:?}");
let recognized_unicode_encodings = [
CharacterMapPlatformAndEncoding::Unicode(
CharacterMapUnicodeEncoding::Version2_0Bmp,
Expand Down
52 changes: 27 additions & 25 deletions rust_programs/ttf_renderer/src/hints.rs
Expand Up @@ -367,7 +367,7 @@ pub(crate) fn parse_instructions(
loop {
let opcode: &u8 = FontParser::read_data_with_cursor(instructions, &mut cursor);
if operations.should_print() {
print!("{cursor:04x}\t{opcode:02x}\t");
//print!("{cursor:04x}\t{opcode:02x}\t");
}
match opcode {
0x00 | 0x01 => {
Expand All @@ -379,7 +379,7 @@ pub(crate) fn parse_instructions(
};

if operations.should_print() {
println!("Set freedom and projection vectors to {axis:?}");
//println!("Set freedom and projection vectors to {axis:?}");
}
if operations.should_execute() {
graphics_state.projection_vector = axis;
Expand All @@ -391,7 +391,7 @@ pub(crate) fn parse_instructions(
let zone_number = graphics_state.pop();
let zone = Zone::from(zone_number);
if operations.should_print() {
println!("SZP0\tZone pointer 0 = {zone:?}");
//println!("SZP0\tZone pointer 0 = {zone:?}");
}
if operations.should_execute() {
graphics_state.zone_pointers[0] = zone;
Expand All @@ -406,7 +406,7 @@ pub(crate) fn parse_instructions(
true => "(taken)",
false => "(not taken)",
};
println!("ELSE {}", take_else_str);
//println!("ELSE {}", take_else_str);
}
if operations.should_execute() {
if !take_else {
Expand All @@ -425,11 +425,11 @@ pub(crate) fn parse_instructions(
0x23 => {
// Swap
if operations.should_print() {
println!("SWAP\ttop 2 stack elements");
//println!("SWAP\ttop 2 stack elements");
}
println!("Stack: ");
//println!("Stack: ");
for x in graphics_state.interpreter_stack.iter().rev() {
println!("\t\t\t{x:08x}");
//println!("\t\t\t{x:08x}");
}
if operations.should_execute() {
let e2 = graphics_state.pop();
Expand All @@ -443,7 +443,7 @@ pub(crate) fn parse_instructions(
// Function identifier number is popped from the stack
let function_identifier_number = graphics_state.pop();
if operations.should_print() {
println!("CALL #{function_identifier_number}");
//println!("CALL #{function_identifier_number}");
}
if operations.should_execute() {
let function = &font.functions_table[&(function_identifier_number as _)];
Expand All @@ -455,7 +455,7 @@ pub(crate) fn parse_instructions(
// Function identifier number is popped from the stack
let function_identifier_number = graphics_state.pop();
if operations.should_print() {
println!("Function define #{function_identifier_number}");
//println!("Function define #{function_identifier_number}");
}
if operations.should_execute() {
//
Expand All @@ -464,16 +464,18 @@ pub(crate) fn parse_instructions(
0x2d => {
// ENDF
if operations.should_print() {
println!("ENDF");
//println!("ENDF");
}
}
0x4b => {
// Measure pixels per em in the projection vector's axis
if operations.should_print() {
/*
println!(
"MPPEM\tMeasure pixels per em in {:?}",
graphics_state.projection_vector
);
*/
}
if operations.should_execute() {
let val = match graphics_state.projection_vector {
Expand All @@ -489,7 +491,7 @@ pub(crate) fn parse_instructions(
let e1 = graphics_state.pop();
let result = e1 < e2;
if operations.should_print() {
println!("LT\tLess than? {e1} < {e2} = {result}");
//println!("LT\tLess than? {e1} < {e2} = {result}");
}
if operations.should_execute() {
graphics_state.push(if result { 1 } else { 0 });
Expand All @@ -506,7 +508,7 @@ pub(crate) fn parse_instructions(
last_if_condition_passed = Some(condition_passed);

if operations.should_print() {
println!("IF\t{condition_passed}");
//println!("IF\t{condition_passed}");
}
if operations.should_execute() {
if !condition_passed {
Expand All @@ -526,14 +528,14 @@ pub(crate) fn parse_instructions(
0x59 => {
// Nothing to do
if operations.should_print() {
println!("EIF");
//println!("EIF");
}
}
0x5c => {
// NOT
let val = graphics_state.pop();
if operations.should_print() {
println!("NOT {val:08x}");
//println!("NOT {val:08x}");
}
if operations.should_execute() {
let result = if val != 0 { 0 } else { 1 };
Expand All @@ -554,15 +556,15 @@ pub(crate) fn parse_instructions(
let period = RoundStatePeriod::from(period_val as usize);

if operations.should_print() {
println!("SROUND\tperiod={period:?}, phase={phase:?}, threshold={threshold:?}");
//println!("SROUND\tperiod={period:?}, phase={phase:?}, threshold={threshold:?}");
}
if operations.should_execute() {
graphics_state.round_state = RoundState::new(period, phase, threshold);
}
//
}
0x77 => {
println!("TODO: Super round @ 45 degrees");
//println!("TODO: Super round @ 45 degrees");
let val = graphics_state.pop();
}
0x85 => {
Expand All @@ -572,7 +574,7 @@ pub(crate) fn parse_instructions(
let low = word & 0xff;
let high = (word >> 8) & 0xff;
if operations.should_print() {
println!("SCANCTRL {low:04x} : {high:04x}");
//println!("SCANCTRL {low:04x} : {high:04x}");
}
if operations.should_execute() {
// TODO(PT): Which axis should this use?
Expand All @@ -588,7 +590,7 @@ pub(crate) fn parse_instructions(
// GETINFO
let selector = graphics_state.pop();
if operations.should_print() {
println!("GETINFO");
//println!("GETINFO");
}
let mut result = 0_u32;
if operations.should_execute() {
Expand All @@ -609,7 +611,7 @@ pub(crate) fn parse_instructions(
// SCANTYPE
let word = graphics_state.pop();
if operations.should_print() {
println!("SCANTYPE {word:08x}");
//println!("SCANTYPE {word:08x}");
}
if operations.should_execute() {
graphics_state.scan_control.dropout_control_mode =
Expand All @@ -625,11 +627,11 @@ pub(crate) fn parse_instructions(
number_of_bytes_to_push as usize,
);
if operations.should_print() {
print!("Push {number_of_bytes_to_push} bytes:");
//print!("Push {number_of_bytes_to_push} bytes:");
for byte in bytes_to_push.iter() {
print!(" {byte:02x}");
//print!(" {byte:02x}");
}
println!();
//println!();
}
if operations.should_execute() {
for byte in bytes_to_push.iter() {
Expand All @@ -649,11 +651,11 @@ pub(crate) fn parse_instructions(
words_to_push.push(word);
}
if operations.should_print() {
print!("Push {number_of_words_to_push} words:");
//print!("Push {number_of_words_to_push} words:");
for word in words_to_push.iter() {
print!(" {word:02x}");
//print!(" {word:02x}");
}
println!();
//println!();
}
if operations.should_execute() {
for word in words_to_push.iter() {
Expand Down
34 changes: 31 additions & 3 deletions rust_programs/ttf_renderer/src/metrics.rs
@@ -1,6 +1,6 @@
use crate::parse_utils::{BigEndianValue, FromFontBufInPlace, TransmuteFontBufInPlace};
use crate::parser::FontParser;
use agx_definitions::Rect;
use agx_definitions::{Rect, Size};
use alloc::vec;
use alloc::vec::Vec;
use core::cell::RefCell;
Expand Down Expand Up @@ -32,17 +32,31 @@ impl TransmuteFontBufInPlace for HheaTableRaw {}

#[derive(Debug, Clone)]
pub struct HheaTable {
pub ascent: isize,
pub descent: isize,
pub line_gap: isize,
pub long_hor_metrics_count: usize,
}

impl FromFontBufInPlace<HheaTableRaw> for HheaTable {
fn from_in_place_buf(raw: &HheaTableRaw) -> Self {
Self {
ascent: raw.ascent.into_value() as _,
descent: raw.descent.into_value() as _,
line_gap: raw.line_gap.into_value() as _,
long_hor_metrics_count: raw.long_hor_metrics_count.into_value() as _,
}
}
}

#[derive(Debug, Clone)]
pub struct FontGlobalLayoutMetrics {
pub ascent: isize,
pub descent: isize,
pub line_gap: isize,
pub long_hor_metrics: Vec<LongHorMetric>,
}

#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
pub struct LongHorMetricRaw {
Expand Down Expand Up @@ -161,6 +175,14 @@ impl GlyphRenderMetrics {
let horizontal_metrics = self.horizontal_metrics.borrow();
let vertical_metrics = self.vertical_metrics.borrow();
let h = horizontal_metrics.as_ref().unwrap();
// TODO(PT): We're not finding vertical metrics for any glyph! This is causing the rendering to go bad?
// Update: vmtx is only for vertical-layout scripts, not English, so I had a misunderstanding
/*
println!(
"Found vert metrics? {}",
vertical_metrics.as_ref().is_some()
);
*/
let v = vertical_metrics
.as_ref()
.unwrap_or(&VerticalMetrics {
Expand All @@ -177,7 +199,7 @@ impl GlyphRenderMetrics {
}
}

pub(crate) fn parse_horizontal_metrics(parser: &FontParser) -> Vec<LongHorMetric> {
pub(crate) fn parse_horizontal_metrics(parser: &FontParser) -> FontGlobalLayoutMetrics {
let hhea: HheaTable = parser.parse_table("hhea");
let hmtx_offset = parser.table_headers.get("hmtx").unwrap().offset;
let mut cursor = hmtx_offset;
Expand All @@ -186,13 +208,19 @@ pub(crate) fn parse_horizontal_metrics(parser: &FontParser) -> Vec<LongHorMetric
let glyph_metric = LongHorMetric::from_in_place_buf(parser.read_with_cursor(&mut cursor));
glyph_metrics.push(glyph_metric);
}
glyph_metrics
FontGlobalLayoutMetrics {
ascent: hhea.ascent,
descent: hhea.descent,
line_gap: hhea.line_gap,
long_hor_metrics: glyph_metrics,
}
}

pub(crate) fn parse_vertical_metrics(
parser: &FontParser,
glyph_count: usize,
) -> Option<Vec<VerticalMetrics>> {
//println!("Vmtx table {:?}", parser.table_headers.get("vmtx"));
let vmtx_offset = match parser.table_headers.get("vmtx") {
None => return None,
Some(vmtx_header) => vmtx_header.offset,
Expand Down

0 comments on commit 2d8b1fd

Please sign in to comment.