// 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.

///|
/// TrueType outlines from the `glyf` table (MVP).
///
/// This only supports simple glyphs (contour streams) for now.
const TAG_HEAD : UInt = 0x68656164 // "head"

///|
const TAG_LOCA : UInt = 0x6C6F6361 // "loca"

///|
const TAG_MAXP : UInt = 0x6D617870 // "maxp"

///|
const COMPOSITE_ARG_1_AND_2_ARE_WORDS : Int = 0x0001

///|
const COMPOSITE_ARGS_ARE_XY_VALUES : Int = 0x0002

///|
const COMPOSITE_ROUND_XY_TO_GRID : Int = 0x0004

///|
const COMPOSITE_WE_HAVE_A_SCALE : Int = 0x0008

///|
const COMPOSITE_MORE_COMPONENTS : Int = 0x0020

///|
const COMPOSITE_WE_HAVE_AN_X_AND_Y_SCALE : Int = 0x0040

///|
const COMPOSITE_WE_HAVE_A_TWO_BY_TWO : Int = 0x0080

///|
const COMPOSITE_WE_HAVE_INSTRUCTIONS : Int = 0x0100

///|
const COMPOSITE_OVERLAP_COMPOUND : Int = 0x0400

///|
const COMPOSITE_SCALED_COMPONENT_OFFSET : Int = 0x0800

///|
const COMPOSITE_UNSCALED_COMPONENT_OFFSET : Int = 0x1000

///|
const SIMPLE_OVERLAP_FLAG : Int = 0x40

///|
fn glyf_read_u16_be(view : BytesView, offset : Int) -> Int? {
  if offset < 0 || offset + 2 > view.length() {
    None
  } else {
    let b0 = view.at(offset).to_int()
    let b1 = view.at(offset + 1).to_int()
    Some((b0 << 8) | b1)
  }
}

///|
fn glyf_read_i16_be(view : BytesView, offset : Int) -> Int? {
  match glyf_read_u16_be(view, offset) {
    None => None
    Some(u) => if u >= 0x8000 { Some(u - 0x10000) } else { Some(u) }
  }
}

///|
fn glyf_read_u32_be(view : BytesView, offset : Int) -> UInt? {
  if offset < 0 || offset + 4 > view.length() {
    None
  } else {
    let b0 = view.at(offset).to_uint()
    let b1 = view.at(offset + 1).to_uint()
    let b2 = view.at(offset + 2).to_uint()
    let b3 = view.at(offset + 3).to_uint()
    Some((b0 << 24) | (b1 << 16) | (b2 << 8) | b3)
  }
}

///|
fn glyf_read_f2dot14(view : BytesView, offset : Int) -> Double? {
  match glyf_read_i16_be(view, offset) {
    None => None
    Some(v) => Some(v.to_double() / 16384.0)
  }
}

///|
fn glyf_units_per_em(font : @moon_skrifa.FontRef) -> UInt16 {
  match font.table(TAG_HEAD) {
    None => 0
    Some(head) =>
      match glyf_read_u16_be(head, 18) {
        None => 0
        Some(v) => v.to_uint16()
      }
  }
}

///|
fn glyf_compute_scale_bits(
  size : @moon_skrifa.Size,
  upem : UInt16,
) -> (Bool, Int) {
  match size.ppem() {
    None => (false, 0x10000)
    Some(ppem) => {
      let upem_i = upem.to_int()
      if upem_i <= 0 {
        (false, 0x10000)
      } else {
        // Matches the reference compute_scale() shape without relying on Int64
        // (works around wasm-gc toolchain crashes in some environments).
        let a = (ppem * 64.0).to_int()
        let q = (a.to_double() * 65536.0 / upem_i.to_double()).round().to_int()
        (true, q)
      }
    }
  }
}

///|
fn glyf_mul_16_16(v : Int, scale_bits : Int) -> Int {
  glyf_round_half_away_from_zero(
    v.to_double() * scale_bits.to_double() / 65536.0,
  )
}

///|
fn glyf_mul_16_16_f(v : Double, scale_bits : Int) -> Int {
  glyf_round_half_away_from_zero(v * scale_bits.to_double() / 65536.0)
}

///|
/// Matches font-types fixed-point mul rounding on 16.16 products:
/// .5 ties are rounded away from zero.
fn glyf_round_half_away_from_zero(v : Double) -> Int {
  if v >= 0.0 {
    (v + 0.5).to_int()
  } else {
    -(-v + 0.5).to_int()
  }
}

///|
fn glyf_f26dot6_bits_to_double(bits : Int) -> Double {
  bits.to_double() / 64.0
}

///|
fn glyf_shift_path_x(path : Array[PathElement], x_shift : Double) -> Unit {
  if x_shift == 0.0 {
    return
  }
  for i in 0.. path.set(i, MoveTo(x - x_shift, y))
      LineTo(x, y) => path.set(i, LineTo(x - x_shift, y))
      QuadTo(cx, cy, x, y) =>
        path.set(i, QuadTo(cx - x_shift, cy, x - x_shift, y))
      CurveTo(cx0, cy0, cx1, cy1, x, y) =>
        path.set(
          i,
          CurveTo(cx0 - x_shift, cy0, cx1 - x_shift, cy1, x - x_shift, y),
        )
      Close => ()
    }
  }
}

///|
fn glyf_midpoint_i32(a : Int, b : Int) -> Int {
  // Matches read-fonts midpoint_i32: a.wrapping_add(b) / 2.
  (a + b) / 2
}

///|
priv struct GlyfTransform {
  a : Double
  b : Double
  c : Double
  d : Double
  dx : Double
  dy : Double
}

///|
priv struct GlyfCompositeComp {
  flags : Int
  gid : Int
  args_xy : Bool
  base_point_ix : Int
  component_point_ix : Int
  dx : Double
  dy : Double
  a : Double
  b : Double
  c : Double
  d : Double
  have_xform : Bool
}

///|
/// FreeType's "guess" for hypot(a, b) used when scaling composite anchor
/// offsets (see fontations-reference).
fn glyf_hypot_guess(a : Double, b : Double) -> Double {
  let aa = a.abs()
  let bb = b.abs()
  if aa > bb {
    aa + 3.0 * bb / 8.0
  } else {
    bb + 3.0 * aa / 8.0
  }
}

