// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
let bsln_format0 = 0
let bsln_format1 = 1
let bsln_format2 = 2
let bsln_format3 = 3
///|
/// Parsed bsln baseline data.
pub enum BslnData {
Format0(Array[Int])
Format1(Array[Int], LookupTable)
Format2(Int, Array[Int])
Format3(Int, Array[Int], LookupTable)
} derive(Show, ToJson)
///|
/// Parsed bsln table.
pub struct BslnTable {
version : Int
format : Int
default_baseline : Int
data : BslnData
} derive(Show, ToJson)
///|
pub fn BslnTable::has_data(self : BslnTable) -> Bool {
self.version != 0
}
fn parse_deltas(data : BytesView, offset : Int) -> Result[Array[Int], AatError] {
if offset < 0 || offset + 64 > data.length() {
return Err(UnexpectedEof)
}
let deltas : Array[Int] = []
for i in 0..<32 {
let value = read_i16(data, offset + i * 2)
match value {
Err(err) => return Err(err)
Ok(value) => deltas.push(value)
}
}
Ok(deltas)
}
fn parse_ctl_points(
data : BytesView,
offset : Int,
) -> Result[Array[Int], AatError] {
if offset < 0 || offset + 64 > data.length() {
return Err(UnexpectedEof)
}
let points : Array[Int] = []
for i in 0..<32 {
let value = read_u16_int(data, offset + i * 2)
match value {
Err(err) => return Err(err)
Ok(value) => {
if value == 0xffff {
points.push(-1)
} else {
points.push(value)
}
}
}
}
Ok(points)
}
///|
/// Parse a bsln table.
pub fn BslnTable::parse(
data : BytesView,
num_glyphs : Int,
) -> Result[BslnTable, AatError] {
if num_glyphs < 0 {
return Err(InvalidFormat)
}
let version = read_i32(data, 0)
let format = read_u16_int(data, 4)
let default_baseline = read_u16_int(data, 6)
match (version, format, default_baseline) {
(Err(err), _, _) => Err(err)
(_, Err(err), _) => Err(err)
(_, _, Err(err)) => Err(err)
(Ok(version), Ok(format), Ok(default_baseline)) => {
if default_baseline < 0 || default_baseline >= 32 {
return Err(InvalidFormat)
}
let base = 8
let data = if format == bsln_format0 {
let deltas = match parse_deltas(data, base) {
Err(err) => return Err(err)
Ok(value) => value
}
BslnData::Format0(deltas)
} else if format == bsln_format1 {
let deltas = match parse_deltas(data, base) {
Err(err) => return Err(err)
Ok(value) => value
}
let lookup_offset = base + 64
let lookup = match parse_lookup(data, lookup_offset, num_glyphs) {
Err(err) => return Err(err)
Ok(value) => value
}
BslnData::Format1(deltas, lookup)
} else if format == bsln_format2 {
if base < 0 || base + 66 > data.length() {
return Err(UnexpectedEof)
}
let std_glyph = match read_u16_int(data, base) {
Err(err) => return Err(err)
Ok(value) => value
}
let points = match parse_ctl_points(data, base + 2) {
Err(err) => return Err(err)
Ok(value) => value
}
BslnData::Format2(std_glyph, points)
} else if format == bsln_format3 {
if base < 0 || base + 66 > data.length() {
return Err(UnexpectedEof)
}
let std_glyph = match read_u16_int(data, base) {
Err(err) => return Err(err)
Ok(value) => value
}
let points = match parse_ctl_points(data, base + 2) {
Err(err) => return Err(err)
Ok(value) => value
}
let lookup_offset = base + 66
let lookup = match parse_lookup(data, lookup_offset, num_glyphs) {
Err(err) => return Err(err)
Ok(value) => value
}
BslnData::Format3(std_glyph, points, lookup)
} else {
return Err(InvalidFormat)
}
Ok(BslnTable::{ version, format, default_baseline, data })
}
}
}