示例#1
0
 def render_cmd_left_right(self, children: List[MathTexAST],
                           font_size) -> HtmlElement:
     middle_item = self.render(children[2], font_size)
     brace_size = middle_item.height / FONT_METRICS.height
     left = children[0].get_first_string()
     right = children[1].get_first_string()
     elem = HtmlElement()
     if len(left) == 1 and left in "([{":
         if brace_size <= 1:
             elem.children.append(
                 self.render_text(left, brace_size, font_size))
         else:
             elem.children.append(
                 HtmlElement.create_brace(left, middle_item.height,
                                          middle_item.baseline, font_size))
     elem.children.append(middle_item)
     if len(right) == 1 and right in ")]}":
         if brace_size <= 1:
             elem.children.append(
                 self.render_text(right, brace_size, font_size))
         else:
             elem.children.append(
                 HtmlElement.create_brace(right, middle_item.height,
                                          middle_item.baseline, font_size))
     self.align_children(elem, font_size)
     return elem
示例#2
0
 def align_children(self, elem: HtmlElement, font_size):
     elem.width = 0
     elem.height = 0
     elem.baseline = 0
     for i in range(0, len(elem.children)):
         if i > 0:
             elem.width += self.char_margin * font_size
         child = elem.children[i]
         child.x = elem.width
         if child.baseline > elem.baseline:
             elem.baseline = child.baseline
         elem.width += child.width
     for child in elem.children:
         child.y = elem.baseline - child.baseline
         if child.y + child.height > elem.height:
             elem.height = child.y + child.height
     return elem
示例#3
0
 def render_block(self, children: List[MathTexAST],
                  font_size) -> HtmlElement:
     elem = HtmlElement()
     for i in range(0, len(children)):
         child = self.render(children[i], font_size)
         elem.children.append(child)
     self.align_children(elem, font_size)
     return elem
示例#4
0
 def render_cmd_sub_sup(self, children: List[MathTexAST],
                        font_size) -> HtmlElement:
     elem = HtmlElement()
     main_item = self.render(children[0], font_size)
     elem.children.append(main_item)
     elem.width = main_item.width
     elem.height = main_item.height
     elem.baseline = main_item.baseline
     sub_size = (font_size + 3) / 5
     if children[1] is not None:
         sub_item = self.render(children[1], sub_size)
         sub_item.x = main_item.width + sub_size * self.char_margin
         elem.children.append(sub_item)
         elem.width = sub_item.x + sub_item.width
         if sub_item.height > main_item.height / 2:
             main_item.y = sub_item.height - main_item.height / 2
             elem.baseline += main_item.y
             elem.height += main_item.y
     if children[2] is not None:
         sup_item = self.render(children[2], sub_size)
         sup_item.x = main_item.width + sub_size * self.char_margin
         elem.children.append(sup_item)
         elem.width = max(elem.width, sup_item.x + sup_item.width)
         delta = sup_item.height - main_item.height / 2
         if delta <= 0:
             sup_item.y = main_item.y + main_item.height / 2 - delta
         else:
             sup_item.y = main_item.y + main_item.height / 2
             elem.height += delta
     return elem
示例#5
0
 def render_text(self,
                 text,
                 font_size,
                 middle_align_with=None,
                 italic=True,
                 bold=False) -> HtmlElement:
     elem = HtmlElement(width=0, height=self.line_height * font_size)
     if middle_align_with is not None:
         elem.update_baseline(middle_align_with)
     else:
         elem.update_baseline(font_size)
     for i in range(0, len(text)):
         c = text[i]
         if i > 0:
             elem.width += self.char_margin * font_size
             pre_c = text[i - 1]
             bearing = min(
                 FONT_METRICS.get_glyph(pre_c).right_bearing,
                 FONT_METRICS.get_glyph(c).left_bearing)
             if bearing > 0:
                 elem.width -= bearing * font_size
         css_class = "bold" if bold else None
         if c.isalpha() and italic:
             css_class = "bold italic" if bold else "italic"
         child = HtmlElement(x=elem.width,
                             y=0,
                             text=c,
                             font_size=font_size,
                             css_class=css_class)
         elem.width += FONT_METRICS.get_glyph(c).width * font_size
         elem.children.append(child)
     return elem