///|
fn glyf_transform_point(
  t : GlyfTransform,
  x : Double,
  y : Double,
) -> (Double, Double) {
  (t.a * x + t.b * y + t.dx, t.c * x + t.d * y + t.dy)
}

///|
fn glyf_apply_transform(
  path : Array[PathElement],
  t : GlyfTransform,
) -> Array[PathElement] {
  let out : Array[PathElement] = Array::new()
  for e in path {
    match e {
      MoveTo(x, y) => {
        let (nx, ny) = glyf_transform_point(t, x, y)
        out.push(MoveTo(nx, ny))
      }
      LineTo(x, y) => {
        let (nx, ny) = glyf_transform_point(t, x, y)
        out.push(LineTo(nx, ny))
      }
      QuadTo(cx, cy, x, y) => {
        let (ncx, ncy) = glyf_transform_point(t, cx, cy)
        let (nx, ny) = glyf_transform_point(t, x, y)
        out.push(QuadTo(ncx, ncy, nx, ny))
      }
      CurveTo(cx0, cy0, cx1, cy1, x, y) => {
        let (ncx0, ncy0) = glyf_transform_point(t, cx0, cy0)
        let (ncx1, ncy1) = glyf_transform_point(t, cx1, cy1)
        let (nx, ny) = glyf_transform_point(t, x, y)
        out.push(CurveTo(ncx0, ncy0, ncx1, ncy1, nx, ny))
      }
      Close => out.push(Close)
    }
  }
  out
}

///|
fn glyf_path_points(path : Array[PathElement]) -> Array[(Double, Double)] {
  let out : Array[(Double, Double)] = Array::new()
  for e in path {
    match e {
      MoveTo(x, y) | LineTo(x, y) => out.push((x, y))
      QuadTo(cx, cy, x, y) => {
        out.push((cx, cy))
        out.push((x, y))
      }
      CurveTo(cx0, cy0, cx1, cy1, x, y) => {
        out.push((cx0, cy0))
        out.push((cx1, cy1))
        out.push((x, y))
      }
      Close => ()
    }
  }
  out
}

///|
fn glyf_composite_point_offset(
  base_path : Array[PathElement],
  component_path : Array[PathElement],
  base_point_ix : Int,
  component_point_ix : Int,
) -> (Double, Double) {
  if base_point_ix < 0 || component_point_ix < 0 {
    return (0.0, 0.0)
  }
  let base_points = glyf_path_points(base_path)
  let component_points = glyf_path_points(component_path)
  if base_point_ix >= base_points.length() ||
    component_point_ix >= component_points.length() {
    return (0.0, 0.0)
  }
  let (bx, by) = base_points.at(base_point_ix)
  let (cx, cy) = component_points.at(component_point_ix)
  (bx - cx, by - cy)
}

///|
priv struct GlyfPoint {
  x : Int
  y : Int
  on : Bool
}

///|
priv struct GlyfPointF {
  x : Double
  y : Double
  on : Bool
}

///|
priv struct GlyfPointFT {
  x : Int
  y : Int
  on : Bool
}

///|
fn glyf_emit_contour_harfbuzz(
  out : Array[PathElement],
  points : ArrayView[GlyfPointF],
  start : Int,
  end : Int,
  path_style : PathStyle,
) -> Unit {
  let n = end - start + 1
  if n <= 0 {
    return
  }
  let first = points.at(start)
  let last = points.at(end)
  let (sx, sy, start_idx) = if first.on {
    (first.x, first.y, start)
  } else {
    match path_style {
      FreeType =>
        if last.on {
          (last.x, last.y, end)
        } else {
          let mx = (last.x + first.x) / 2.0
          let my = (last.y + first.y) / 2.0
          (mx, my, -1)
        }
      HarfBuzz =>
        if n >= 2 {
          let second = points.at(start + 1)
          if second.on {
            (second.x, second.y, start + 1)
          } else {
            let mx = (first.x + second.x) / 2.0
            let my = (first.y + second.y) / 2.0
            (mx, my, -1)
          }
        } else {
          (first.x, first.y, start)
        }
    }
  }
  out.push(MoveTo(sx, sy))
  let mut control : (Double, Double)? = None
  if start_idx == -1 {
    for i in start..<(end + 1) {
      let p = points.at(i)
      if p.on {
        match control {
          None => out.push(LineTo(p.x, p.y))
          Some((cx, cy)) => {
            out.push(QuadTo(cx, cy, p.x, p.y))
            control = None
          }
        }
      } else {
        match control {
          None => control = Some((p.x, p.y))
          Some((cx, cy)) => {
            let mx = (cx + p.x) / 2.0
            let my = (cy + p.y) / 2.0
            out.push(QuadTo(cx, cy, mx, my))
            control = Some((p.x, p.y))
          }
        }
      }
    }
  } else {
    let base = start_idx - start
    for step in 1.. out.push(LineTo(p.x, p.y))
          Some((cx, cy)) => {
            out.push(QuadTo(cx, cy, p.x, p.y))
            control = None
          }
        }
      } else {
        match control {
          None => control = Some((p.x, p.y))
          Some((cx, cy)) => {
            let mx = (cx + p.x) / 2.0
            let my = (cy + p.y) / 2.0
            out.push(QuadTo(cx, cy, mx, my))
            control = Some((p.x, p.y))
          }
        }
      }
    }
  }
  match control {
    Some((cx, cy)) => out.push(QuadTo(cx, cy, sx, sy))
    None => ()
  }
  out.push(Close)
}

