Commit 0514685a authored by Paul Asmuth's avatar Paul Asmuth
Browse files

implement bidirectional text placement

parent e32115df
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -185,7 +185,7 @@ Status svg_text_span_embed(
      Path gp;

      auto rc = font_get_glyph_path(
          s.font,
          g.font,
          op.style.font_size,
          dpi,
          g.codepoint,
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ Status drawTextLabel(
    Layer* layer) {
  Rectangle bbox;
  std::vector<text::GlyphSpan> spans;
  auto rc = text::text_layout_hspan(
  auto rc = text::text_layout_hline(
      text,
      style.direction,
      style.font,
+1 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ namespace fviz::text {
 */
ReturnCode text_analyze_bidi_line(
    const std::string& text,
    TextDirection text_direction,
    TextDirection base_text_direction,
    TextLine* text_span);

} // namespace fviz::text
+2 −2
Original line number Diff line number Diff line
@@ -19,10 +19,10 @@ namespace fviz::text {

ReturnCode text_analyze_bidi_line(
    const std::string& text,
    TextDirection text_direction,
    TextDirection base_text_direction,
    TextLine* text_line) {
  FriBidiParType fb_basedir;
  switch (text_direction) {
  switch (base_text_direction) {
    case TextDirection::LTR:
      fb_basedir = FRIBIDI_PAR_LTR;
      break;
+90 −30
Original line number Diff line number Diff line
@@ -19,17 +19,16 @@
namespace fviz {
namespace text {

Status text_layout_hspan(
Status text_layout_hrun(
    const std::string& text_logical,
    const TextDirection text_direction,
    const FontInfo& font_info,
    double font_size,
    double dpi,
    std::vector<GlyphSpan>* glyph_spans,
    Rectangle* bbox) {
  TextLine text_line;
  text_analyze_bidi_line(text_logical, text_direction, &text_line);

    std::vector<GlyphPlacement>* glyphs,
    double* span_length,
    double* span_top,
    double* span_bottom) {
  std::vector<GlyphInfo> glyph_list;
  auto shaping_rc = text_shape_run_with_font_fallback(
      text_logical,
@@ -43,64 +42,125 @@ Status text_layout_hspan(
    return shaping_rc;
  }

  double span_length = 0.0;
  double span_top = 0.0;
  double span_bottom = 0.0;
  for (const auto& gi : glyph_list) {
    GlyphPlacement gp;
    gp.font = gi.font;
    gp.codepoint = gi.codepoint;
    gp.y = 0;

    switch (text_direction) {
      case TextDirection::LTR:
        gp.x = span_length;
        gp.x = *span_length;
        break;
      case TextDirection::RTL:
        gp.x = -*span_length - gi.advance_x;
        break;
    }

    glyphs->emplace_back(gp);

    *span_length += gi.advance_x;
    *span_top = std::min(-gi.metrics_ascender, *span_top);
    *span_bottom = std::max(-gi.metrics_descender, *span_bottom);
  }

  return OK;
}

Status text_layout_hline(
    const std::string& text_logical,
    const TextDirection base_text_direction,
    const FontInfo& font_info,
    double font_size,
    double dpi,
    std::vector<GlyphSpan>* glyph_spans,
    Rectangle* bbox) {
  TextLine text_line;
  text_analyze_bidi_line(text_logical, base_text_direction, &text_line);

  double line_top = 0.0;
  double line_bottom = 0.0;
  double line_length = 0;
  for (size_t i = 0; i < text_line.text_runs.size(); ++i) {
    double span_length = 0.0;
    std::vector<GlyphPlacement> span_glyphs;

    auto rc = text_layout_hrun(
        text_line.text_runs[i],
        text_line.text_directions[i],
        font_info,
        font_size,
        dpi,
        &span_glyphs,
        &span_length,
        &line_top,
        &line_bottom);

    if (rc != OK) {
      return rc;
    }

    for (auto& gi : span_glyphs) {
      if (base_text_direction != text_line.text_directions[i]) {
        switch (base_text_direction) {
          case TextDirection::LTR:
            gi.x += span_length;
            break;
          case TextDirection::RTL:
        gp.x = -span_length - gi.advance_x;
            gi.x -= span_length;
            break;
        }
      }

    GlyphSpan span;
    span.font = gi.font;
    span.glyphs.push_back(gp);
      switch (base_text_direction) {
        case TextDirection::LTR:
          gi.x += line_length;
          break;
        case TextDirection::RTL:
          gi.x -= line_length;
          break;
      }

      GlyphSpan gs;
      gs.font = gi.font;
      gs.glyphs.emplace_back(gi);

      // TODO merge glyph spans witht the same font
      if (glyph_spans) {
      glyph_spans->emplace_back(span);
        glyph_spans->emplace_back(gs);
      }

    span_length += gi.advance_x;
    span_top = std::min(-gi.metrics_ascender, span_top);
    span_bottom = std::max(-gi.metrics_descender, span_bottom);
    }

    line_length += span_length;
  }

  double span_left = 0.0;
  switch (text_direction) {
  double line_left = 0.0;
  switch (base_text_direction) {
    case TextDirection::LTR:
      span_left = 0;
      line_left = 0;
      break;
    case TextDirection::RTL:
      span_left = -span_length;
      line_left = -line_length;
      break;
  }

  *bbox = Rectangle(
      span_left,
      span_top,
      span_length,
      span_bottom - span_top);
      line_left,
      line_top,
      line_length,
      line_bottom - line_top);

  return OK;
}


Status text_measure_span(
    const std::string& text,
    const FontInfo& font_info,
    double font_size,
    double dpi,
    Rectangle* bbox) {
  return text_layout_hspan(
  return text_layout_hline(
      text,
      TextDirection::LTR,
      font_info,
Loading