port Font to Rust

This commit is contained in:
Jacob Lifshay 2026-01-01 23:14:08 -08:00
parent 944ae4bf41
commit 8643d47338
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ

View file

@ -1,5 +1,517 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use non_nan_float::NonNaNF32;
mod quad_tree;
mod non_nan_float {
#[derive(Default, PartialEq, PartialOrd, Clone, Copy)]
pub(crate) struct NonNaNF32(f32);
impl std::fmt::Debug for NonNaNF32 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl std::fmt::Display for NonNaNF32 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl NonNaNF32 {
pub(crate) const fn new(v: f32) -> Option<Self> {
if v.is_nan() { None } else { Some(Self(v)) }
}
pub(crate) const fn get(self) -> f32 {
self.0
}
}
impl std::hash::Hash for NonNaNF32 {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
if self.0 == 0.0 { 0.0 } else { self.0 }
.to_bits()
.hash(state);
}
}
impl Eq for NonNaNF32 {}
impl Ord for NonNaNF32 {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other).expect("known to be non-NaN")
}
}
}
macro_rules! make_enum_font {
(
enum $Font:ident {
#[other]
$Other:ident $other_body:tt,
$(#[group]
$KnownFontGroup:ident {
$(#[name = $known_font_name:literal, size = $known_font_size:literal]
$KnownFont:ident,)*
},)*
}
) => {
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
enum $Font {
$Other $other_body,
$($($KnownFont,)*)*
}
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone)]
enum KnownFontGroup {
$($KnownFontGroup,)*
}
impl KnownFontGroup {
const fn fonts(self) -> &'static [Font] {
match self {
$(Self::$KnownFontGroup => &[$(Font::$KnownFont,)*],)*
}
}
const INSN_CODE_FONT_GROUPS: &[Self] = &[Self::InsnCode, Self::InsnCodeSubscript];
}
impl $Font {
const fn size(&self) -> f32 {
match *self {
Self::$Other { size, .. } => size.get(),
$($(Self::$KnownFont => $known_font_size,)*)*
}
}
const fn font_name(&self) -> &str {
match self {
Self::$Other { font_name, .. } => font_name,
$($(Self::$KnownFont => $known_font_name,)*)*
}
}
const fn known_font_group(&self) -> Option<KnownFontGroup> {
match self {
Self::$Other { .. } => None,
$($(Self::$KnownFont => Some(KnownFontGroup::$KnownFontGroup),)*)*
}
}
const fn line_height(&self) -> f32 {
match self {
Self::$Other { .. } => self.line_height_helper(),
$($(Self::$KnownFont => const { Self::$KnownFont.line_height_helper() },)*)*
}
}
}
};
}
make_enum_font! {
enum Font {
#[other]
Other {
font_name: Box<str>,
size: NonNaNF32,
},
#[group]
InsnHeader {
#[name = "YDJYQV+DejaVuSansCondensed-BoldOblique", size = 9.963]
InsnHeader,
},
#[group]
RtlFnHeader {
#[name = "APUYSQ+zcoN-Regular", size = 9.963]
RtlFnHeader,
},
#[group]
PageHeader {
#[name = "MJBFWM+DejaVuSansCondensed", size = 9.963]
PageHeader,
},
#[group]
PageFooter {
#[name = "MJBFWM+DejaVuSansCondensed", size = 4.981]
PageFooter,
},
#[group]
InsnDesc {
#[name = "MJBFWM+DejaVuSansCondensed", size = 8.966]
InsnDesc0,
#[name = "FZTIYT+CMMI9", size = 8.966]
InsnDesc1,
#[name = "ONUAYC+CMSSI9", size = 8.966]
InsnDesc2,
#[name = "TNGBFZ+CMSY9", size = 8.966]
InsnDesc3,
#[name = "WHMZPU+CMEX9", size = 8.966]
InsnDesc4,
#[name = "ZJTMSG+CMSS9", size = 8.966]
InsnDesc5,
},
#[group]
InsnDescMisc {
#[name = "MJBFWM+DejaVuSansCondensed", size = 2.377]
InsnDescMisc0,
#[name = "MJBFWM+DejaVuSansCondensed", size = 2.561]
InsnDescMisc1,
#[name = "MJBFWM+DejaVuSansCondensed", size = 4.492]
InsnDescMisc2,
#[name = "MJBFWM+DejaVuSansCondensed", size = 4.641]
InsnDescMisc3,
#[name = "MJBFWM+DejaVuSansCondensed", size = 4.772]
InsnDescMisc4,
#[name = "MJBFWM+DejaVuSansCondensed", size = 4.864]
InsnDescMisc5,
#[name = "MJBFWM+DejaVuSansCondensed", size = 4.925]
InsnDescMisc6,
#[name = "MJBFWM+DejaVuSansCondensed", size = 5.097]
InsnDescMisc7,
#[name = "MJBFWM+DejaVuSansCondensed", size = 5.123]
InsnDescMisc8,
#[name = "MJBFWM+DejaVuSansCondensed", size = 5.131]
InsnDescMisc9,
#[name = "MJBFWM+DejaVuSansCondensed", size = 5.516]
InsnDescMisc10,
#[name = "MJBFWM+DejaVuSansCondensed", size = 5.604]
InsnDescMisc11,
#[name = "MJBFWM+DejaVuSansCondensed", size = 5.634]
InsnDescMisc12,
#[name = "MJBFWM+DejaVuSansCondensed", size = 5.906]
InsnDescMisc13,
#[name = "MJBFWM+DejaVuSansCondensed", size = 6.033]
InsnDescMisc14,
#[name = "MJBFWM+DejaVuSansCondensed", size = 6.068]
InsnDescMisc15,
#[name = "MJBFWM+DejaVuSansCondensed", size = 6.213]
InsnDescMisc16,
#[name = "MJBFWM+DejaVuSansCondensed", size = 6.252]
InsnDescMisc17,
#[name = "MJBFWM+DejaVuSansCondensed", size = 6.962]
InsnDescMisc18,
#[name = "MJBFWM+DejaVuSansCondensed", size = 7.977]
InsnDescMisc19,
},
#[group]
InsnDescCode {
#[name = "APUYSQ+zcoN-Regular", size = 6.974]
InsnDescCode,
},
#[group]
InsnDescCodeMisc {
#[name = "APUYSQ+zcoN-Regular", size = 3.587]
InsnDescCodeMisc0,
#[name = "APUYSQ+zcoN-Regular", size = 4.483]
InsnDescCodeMisc1,
},
#[group]
InsnDescItalic {
#[name = "CGMSHV+DejaVuSansCondensed-Oblique", size = 8.966]
InsnDescItalic,
},
#[group]
InsnDescBold {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 8.966]
InsnDescBold,
},
#[group]
InsnDescBoldItalic {
#[name = "YDJYQV+DejaVuSansCondensed-BoldOblique", size = 8.966]
InsnDescBoldItalic,
},
#[group]
InsnDescSmall {
#[name = "MJBFWM+DejaVuSansCondensed", size = 7.97]
InsnDescSmall,
},
#[group]
InsnDescSmallItalic {
#[name = "CGMSHV+DejaVuSansCondensed-Oblique", size = 7.97]
InsnDescSmallItalic,
},
#[group]
InsnDescSmallBold {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 7.97]
InsnDescSmallBold,
},
#[group]
InsnDescSmallBoldItalic {
#[name = "YDJYQV+DejaVuSansCondensed-BoldOblique", size = 7.97]
InsnDescSmallBoldItalic,
},
#[group]
InsnDescBoldMisc {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 2.21]
InsnDescBoldMisc0,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 2.399]
InsnDescBoldMisc1,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 2.763]
InsnDescBoldMisc2,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 2.946]
InsnDescBoldMisc3,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 2.949]
InsnDescBoldMisc4,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 2.999]
InsnDescBoldMisc5,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 3.065]
InsnDescBoldMisc6,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 3.086]
InsnDescBoldMisc7,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 3.183]
InsnDescBoldMisc8,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 3.686]
InsnDescBoldMisc9,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 3.744]
InsnDescBoldMisc10,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 3.825]
InsnDescBoldMisc11,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 3.842]
InsnDescBoldMisc12,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 3.857]
InsnDescBoldMisc13,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 3.979]
InsnDescBoldMisc14,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.032]
InsnDescBoldMisc15,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.112]
InsnDescBoldMisc16,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.161]
InsnDescBoldMisc17,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.206]
InsnDescBoldMisc18,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.353]
InsnDescBoldMisc19,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.378]
InsnDescBoldMisc20,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.434]
InsnDescBoldMisc21,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.595]
InsnDescBoldMisc22,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.619]
InsnDescBoldMisc23,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.647]
InsnDescBoldMisc24,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.68]
InsnDescBoldMisc25,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.693]
InsnDescBoldMisc26,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.736]
InsnDescBoldMisc27,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.781]
InsnDescBoldMisc28,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.802]
InsnDescBoldMisc29,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 4.995]
InsnDescBoldMisc30,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.201]
InsnDescBoldMisc31,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.258]
InsnDescBoldMisc32,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.363]
InsnDescBoldMisc33,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.442]
InsnDescBoldMisc34,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.473]
InsnDescBoldMisc35,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.485]
InsnDescBoldMisc36,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.512]
InsnDescBoldMisc37,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.543]
InsnDescBoldMisc38,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.613]
InsnDescBoldMisc39,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.744]
InsnDescBoldMisc40,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.774]
InsnDescBoldMisc41,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.809]
InsnDescBoldMisc42,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.849]
InsnDescBoldMisc43,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.911]
InsnDescBoldMisc44,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.92]
InsnDescBoldMisc45,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.962]
InsnDescBoldMisc46,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.981]
InsnDescBoldMisc47,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.146]
InsnDescBoldMisc48,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.213]
InsnDescBoldMisc49,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.221]
InsnDescBoldMisc50,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.243]
InsnDescBoldMisc51,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.55]
InsnDescBoldMisc52,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.62]
InsnDescBoldMisc53,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.699]
InsnDescBoldMisc54,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.725]
InsnDescBoldMisc55,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.751]
InsnDescBoldMisc56,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.856]
InsnDescBoldMisc57,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 8.029]
InsnDescBoldMisc58,
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 8.406]
InsnDescBoldMisc59,
},
#[group]
InsnDescSubscript {
#[name = "MJBFWM+DejaVuSansCondensed", size = 5.978]
InsnDescSubscript,
},
#[group]
InsnDescBoldSubscript {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 5.978]
InsnDescBoldSubscript,
},
#[group]
InsnDescItalicSubscript {
#[name = "CGMSHV+DejaVuSansCondensed-Oblique", size = 5.978]
InsnDescItalicSubscript,
},
#[group]
InsnDescBoldItalicSubscript {
#[name = "YDJYQV+DejaVuSansCondensed-BoldOblique", size = 5.978]
InsnDescBoldItalicSubscript,
},
#[group]
InsnExtMnemonic {
#[name = "APUYSQ+zcoN-Regular", size = 8.966]
InsnExtMnemonic,
},
#[group]
InsnCode {
#[name = "APUYSQ+zcoN-Regular", size = 7.97]
InsnCode0,
#[name = "RRFUNA+CMSY8", size = 7.97]
InsnCode1,
#[name = "HPXOZC+CMSS8", size = 7.97]
InsnCode2,
},
#[group]
InsnCodeSubscript {
#[name = "APUYSQ+zcoN-Regular", size = 5.978]
InsnCodeSubscript0,
#[name = "DBQTKF+CMSY6", size = 5.978]
InsnCodeSubscript1,
},
#[group]
TitlePageBig {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 24.787]
TitlePageBig,
},
#[group]
TitlePageVersion {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 9.963]
TitlePageVersion,
},
#[group]
TitlePageTm {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 6.974]
TitlePageTm,
},
#[group]
TitlePageRev {
#[name = "MJBFWM+DejaVuSansCondensed", size = 6.974]
TitlePageRev,
},
#[group]
TitlePageBook {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 20.663]
TitlePageBook,
},
#[group]
LegalPageItalic {
#[name = "CGMSHV+DejaVuSansCondensed-Oblique", size = 9.963]
LegalPageItalic,
},
#[group]
ChangeSummaryPageBold {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 11.955]
ChangeSummaryPageBold,
},
#[group]
ChapterTitle {
#[name = "NHUPPK+DejaVuSansCondensed-Bold", size = 17.215]
ChapterTitle,
},
#[group]
MathMisc {
#[name = "AAJMKT+CMMI6", size = 5.978]
MathMisc0,
#[name = "CUTMFD+CMSSI8", size = 5.978]
MathMisc1,
#[name = "CUTMFD+CMSSI8", size = 7.97]
MathMisc2,
#[name = "FZTIYT+CMMI9", size = 5.734]
MathMisc3,
#[name = "FZTIYT+CMMI9", size = 7.168]
MathMisc4,
#[name = "HONFQS+CMMI8", size = 7.97]
MathMisc5,
#[name = "HPXOZC+CMSS8", size = 5.978]
MathMisc6,
#[name = "LLVRDD+CMSY10", size = 11.955]
MathMisc7,
#[name = "ZJTMSG+CMSS9", size = 7.168]
MathMisc8,
},
}
}
impl Font {
const fn space_width(&self) -> f32 {
self.size() * const { 3.985 / Font::InsnCode0.size() }
}
const fn line_height_helper(&self) -> f32 {
const fn str_eq(a: &str, b: &str) -> bool {
let a = a.as_bytes();
let b = b.as_bytes();
if a.len() != b.len() {
return false;
}
let mut i = 0;
while i < a.len() {
if a[i] != b[i] {
return false;
}
i += 1;
}
true
}
let font_name = self.font_name();
let mut i = 0;
while i < KnownFontGroup::INSN_CODE_FONT_GROUPS.len() {
let fonts = KnownFontGroup::INSN_CODE_FONT_GROUPS[i].fonts();
let mut j = 0;
while j < fonts.len() {
if str_eq(font_name, fonts[j].font_name()) {
return 9.464 * self.size() / Font::InsnCode0.size();
}
j += 1;
}
i += 1;
}
let group = self.known_font_group();
if matches!(group, Some(KnownFontGroup::InsnDesc))
|| str_eq(font_name, Font::InsnDesc0.font_name())
|| str_eq(font_name, Font::InsnDescBold.font_name())
|| str_eq(font_name, Font::InsnDescItalic.font_name())
|| str_eq(font_name, Font::InsnDescBoldItalic.font_name())
|| matches!(group, Some(KnownFontGroup::MathMisc))
{
return 10.959 * self.size() / Font::InsnDesc0.size();
}
panic!("no line height")
}
}
fn main() {}