///|
fn glyf_emit_contour_freetype(
  out : Array[PathElement],
  points : ArrayView[GlyfPointFT],
  start : Int,
  end : Int,
) -> Unit {
  let n = end - start + 1
  if n <= 0 {
    return
  }
  let first = points.at(start)
  let last = points.at(end)
  let (sx, sy, start_idx) = if first.on {
    (first.x, first.y, start)
  } else if last.on {
    (last.x, last.y, end)
  } else {
    (glyf_midpoint_i32(last.x, first.x), glyf_midpoint_i32(last.y, first.y), -1)
  }
  out.push(
    MoveTo(glyf_f26dot6_bits_to_double(sx), glyf_f26dot6_bits_to_double(sy)),
  )
  let mut control : (Int, Int)? = None
  if start_idx == -1 {
    for i in start..<(end + 1) {
      let p = points.at(i)
      if p.on {
        match control {
          None =>
            out.push(
              LineTo(
                glyf_f26dot6_bits_to_double(p.x),
                glyf_f26dot6_bits_to_double(p.y),
              ),
            )
          Some((cx, cy)) => {
            out.push(
              QuadTo(
                glyf_f26dot6_bits_to_double(cx),
                glyf_f26dot6_bits_to_double(cy),
                glyf_f26dot6_bits_to_double(p.x),
                glyf_f26dot6_bits_to_double(p.y),
              ),
            )
            control = None
          }
        }
      } else {
        match control {
          None => control = Some((p.x, p.y))
          Some((cx, cy)) => {
            let mx = glyf_midpoint_i32(cx, p.x)
            let my = glyf_midpoint_i32(cy, p.y)
            out.push(
              QuadTo(
                glyf_f26dot6_bits_to_double(cx),
                glyf_f26dot6_bits_to_double(cy),
                glyf_f26dot6_bits_to_double(mx),
                glyf_f26dot6_bits_to_double(my),
              ),
            )
            control = Some((p.x, p.y))
          }
        }
      }
    }
  } else {
    let base = start_idx - start
    for step in 1..
            out.push(
              LineTo(
                glyf_f26dot6_bits_to_double(p.x),
                glyf_f26dot6_bits_to_double(p.y),
              ),
            )
          Some((cx, cy)) => {
            out.push(
              QuadTo(
                glyf_f26dot6_bits_to_double(cx),
                glyf_f26dot6_bits_to_double(cy),
                glyf_f26dot6_bits_to_double(p.x),
                glyf_f26dot6_bits_to_double(p.y),
              ),
            )
            control = None
          }
        }
      } else {
        match control {
          None => control = Some((p.x, p.y))
          Some((cx, cy)) => {
            let mx = glyf_midpoint_i32(cx, p.x)
            let my = glyf_midpoint_i32(cy, p.y)
            out.push(
              QuadTo(
                glyf_f26dot6_bits_to_double(cx),
                glyf_f26dot6_bits_to_double(cy),
                glyf_f26dot6_bits_to_double(mx),
                glyf_f26dot6_bits_to_double(my),
              ),
            )
            control = Some((p.x, p.y))
          }
        }
      }
    }
  }
  match control {
    Some((cx, cy)) =>
      out.push(
        QuadTo(
          glyf_f26dot6_bits_to_double(cx),
          glyf_f26dot6_bits_to_double(cy),
          glyf_f26dot6_bits_to_double(sx),
          glyf_f26dot6_bits_to_double(sy),
        ),
      )
    None => ()
  }
  out.push(Close)
}

///|
fn glyf_simple_path(
  ctx : GlyfCtx,
  glyph : BytesView,
  gid : @moon_skrifa.GlyphId,
  path_style : PathStyle,
) -> Array[PathElement]? {
  let number_of_contours = match glyf_read_i16_be(glyph, 0) {
    None => return None
    Some(v) => v
  }
  if number_of_contours == 0 {
    return Some(Array::new())
  }
  if number_of_contours < 0 {
    // Handled by composite parsing.
    return None
  }
  // Skip bbox (xMin..yMax).
  let mut off = 10
  let end_pts : Array[Int] = Array::new()
  for _ in 0.. return None
      Some(u) => u
    }
    end_pts.push(v)
    off = off + 2
  }
  let instruction_len = match glyf_read_u16_be(glyph, off) {
    None => return None
    Some(v) => v
  }
  off = off + 2
  if instruction_len < 0 || off + instruction_len > glyph.length() {
    return None
  }
  off = off + instruction_len
  let last_end = end_pts.at(end_pts.length() - 1)
  let num_points = last_end + 1
  if num_points <= 0 {
    return Some(Array::new())
  }

  // Flags stream.
  let flags : Array[Int] = Array::new()
  while flags.length() < num_points {
    if off >= glyph.length() {
      return None
    }
    let flag = glyph.at(off).to_int()
    off = off + 1
    flags.push(flag)
    if (flag & 0x08) != 0 {
      if off >= glyph.length() {
        return None
      }
      let repeat = glyph.at(off).to_int()
      off = off + 1
      for _ in 0..= glyph.length() {
        return None
      }
      let b = glyph.at(off).to_int()
      off = off + 1
      dxs.push(if same { b } else { -b })
    } else if same {
      dxs.push(0)
    } else {
      let d = match glyf_read_i16_be(glyph, off) {
        None => return None
        Some(v) => v
      }
      off = off + 2
      dxs.push(d)
    }
  }
  // y deltas
  let dys : Array[Int] = Array::new()
  for i in 0..= glyph.length() {
        return None
      }
      let b = glyph.at(off).to_int()
      off = off + 1
      dys.push(if same { b } else { -b })
    } else if same {
      dys.push(0)
    } else {
      let d = match glyf_read_i16_be(glyph, off) {
        None => return None
        Some(v) => v
      }
      off = off + 2
      dys.push(d)
    }
  }
  for i in 0.. {
      // In FreeType mode, points are stored in 26.6 fixed (as Int bits).
      let scaled : Array[GlyfPointFT] = Array::new()
      for i in 0..= scaled.length() {
          return None
        }
        glyf_emit_contour_freetype(
          out,
          scaled.op_as_view(),
          contour_start,
          contour_end,
        )
        contour_start = contour_end + 1
      }
      Some(out)
    }
    HarfBuzz => {
      // In HarfBuzz mode, points are stored as f32 in 16.16 fixed units (as Double here).
      let scale = if ctx.is_scaled { ctx.hb_scale } else { 1.0 }
      let scaled : Array[GlyfPointF] = Array::new()
      for i in 0..= scaled.length() {
          return None
        }
        glyf_emit_contour_harfbuzz(
          out,
          scaled.op_as_view(),
          contour_start,
          contour_end,
          path_style,
        )
        contour_start = contour_end + 1
      }
      Some(out)
    }
  }
}