示例#6
0
 def render_env(self, lines: List[MathTexAST], font_size) -> HtmlElement:
     elem = HtmlElement()
     children = Array2D()  # type: Array2D[HtmlElement]
     for i in range(0, len(lines)):
         line = lines[i]
         for j in range(0, len(line.children)):
             child = self.render(line.children[j], font_size)
             children.set(i, j, child)
     self.align_children_grid(elem, children, font_size)
     return elem
示例#7
0
 def render(self, node: MathTexAST, font_size) -> HtmlElement:
     node.prepare_render()
     if node.node_type == MathTexAST.TEXT_NODE:
         return self.render_text(node.text, font_size)
     if node.node_type == MathTexAST.BLOCK_NODE:
         return self.render_block(node.children, font_size)
     if node.node_type == MathTexAST.CELL_NODE:
         return self.render_block(node.children, font_size)
     if node.node_type == MathTexAST.ENV_NODE:
         return self.render_env(node.children, font_size)
     if node.node_type == MathTexAST.CMD_NODE:
         return self.render_command(node.command, node.children, font_size)
     return HtmlElement(width=0, height=0)
示例#8
0
 def render_cmd_square_root(self, children: List[MathTexAST],
                            font_size) -> HtmlElement:
     elem = HtmlElement()
     inner_item = self.render(children[0], font_size)
     inner_item.x = 0.4 * font_size
     inner_item.y = 0.1 * font_size
     elem.width = inner_item.x + inner_item.width + 0.2 * font_size
     elem.height = inner_item.y + inner_item.height
     elem.baseline = inner_item.y + inner_item.baseline
     elem.children = [inner_item] + HtmlElement.create_square_root_group(
         elem.width, elem.height, font_size)
     return elem
示例#9
0
    def align_children_grid(self, elem: HtmlElement,
                            children: Array2D[HtmlElement], font_size):
        rows = Array1D(children.height, lambda: RowColumnMeta())
        columns = Array1D(children.width, lambda: RowColumnMeta())

        def update_row_column_meta1(y, x, item: HtmlElement):
            if item.baseline > rows[y].baseline:
                rows[y].baseline = item.baseline
            if item.width > columns[x].width:
                columns[x].width = item.width

        def update_row_column_meta2(y, _, item: HtmlElement):
            y_offset = rows[y].baseline - item.baseline
            new_height = y_offset + item.height
            if new_height > rows[y].height:
                rows[y].height = new_height

        children.for_each_not_none(update_row_column_meta1)
        children.for_each_not_none(update_row_column_meta2)
        for i in range(0, children.height):
            if i > 0:
                rows[i].y = rows[i - 1].y + rows[
                    i - 1].height + self.line_margin * font_size
            elem.height = rows[i].y + rows[i].height
        elem.update_baseline(font_size)
        for j in range(0, children.width):
            if j > 0:
                columns[j].x = columns[j - 1].x + columns[
                    j - 1].width + self.cell_margin * font_size
            elem.width = columns[j].x + columns[j].width

        def update_cell_position(y, x, item: HtmlElement):
            item.x = columns[x].x
            item.y = rows[y].y + rows[y].baseline - item.baseline
            elem.children.append(item)

        children.for_each_not_none(update_cell_position)
示例#10
0
 def render_cmd_fraction(self, children: List[MathTexAST],
                         font_size) -> HtmlElement:
     elem = HtmlElement()
     up_item = self.render(children[0], font_size)
     down_item = self.render(children[1], font_size)
     elem.width = max(up_item.width, down_item.width) + font_size / 2
     elem.height = up_item.height + down_item.height + self.line_margin * font_size
     elem.update_baseline(font_size,
                          pseudo_height=up_item.height * 2 +
                          self.line_margin * font_size)
     up_item.x = (elem.width - up_item.width) / 2
     down_item.x = (elem.width - down_item.width) / 2
     down_item.y = elem.height - down_item.height
     line = HtmlElement.create_horizontal_line(
         font_size / 8, up_item.height + self.line_margin * font_size / 2,
         elem.width - font_size / 4)
     elem.children = [up_item, down_item, line]
     return elem
示例#11
0
 def update_cell_position(y, x, item: HtmlElement):
     item.x = columns[x].x
     item.y = rows[y].y + rows[y].baseline - item.baseline
     elem.children.append(item)