///|
fn PdfDocument::pdf_text_font_metrics_descriptor(
  self : PdfDocument,
  font : @syntax.PdfObject,
) -> @syntax.PdfObject? {
  match self.lookup_direct(pdf_text_subtype_key_name, font) {
    Some(PdfNameObject(subtype)) if subtype == pdf_text_type3_name => Some(font)
    _ => self.lookup_direct(pdf_text_font_descriptor_key_name, font)
  }
}

///|
fn PdfDocument::pdf_text_font_char_bound(
  self : PdfDocument,
  font : @syntax.PdfObject,
  key : @core.PdfName,
  error : @core.PdfError,
) -> Int raise @core.PdfError {
  match self.lookup_direct(key, font) {
    Some(PdfInteger(value)) if value >= 0 && value <= 255 => value
    _ => raise error
  }
}

///|
fn PdfDocument::pdf_text_font_missing_width(
  self : PdfDocument,
  descriptor : @syntax.PdfObject,
) -> Double raise @core.PdfError {
  match self.lookup_direct(pdf_text_missing_width_key_name, descriptor) {
    Some(value) => self.get_number(value)
    None => 0.0
  }
}

///|
fn PdfDocument::pdf_text_font_widths_array(
  self : PdfDocument,
  font : @syntax.PdfObject,
) -> Array[@syntax.PdfObject] raise @core.PdfError {
  match self.lookup_direct(pdf_text_widths_key_name, font) {
    Some(PdfArray(values)) => values
    _ => raise FontWidthsExpected
  }
}

///|
/// Read normalized one-byte font metrics for a simple or Type 3 font.
///
/// The result contains 256 entries when `/Widths`, `/FirstChar`, and
/// `/LastChar` are present and well formed. Missing metrics return `None`;
/// malformed bounds or width arrays raise the corresponding font error.
pub fn PdfDocument::read_font_metrics(
  self : PdfDocument,
  font : @syntax.PdfObject,
) -> Array[Double]? raise @core.PdfError {
  match self.pdf_text_font_metrics_descriptor(font) {
    None => None
    Some(descriptor) => {
      let firstchar = self.pdf_text_font_char_bound(
        font,
        pdf_text_first_char_key_name,
        FontFirstCharExpected,
      )
      let lastchar = self.pdf_text_font_char_bound(
        font,
        pdf_text_last_char_key_name,
        FontLastCharExpected,
      )
      guard lastchar >= firstchar else { raise FontWidthsExpected }
      let widths = self.pdf_text_font_widths_array(font)
      guard widths.length() == lastchar - firstchar + 1 else {
        raise FontWidthsExpected
      }
      let missingwidth = self.pdf_text_font_missing_width(descriptor)
      let metrics : Array[Double] = Array(capacity=256)
      for _ in 0.. raise FontWidthExpected
          },
        )
      }
      for _ in 0..<(255 - lastchar) {
        metrics.push(missingwidth)
      }
      Some(metrics)
    }
  }
}