///|
priv struct GlyfCtx {
  font : @moon_skrifa.FontRef
  glyf : BytesView
  loca : BytesView
  num_glyphs : Int
  index_to_loc_format : Int
  coords : ArrayView[@moon_skrifa.NormalizedCoord]
  is_scaled : Bool
  is_hinted : Bool
  scale_bits : Int
  hb_scale : Double
}

///|
fn glyf_glyph_slice(ctx : GlyfCtx, idx : Int) -> BytesView? {
  if idx < 0 || idx >= ctx.num_glyphs {
    return None
  }
  let (start, end) = if ctx.index_to_loc_format == 0 {
    let need = (ctx.num_glyphs + 1) * 2
    if ctx.loca.length() < need {
      return None
    }
    let o0 = match glyf_read_u16_be(ctx.loca, idx * 2) {
      None => return None
      Some(v) => v
    }
    let o1 = match glyf_read_u16_be(ctx.loca, (idx + 1) * 2) {
      None => return None
      Some(v) => v
    }
    (o0 * 2, o1 * 2)
  } else if ctx.index_to_loc_format == 1 {
    let need = (ctx.num_glyphs + 1) * 4
    if ctx.loca.length() < need {
      return None
    }
    let o0 = match glyf_read_u32_be(ctx.loca, idx * 4) {
      None => return None
      Some(v) => v.to_uint64().to_int()
    }
    let o1 = match glyf_read_u32_be(ctx.loca, (idx + 1) * 4) {
      None => return None
      Some(v) => v.to_uint64().to_int()
    }
    (o0, o1)
  } else {
    return None
  }
  if start < 0 || end < start || end > ctx.glyf.length() {
    return None
  }
  Some(ctx.glyf[start:end])
}

///|
fn glyf_composite_path(
  ctx : GlyfCtx,
  glyph : BytesView,
  gid : @moon_skrifa.GlyphId,
  visited : Array[Bool],
  path_style : PathStyle,
) -> Array[PathElement]? {
  if glyph.length() < 10 {
    return None
  }
  // Skip bbox (xMin..yMax).
  let mut off = 10
  let comps : Array[GlyfCompositeComp] = Array::new()
  let mut flags = 0
  while true {
    flags = match glyf_read_u16_be(glyph, off) {
      None => return None
      Some(v) => v
    }
    let comp_gid = match glyf_read_u16_be(glyph, off + 2) {
      None => return None
      Some(v) => v
    }
    off = off + 4
    let arg_words = (flags & COMPOSITE_ARG_1_AND_2_ARE_WORDS) != 0
    let args_xy = (flags & COMPOSITE_ARGS_ARE_XY_VALUES) != 0
    let (dx, dy, base_point_ix, component_point_ix) = if arg_words {
      if args_xy {
        let a1 = match glyf_read_i16_be(glyph, off) {
          None => return None
          Some(v) => v
        }
        let a2 = match glyf_read_i16_be(glyph, off + 2) {
          None => return None
          Some(v) => v
        }
        off = off + 4
        (a1.to_double(), a2.to_double(), -1, -1)
      } else {
        let p1 = match glyf_read_u16_be(glyph, off) {
          None => return None
          Some(v) => v
        }
        let p2 = match glyf_read_u16_be(glyph, off + 2) {
          None => return None
          Some(v) => v
        }
        off = off + 4
        (0.0, 0.0, p1, p2)
      }
    } else {
      if off + 2 > glyph.length() {
        return None
      }
      let b1 = glyph.at(off).to_int()
      let b2 = glyph.at(off + 1).to_int()
      off = off + 2
      if args_xy {
        let a1 = if b1 >= 128 { b1 - 256 } else { b1 }
        let a2 = if b2 >= 128 { b2 - 256 } else { b2 }
        (a1.to_double(), a2.to_double(), -1, -1)
      } else {
        (0.0, 0.0, b1, b2)
      }
    }
    let mut a = 1.0
    let mut b = 0.0
    let mut c = 0.0
    let mut d = 1.0
    let mut have_xform = false
    if (flags & COMPOSITE_WE_HAVE_A_SCALE) != 0 {
      let s = match glyf_read_f2dot14(glyph, off) {
        None => return None
        Some(v) => v
      }
      off = off + 2
      a = s
      d = s
      have_xform = true
    } else if (flags & COMPOSITE_WE_HAVE_AN_X_AND_Y_SCALE) != 0 {
      let sx = match glyf_read_f2dot14(glyph, off) {
        None => return None
        Some(v) => v
      }
      let sy = match glyf_read_f2dot14(glyph, off + 2) {
        None => return None
        Some(v) => v
      }
      off = off + 4
      a = sx
      d = sy
      have_xform = true
    } else if (flags & COMPOSITE_WE_HAVE_A_TWO_BY_TWO) != 0 {
      let ca = match glyf_read_f2dot14(glyph, off) {
        None => return None
        Some(v) => v
      }
      let cb = match glyf_read_f2dot14(glyph, off + 2) {
        None => return None
        Some(v) => v
      }
      let cc = match glyf_read_f2dot14(glyph, off + 4) {
        None => return None
        Some(v) => v
      }
      let cd = match glyf_read_f2dot14(glyph, off + 6) {
        None => return None
        Some(v) => v
      }
      off = off + 8
      a = ca
      b = cb
      c = cc
      d = cd
      have_xform = true
    }
    comps.push({
      flags,
      gid: comp_gid,
      args_xy,
      base_point_ix,
      component_point_ix,
      dx,
      dy,
      a,
      b,
      c,
      d,
      have_xform,
    })
    if (flags & COMPOSITE_MORE_COMPONENTS) == 0 {
      break
    }
  }
  if (flags & COMPOSITE_WE_HAVE_INSTRUCTIONS) != 0 {
    if off + 2 > glyph.length() {
      return None
    }
    let ins_len = match glyf_read_u16_be(glyph, off) {
      None => return None
      Some(v) => v
    }
    off = off + 2
    if ins_len < 0 || off + ins_len > glyph.length() {
      return None
    }
  }
  let mut delta_x : Array[Double]? = None
  let mut delta_y : Array[Double]? = None
  match glyf_gvar_composite_deltas(ctx.font, gid, ctx.coords, comps.length()) {
    None => ()
    Some((xs, ys)) => {
      delta_x = Some(xs)
      delta_y = Some(ys)
    }
  }
  let out : Array[PathElement] = Array::new()
  for i in 0.. return None
      Some(p) => p
    }
    let transformed = if comp.args_xy {
      let mut dx = comp.dx
      let mut dy = comp.dy
      if comp.have_xform &&
        (
          comp.flags &
          (
            COMPOSITE_SCALED_COMPONENT_OFFSET |
            COMPOSITE_UNSCALED_COMPONENT_OFFSET
          )
        ) ==
        COMPOSITE_SCALED_COMPONENT_OFFSET {
        // Matches FreeType's guess-based scaling.
        dx = dx * glyf_hypot_guess(comp.a, comp.b)
        dy = dy * glyf_hypot_guess(comp.d, comp.c)
      }
      match (delta_x, delta_y) {
        (Some(dx_arr), Some(dy_arr)) =>
          if i < dx_arr.length() && i < dy_arr.length() {
            match path_style {
              FreeType => {
                // FreeType rounds off the fractional part of component deltas.
                dx = dx + dx_arr.at(i).to_int().to_double()
                dy = dy + dy_arr.at(i).to_int().to_double()
              }
              HarfBuzz => {
                dx = dx + dx_arr.at(i)
                dy = dy + dy_arr.at(i)
              }
            }
          }
        _ => ()
      }
      let (sdx, sdy) = match path_style {
        FreeType => {
          let dx_i = dx.to_int()
          let dy_i = dy.to_int()
          let dx_bits = if ctx.is_scaled {
            glyf_mul_16_16(dx_i, ctx.scale_bits)
          } else {
            dx_i * 64
          }
          let mut dy_bits = if ctx.is_scaled {
            glyf_mul_16_16(dy_i, ctx.scale_bits)
          } else {
            dy_i * 64
          }
          if ctx.is_scaled &&
            ctx.is_hinted &&
            (comp.flags & COMPOSITE_ROUND_XY_TO_GRID) != 0 {
            // Match fontations-reference (FreeType behavior): only round the y
            // component, and only when hinting is enabled.
            dy_bits = (dy_bits + 32) & -64
          }
          (
            glyf_f26dot6_bits_to_double(dx_bits),
            glyf_f26dot6_bits_to_double(dy_bits),
          )
        }
        HarfBuzz =>
          // Matches fontations-reference HarfBuzzScaler: component offsets are
          // applied without scaling, even when points are scaled to 16.16.
          (dx, dy)
      }
      glyf_apply_transform(comp_path, {
        a: comp.a,
        b: comp.b,
        c: comp.c,
        d: comp.d,
        dx: sdx,
        dy: sdy,
      })
    } else {
      // Point matching anchors: align component point to a point in the
      // already-built composite path.
      let without_offset = glyf_apply_transform(comp_path, {
        a: comp.a,
        b: comp.b,
        c: comp.c,
        d: comp.d,
        dx: 0.0,
        dy: 0.0,
      })
      let (anchor_dx, anchor_dy) = glyf_composite_point_offset(
        out,
        without_offset,
        comp.base_point_ix,
        comp.component_point_ix,
      )
      glyf_apply_transform(comp_path, {
        a: comp.a,
        b: comp.b,
        c: comp.c,
        d: comp.d,
        dx: anchor_dx,
        dy: anchor_dy,
      })
    }
    for e in transformed {
      out.push(e)
    }
  }
  Some(out)
}

