// Copyright 2025 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.
///|
/// Function/Instruction definitions for the TrueType interpreter.
///
/// Ported from `fontations/skrifa/src/outline/glyf/hint/definition.rs`
/// (Apache-2.0 OR MIT).
priv struct TtDefinition {
mut code : BytesView?
mut start : Int
mut end_ : Int
mut key : Int
mut active : Bool
}
///|
fn TtDefinition::default() -> TtDefinition {
{ code: None, start: -1, end_: -1, key: 0, active: false }
}
///|
fn TtDefinition::is_defined(self : TtDefinition) -> Bool {
self.active &&
self.code is Some(_) &&
self.start >= 0 &&
self.end_ >= self.start
}
///|
fn TtDefinition::set(
self : TtDefinition,
code : BytesView,
start : Int,
end_ : Int,
key : Int,
) -> Unit {
self.code = Some(code)
self.start = start
self.end_ = end_
self.key = key
self.active = true
}
///|
fn TtDefinition::slice(self : TtDefinition) -> BytesView? {
match self.code {
None => None
Some(code) =>
if self.start < 0 || self.end_ < self.start || self.end_ > code.length() {
None
} else {
Some(code[self.start:self.end_])
}
}
}
///|
priv struct TtDefinitionSet {
defs : Array[TtDefinition]
}
///|
fn TtDefinitionSet::TtDefinitionSet(cap : Int) -> TtDefinitionSet {
// `Array::make(cap, v)` duplicates `v`. For mutable structs, we need a fresh
// default instance per slot (matches Rust `vec![Default::default(); cap]`).
let defs : Array[TtDefinition] = Array::new()
for _ in 0.. Unit {
let n = self.defs.length()
for i in 0.. TtDefinition? {
let n = self.defs.length()
if index >= 0 && index < n {
let d = self.defs.at(index)
if d.is_defined() && d.key == index {
return Some(d)
}
}
for j in 0.. Result[Unit, HintError] {
if start < 0 || end_ < start || end_ > code.length() {
return Err(InvalidDefinition(index))
}
let n = self.defs.length()
if n == 0 {
return Err(TooManyDefinitions)
}
let mut chosen : Int? = None
if index >= 0 && index < n {
let d = self.defs.at(index)
if !d.active || d.key == index {
chosen = Some(index)
}
}
if chosen is None {
let mut last_inactive : Int? = None
for j in 0.. return Err(TooManyDefinitions)
Some(ix) => {
let d = self.defs.at(ix)
d.set(code, start, end_, index)
self.defs.set(ix, d)
}
}
Ok(())
}