class_docstr: A class for converting documents from the hOCR format.
  
  For details of the hOCR format, see:
  http://kba.cloud/hocr-spec/.
class_docstr_tok: ["A","class","for","converting","documents","from","the","hOCR","format",".","For","details","of","the","hOCR","format",",","see",":","http",":","\/\/kba.cloud\/hocr-spec\/","."]
docstr: Render the text for a given line.
  
  The canvas's coordinate system must be configured so that hOCR pixel
  coordinates are mapped to PDF coordinates.
docstr_tok: ["Render","the","text","for","a","given","line",".","The","canvas","'s","coordinate","system","must","be","configured","so","that","hOCR","pixel","coordinates","are","mapped","to","PDF","coordinates","."]
code: def _do_line(
      self,
      canvas: Canvas,
      line: Element | None,
      elemclass: str,
      invisible_text: bool,
      text_direction: TextDirection,
      inject_word_breaks: bool,
  ):
      """Render the text for a given line.
  
      The canvas's coordinate system must be configured so that hOCR pixel
      coordinates are mapped to PDF coordinates.
      """
      if line is None:
          return
      line_box = self.element_coordinates(line)
      if not line_box:
          return
      assert line_box.ury > line_box.lly  # lly is top, ury is bottom
  
      self._debug_draw_line_bbox(canvas, line_box)
  
      # Baseline is a polynomial (usually straight line) that describes the
      # text baseline relative to the bottom left corner of the line bounding
      # box.
      bottom_left_corner = line_box.llx, line_box.ury
      slope, intercept = self.baseline(line)
      if abs(slope) < 0.005:
          slope = 0.0
      angle = atan(slope)
  
      # Setup a new coordinate system on the line box's intercept and rotated by
      # its slope.
      line_matrix = (
          Matrix()
          .translated(*bottom_left_corner)
          .translated(0, intercept)
          .rotated(angle / pi * 180)
      )
      log.debug(line_matrix)
      with canvas.do.save_state(cm=line_matrix):
          text = Text(direction=text_direction)
  
          # Don't allow the font to break out of the bounding box. Division by
          # cos_a accounts for extra clearance between the glyph's vertical axis
          # on a sloped baseline and the edge of the bounding box.
          line_box_height = abs(line_box.height) / cos(angle)
          fontsize = line_box_height + intercept
          text.font(self._fontname, fontsize)
          text.render_mode(3 if invisible_text else 0)
  
          self._debug_draw_baseline(
              canvas, line_matrix.inverse().transform(line_box), 0
          )
  
          canvas.do.fill_color(BLACK)  # text in black
          elements = line.findall(self._child_xpath("span", elemclass))
          for elem, next_elem in pairwise(elements + [None]):
              self._do_line_word(
                  canvas,
                  line_matrix,
                  text,
                  fontsize,
                  elem,
                  next_elem,
                  text_direction,
                  inject_word_breaks,
              )
          canvas.do.draw_text(text)
  
imports: from __future__ import annotations
  import logging
  import os
  import re
  import unicodedata
  from dataclasses import dataclass
  from itertools import pairwise
  from math import atan, cos, pi
  from pathlib import Path
  from xml.etree import ElementTree
  from pikepdf import Matrix, Name, Rectangle
  from pikepdf.canvas import BLACK, BLUE, CYAN, DARKGREEN, GREEN, MAGENTA, RED, Canvas, Text, TextDirection
  from ocrmypdf.hocrtransform._font import EncodableFont
  from ocrmypdf.hocrtransform._font import GlyphlessFont
label_desc: Use image node_id 11 for calling the HocrTransform obj's underlying member method code with example usage: obj._do_line(canvas, line, elemclass, invisible_text, text_direction, inject_word_breaks) without return types