///|
fn glyf_outline_path_idx(
  ctx : GlyfCtx,
  idx : Int,
  visited : Array[Bool],
  path_style : PathStyle,
) -> Array[PathElement]? {
  if idx < 0 || idx >= ctx.num_glyphs {
    return None
  }
  if visited.at(idx) {
    return None
  }
  visited.set(idx, true)
  let res = match glyf_glyph_slice(ctx, idx) {
    None => None
    Some(glyph) =>
      if glyph.length() == 0 {
        Some(Array::new())
      } else {
        match glyf_read_i16_be(glyph, 0) {
          None => None
          Some(nc) =>
            if nc < 0 {
              glyf_composite_path(
                ctx,
                glyph,
                GlyphId(idx.to_uint16()),
                visited,
                path_style,
              )
            } else {
              glyf_simple_path(ctx, glyph, GlyphId(idx.to_uint16()), path_style)
            }
        }
      }
  }
  visited.set(idx, false)
  res
}

///|
fn glyf_outline_path(
  font : @moon_skrifa.FontRef,
  gid : @moon_skrifa.GlyphId,
  coords : ArrayView[@moon_skrifa.NormalizedCoord],
  path_style : PathStyle,
  size : @moon_skrifa.Size,
  is_hinted : Bool,
) -> Array[PathElement]? {
  let upem = glyf_units_per_em(font)
  let (is_scaled, scale_bits) = glyf_compute_scale_bits(size, upem)
  // HarfBuzz uses an exact 16.16 scale factor. Do not inherit FreeType's
  // fixed-point rounding of the scale factor used for 26.6.
  let hb_scale = match size.ppem() {
    None => 1.0
    Some(ppem) => {
      let upem_i = upem.to_int()
      if upem_i <= 0 {
        1.0
      } else {
        ppem * 65536.0 / upem_i.to_double()
      }
    }
  }
  let glyf = match font.table(TAG_GLYF) {
    None => return None
    Some(v) => v
  }
  let maxp = match font.table(TAG_MAXP) {
    None => return None
    Some(v) => v
  }
  let head = match font.table(TAG_HEAD) {
    None => return None
    Some(v) => v
  }
  let loca = match font.table(TAG_LOCA) {
    None => return None
    Some(v) => v
  }
  let num_glyphs = match glyf_read_u16_be(maxp, 4) {
    None => return None
    Some(v) => v
  }
  let idx = gid.to_uint64().to_int()
  if idx < 0 || idx >= num_glyphs {
    return None
  }
  let index_to_loc_format = match glyf_read_i16_be(head, 50) {
    None => return None
    Some(v) => v
  }
  let ctx = GlyfCtx::{
    font,
    glyf,
    loca,
    num_glyphs,
    index_to_loc_format,
    coords,
    is_scaled,
    is_hinted,
    scale_bits,
    hb_scale,
  }
  let x_shift = match glyf_glyph_slice(ctx, idx) {
    None => 0.0
    Some(glyph) =>
      if glyph.length() < 10 {
        0.0
      } else {
        let x_min = glyf_read_i16_be(glyph, 2).unwrap_or(0).to_double()
        let loc = @moon_skrifa.LocationRef::LocationRef(coords)
        let lsb = @moon_skrifa.FontRef::glyph_metrics(
            font,
            @moon_skrifa.Size::unscaled(),
            loc,
          )
          .left_side_bearing(gid)
          .unwrap_or(0.0)
        let x_shift_du = x_min - lsb
        if x_shift_du == 0.0 {
          0.0
        } else {
          match path_style {
            FreeType =>
              if is_scaled {
                glyf_f26dot6_bits_to_double(
                  glyf_mul_16_16_f(x_shift_du, scale_bits),
                )
              } else {
                x_shift_du
              }
            HarfBuzz =>
              if is_scaled {
                x_shift_du * hb_scale
              } else {
                x_shift_du
              }
          }
        }
      }
  }
  let visited = Array::make(num_glyphs, false)
  match glyf_outline_path_idx(ctx, idx, visited, path_style) {
    None => None
    Some(path) => {
      glyf_shift_path_x(path, x_shift)
      Some(path)
    }
  }
}

