namespace XFESystem.Kernel; /// Validated SFNT metrics convert a CSS em size to Cosmos' hhea pixel height. public sealed class NativeWebFontMetrics { public double LineToEm { get; } public double AscentToEm { get; } public double NaturalLineToEm { get; } public NativeWebFontMetrics(byte[] data) { ArgumentNullException.ThrowIfNull(data); int U16(int p) { if(p<0||p>data.Length-2)throw new InvalidOperationException("Font table is truncated.");return data[p]<<8|data[p+1]; } int S16(int p)=>unchecked((short)U16(p)); int U32(int p) { if(p<0||p>data.Length-4)throw new InvalidOperationException("Font table is truncated.");uint value=(uint)(data[p]<<24|data[p+1]<<16|data[p+2]<<8|data[p+3]);if(value>int.MaxValue)throw new InvalidOperationException("Font table offset is excessive.");return (int)value; } int count=U16(4),head=-1,hhea=-1; if(count>256||12L+count*16>data.Length)throw new InvalidOperationException("Font directory is invalid."); for(int i=0;idata.Length-length)throw new InvalidOperationException("Font table is outside the font."); if(data[p]=='h'&&data[p+1]=='e'&&data[p+2]=='a'&&data[p+3]=='d'&&length>=20)head=offset; if(data[p]=='h'&&data[p+1]=='h'&&data[p+2]=='e'&&data[p+3]=='a'&&length>=10)hhea=offset; } if(head<0||hhea<0)throw new InvalidOperationException("Font head/hhea table is missing."); int em=U16(head+18),ascent=S16(hhea+4),descent=S16(hhea+6),gap=S16(hhea+8); if(em is <16 or >16384||ascent<=descent)throw new InvalidOperationException("Font line metrics are invalid."); LineToEm=(ascent-descent)/(double)em; AscentToEm=ascent/(double)em; NaturalLineToEm=(ascent-descent+gap)/(double)em; } }