///|
fn glyf_glyph_count(font : @moon_skrifa.FontRef) -> Int? {
  let maxp = match font.table(TAG_MAXP) {
    None => return None
    Some(v) => v
  }
  // maxp.numGlyphs at offset 4.
  match glyf_read_u16_be(maxp, 4) {
    None => None
    Some(v) => Some(v)
  }
}

///|
fn glyf_outline_info_from_glyph(glyph : BytesView) -> (Bool, Bool)? {
  if glyph.length() < 10 {
    return None
  }
  let number_of_contours = match glyf_read_i16_be(glyph, 0) {
    None => return None
    Some(v) => v
  }
  if number_of_contours == 0 {
    return Some((false, false))
  }
  if number_of_contours < 0 {
    // Composite.
    let mut off = 10
    let mut has_overlaps = false
    let mut flags = 0
    while true {
      flags = match glyf_read_u16_be(glyph, off) {
        None => return None
        Some(v) => v
      }
      has_overlaps = has_overlaps || (flags & COMPOSITE_OVERLAP_COMPOUND) != 0
      // component glyph id
      match glyf_read_u16_be(glyph, off + 2) {
        None => return None
        Some(_) => ()
      }
      off = off + 4
      let arg_words = (flags & COMPOSITE_ARG_1_AND_2_ARE_WORDS) != 0
      let args_len = if arg_words { 4 } else { 2 }
      if off + args_len > glyph.length() {
        return None
      }
      off = off + args_len
      // Transform parameters.
      if (flags & COMPOSITE_WE_HAVE_A_SCALE) != 0 {
        off = off + 2
      } else if (flags & COMPOSITE_WE_HAVE_AN_X_AND_Y_SCALE) != 0 {
        off = off + 4
      } else if (flags & COMPOSITE_WE_HAVE_A_TWO_BY_TWO) != 0 {
        off = off + 8
      }
      if off < 0 || off > glyph.length() {
        return None
      }
      if (flags & COMPOSITE_MORE_COMPONENTS) == 0 {
        break
      }
    }
    let has_hinting = (flags & COMPOSITE_WE_HAVE_INSTRUCTIONS) != 0
    return Some((has_overlaps, has_hinting))
  }
  // Simple: scan flags for overlap bit; hinting if instruction length > 0.
  let mut off = 10
  let end_pts : Array[Int] = Array::new()
  for _ in 0.. return None
      Some(u) => u
    }
    end_pts.push(v)
    off = off + 2
  }
  let instruction_len = match glyf_read_u16_be(glyph, off) {
    None => return None
    Some(v) => v
  }
  off = off + 2
  if instruction_len < 0 || off + instruction_len > glyph.length() {
    return None
  }
  let has_hinting = instruction_len > 0
  off = off + instruction_len
  let last_end = end_pts.at(end_pts.length() - 1)
  let num_points = last_end + 1
  if num_points <= 0 {
    return Some((false, has_hinting))
  }
  let mut has_overlaps = false
  let flags : Array[Int] = Array::new()
  while flags.length() < num_points {
    if off >= glyph.length() {
      return None
    }
    let flag = glyph.at(off).to_int()
    off = off + 1
    has_overlaps = has_overlaps || (flag & SIMPLE_OVERLAP_FLAG) != 0
    flags.push(flag)
    if (flag & 0x08) != 0 {
      if off >= glyph.length() {
        return None
      }
      let repeat = glyph.at(off).to_int()
      off = off + 1
      for _ in 0.. (Bool, Bool)? {
  let glyf = match font.table(TAG_GLYF) {
    None => return None
    Some(v) => v
  }
  let maxp = match font.table(TAG_MAXP) {
    None => return None
    Some(v) => v
  }
  let head = match font.table(TAG_HEAD) {
    None => return None
    Some(v) => v
  }
  let loca = match font.table(TAG_LOCA) {
    None => return None
    Some(v) => v
  }
  let num_glyphs = match glyf_read_u16_be(maxp, 4) {
    None => return None
    Some(v) => v
  }
  let idx = gid.to_uint64().to_int()
  if idx < 0 || idx >= num_glyphs {
    return None
  }
  let index_to_loc_format = match glyf_read_i16_be(head, 50) {
    None => return None
    Some(v) => v
  }
  let empty : Array[@moon_skrifa.NormalizedCoord] = Array::new()
  let ctx = GlyfCtx::{
    font,
    glyf,
    loca,
    num_glyphs,
    index_to_loc_format,
    coords: empty.op_as_view(),
    is_scaled: false,
    is_hinted: false,
    scale_bits: 0x10000,
    hb_scale: 1.0,
  }
  match glyf_glyph_slice(ctx, idx) {
    None => None
    Some(g) => glyf_outline_info_from_glyph(g)
  }
}

///|
fn glyf_has_overlaps(
  font : @moon_skrifa.FontRef,
  gid : @moon_skrifa.GlyphId,
) -> Bool? {
  match glyf_outline_info(font, gid) {
    None => None
    Some((has_overlaps, _)) => Some(has_overlaps)
  }
}

///|
fn glyf_has_hinting(
  font : @moon_skrifa.FontRef,
  gid : @moon_skrifa.GlyphId,
) -> Bool? {
  match glyf_outline_info(font, gid) {
    None => None
    Some((_, has_hinting)) => Some(has_hinting)
  }
}

///|
const GLYF_MEM_PHANTOM_POINT_COUNT : Int = 4

///|
const GLYF_MEM_TAG_GVAR : UInt = 0x67766172 // "gvar"

///|
const GLYF_MEM_TAG_CVT : UInt = 0x63767420 // "cvt "

///|
const GLYF_MEM_COMPOSITE_RECURSION_LIMIT : Int = 32

///|
// These sizes match upstream read-fonts layouts:
// Point => 2x i32 = 8 bytes, PointFlags => u8 = 1 byte.
const GLYF_MEM_SIZE_POINT : Int = 8

///|
const GLYF_MEM_SIZE_POINT_FLAGS : Int = 1

///|
const GLYF_MEM_SIZE_U16 : Int = 2

///|
const GLYF_MEM_SIZE_I32 : Int = 4

///|
const GLYF_MEM_SIZE_ALIGN_I32 : Int = 4

///|
priv struct GlyfDrawMemorySummary {
  mut points : Int
  mut contours : Int
  mut max_simple_points : Int
  mut max_other_points : Int
  mut max_component_delta_stack : Int
  mut has_hinting : Bool
  mut has_overlaps : Bool
  has_variations : Bool
  max_stack : Int
  cvt_count : Int
  storage_count : Int
  max_twilight_points : Int
}

///|
fn glyf_draw_memory_summary_default(
  font : @moon_skrifa.FontRef,
) -> GlyfDrawMemorySummary {
  let has_variations = font.table(GLYF_MEM_TAG_GVAR) is Some(_)
  {
    points: 0,
    contours: 0,
    max_simple_points: 0,
    max_other_points: 0,
    max_component_delta_stack: 0,
    has_hinting: false,
    has_overlaps: false,
    has_variations,
    max_stack: 0,
    cvt_count: 0,
    storage_count: 0,
    max_twilight_points: 0,
  }
}

///|
fn glyf_draw_memory_summary_with_limits(
  font : @moon_skrifa.FontRef,
  max_stack : Int,
  cvt_count : Int,
  storage_count : Int,
  max_twilight_points : Int,
) -> GlyfDrawMemorySummary {
  let base = glyf_draw_memory_summary_default(font)
  {
    points: base.points,
    contours: base.contours,
    max_simple_points: base.max_simple_points,
    max_other_points: base.max_other_points,
    max_component_delta_stack: base.max_component_delta_stack,
    has_hinting: base.has_hinting,
    has_overlaps: base.has_overlaps,
    has_variations: base.has_variations,
    max_stack,
    cvt_count,
    storage_count,
    max_twilight_points,
  }
}

///|
fn glyf_draw_memory_required_size(
  sum : GlyfDrawMemorySummary,
  hinting : Hinting,
) -> Int {
  let hinted = sum.has_hinting && hinting is Embedded
  let mut size = 0
  // Scaled points.
  size = size + sum.points * GLYF_MEM_SIZE_POINT
  // Unscaled and (if hinted) original scaled points.
  size = size +
    sum.max_other_points * GLYF_MEM_SIZE_POINT * (if hinted { 2 } else { 1 })
  // Contour end points.
  size = size + sum.contours * GLYF_MEM_SIZE_U16
  // Point flags.
  size = size + sum.points * GLYF_MEM_SIZE_POINT_FLAGS
  if sum.has_variations {
    // IUP buffer + delta buffers.
    size = size + sum.max_simple_points * GLYF_MEM_SIZE_POINT
    size = size + sum.max_simple_points * GLYF_MEM_SIZE_POINT
    size = size + sum.max_component_delta_stack * GLYF_MEM_SIZE_POINT
  }
  if hinted {
    size = size + sum.max_stack * GLYF_MEM_SIZE_I32
    size = size + (sum.cvt_count + sum.storage_count) * GLYF_MEM_SIZE_I32
    size = size +
      sum.max_twilight_points *
      (GLYF_MEM_SIZE_POINT * 2 + GLYF_MEM_SIZE_POINT_FLAGS)
  }
  if size != 0 {
    size = size + GLYF_MEM_SIZE_ALIGN_I32
  }
  size
}

///|
fn glyf_draw_memory_summary_rec(
  ctx : GlyfCtx,
  idx : Int,
  visited : Array[Bool],
  sum : GlyfDrawMemorySummary,
  component_depth : Int,
  recurse_depth : Int,
) -> Bool {
  if recurse_depth > GLYF_MEM_COMPOSITE_RECURSION_LIMIT {
    return false
  }
  if idx < 0 || idx >= ctx.num_glyphs {
    return false
  }
  if visited.at(idx) {
    return false
  }
  visited.set(idx, true)
  let glyph = match glyf_glyph_slice(ctx, idx) {
    None => {
      visited.set(idx, false)
      return false
    }
    Some(g) => g
  }
  // Empty glyph is valid (loca start==end).
  if glyph.length() == 0 {
    visited.set(idx, false)
    return true
  }
  if glyph.length() < 10 {
    visited.set(idx, false)
    return false
  }
  let number_of_contours = match glyf_read_i16_be(glyph, 0) {
    None => {
      visited.set(idx, false)
      return false
    }
    Some(v) => v
  }
  if number_of_contours == 0 {
    visited.set(idx, false)
    return true
  }
  if number_of_contours > 0 {
    // Simple glyph.
    let mut off = 10
    let mut last_end = -1
    for _ in 0.. {
          visited.set(idx, false)
          return false
        }
        Some(u) => u
      }
      last_end = v
      off = off + 2
    }
    let instruction_len = match glyf_read_u16_be(glyph, off) {
      None => {
        visited.set(idx, false)
        return false
      }
      Some(v) => v
    }
    off = off + 2
    if instruction_len < 0 || off + instruction_len > glyph.length() {
      visited.set(idx, false)
      return false
    }
    let has_hinting = instruction_len > 0
    off = off + instruction_len
    let num_points = last_end + 1
    if num_points > 0 {
      let num_points_with_phantom = num_points + GLYF_MEM_PHANTOM_POINT_COUNT
      sum.max_simple_points = sum.max_simple_points.max(num_points_with_phantom)
      sum.max_other_points = sum.max_other_points.max(num_points_with_phantom)
      sum.points = sum.points + num_points
      sum.contours = sum.contours + number_of_contours
      sum.has_hinting = sum.has_hinting || has_hinting
      // Scan flags for overlap bit.
      let mut seen = 0
      while seen < num_points {
        if off >= glyph.length() {
          visited.set(idx, false)
          return false
        }
        let flag = glyph.at(off).to_int()
        off = off + 1
        sum.has_overlaps = sum.has_overlaps || (flag & SIMPLE_OVERLAP_FLAG) != 0
        seen = seen + 1
        if (flag & 0x08) != 0 {
          if off >= glyph.length() {
            visited.set(idx, false)
            return false
          }
          let repeat = glyph.at(off).to_int()
          off = off + 1
          for _ in 0.. {
        visited.set(idx, false)
        return false
      }
      Some(v) => v
    }
    sum.has_overlaps = sum.has_overlaps ||
      (flags & COMPOSITE_OVERLAP_COMPOUND) != 0
    let comp_gid = match glyf_read_u16_be(glyph, off + 2) {
      None => {
        visited.set(idx, false)
        return false
      }
      Some(v) => v
    }
    comp_ids.push(comp_gid)
    component_count = component_count + 1
    off = off + 4
    let arg_words = (flags & COMPOSITE_ARG_1_AND_2_ARE_WORDS) != 0
    let args_len = if arg_words { 4 } else { 2 }
    if off + args_len > glyph.length() {
      visited.set(idx, false)
      return false
    }
    off = off + args_len
    if (flags & COMPOSITE_WE_HAVE_A_SCALE) != 0 {
      off = off + 2
    } else if (flags & COMPOSITE_WE_HAVE_AN_X_AND_Y_SCALE) != 0 {
      off = off + 4
    } else if (flags & COMPOSITE_WE_HAVE_A_TWO_BY_TWO) != 0 {
      off = off + 8
    }
    if off < 0 || off > glyph.length() {
      visited.set(idx, false)
      return false
    }
    if (flags & COMPOSITE_MORE_COMPONENTS) == 0 {
      break
    }
  }
  let has_hinting = (flags & COMPOSITE_WE_HAVE_INSTRUCTIONS) != 0
  let count = component_count + GLYF_MEM_PHANTOM_POINT_COUNT
  sum.max_component_delta_stack = sum.max_component_delta_stack.max(
    component_depth + count,
  )
  for cg in comp_ids.iter() {
    // Missing component glyphs are treated as empty.
    if cg >= 0 && cg < ctx.num_glyphs {
      if !glyf_draw_memory_summary_rec(
          ctx,
          cg,
          visited,
          sum,
          component_depth + count,
          recurse_depth + 1,
        ) {
        visited.set(idx, false)
        return false
      }
    }
  }
  if has_hinting {
    let num_points_in_composite = sum.points -
      point_base +
      GLYF_MEM_PHANTOM_POINT_COUNT
    sum.max_other_points = sum.max_other_points.max(num_points_in_composite)
  }
  sum.has_hinting = sum.has_hinting || has_hinting
  visited.set(idx, false)
  true
}

///|
/// Returns the required temporary memory size (in bytes) for drawing a glyf
/// outline, matching upstream `skrifa::outline::glyf::Outline::required_buffer_size`.
fn glyf_draw_memory_size(
  font : @moon_skrifa.FontRef,
  gid : @moon_skrifa.GlyphId,
  hinting : Hinting,
) -> Int? {
  // Build a context for slice access.
  let glyf = match font.table(TAG_GLYF) {
    None => return None
    Some(v) => v
  }
  let maxp = match font.table(TAG_MAXP) {
    None => return None
    Some(v) => v
  }
  let head = match font.table(TAG_HEAD) {
    None => return None
    Some(v) => v
  }
  let loca = match font.table(TAG_LOCA) {
    None => return None
    Some(v) => v
  }
  let num_glyphs = match glyf_read_u16_be(maxp, 4) {
    None => return None
    Some(v) => v
  }
  let idx = gid.to_uint64().to_int()
  if idx < 0 || idx >= num_glyphs {
    return None
  }
  let index_to_loc_format = match glyf_read_i16_be(head, 50) {
    None => return None
    Some(v) => v
  }
  let empty : Array[@moon_skrifa.NormalizedCoord] = Array::new()
  let ctx = GlyfCtx::{
    font,
    glyf,
    loca,
    num_glyphs,
    index_to_loc_format,
    coords: empty.op_as_view(),
    is_scaled: false,
    is_hinted: false,
    scale_bits: 0x10000,
    hb_scale: 1.0,
  }

  // Parse maxp-derived hinting limits and CVT size.
  let max_twilight_points = glyf_read_u16_be(maxp, 16).unwrap_or(0) + 4
  let max_stack = glyf_read_u16_be(maxp, 24).unwrap_or(0) + 32
  let max_storage = glyf_read_u16_be(maxp, 18).unwrap_or(0)
  let cvt_count = match font.table(GLYF_MEM_TAG_CVT) {
    None => 0
    Some(cvt) => cvt.length() / 2
  }
  let sum = glyf_draw_memory_summary_with_limits(
    font, max_stack, cvt_count, max_storage, max_twilight_points,
  )
  let visited = Array::make(num_glyphs, false)
  if !glyf_draw_memory_summary_rec(ctx, idx, visited, sum, 0, 0) {
    return None
  }
  // Add phantom points at top-level.
  sum.points = sum.points + GLYF_MEM_PHANTOM_POINT_COUNT
  Some(glyf_draw_memory_required_size(sum, hinting))
}