Commit 24c0020c authored by Paul Asmuth's avatar Paul Asmuth
Browse files

go back to using std::variant

parent 3f6814d0
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -28,17 +28,13 @@ namespace clip {
 * Since the page is a low-level interface, it is recommended that you use one
 * of the helper functions, such as page_add_text or page_add_shape instead of
 * interacting directly with the elements lists. Nevertheless, directly
 * manipulating the element lists is safe as long as you ensure that all elements
 * list are ordered by increasing z-index and the zindex member contains the
 * maximum z index of all elements.
 * manipulating the structure is safe.
 */
struct Page {
  double width;
  double height;
  double dpi;
  std::vector<PageTextElement> text_elements;
  std::vector<PageShapeElement> shape_elements;
  std::optional<uint32_t> zindex;
  std::vector<PageElement> elements;
  FontInfo font;
  Measure font_size;
  Color background_color;
+2 −12
Original line number Diff line number Diff line
@@ -16,21 +16,11 @@
namespace clip {

void page_add_text(Page* page, PageTextElement elem) {
  if (!elem.zindex) {
    elem.zindex = page->zindex.value_or(0) + 1;
  }

  page->zindex = std::max(*elem.zindex, page->zindex.value_or(0));
  page->text_elements.emplace_back(std::move(elem));
  page->elements.emplace_back(std::move(elem));
}

void page_add_shape(Page* page, PageShapeElement elem) {
  if (!elem.zindex) {
    elem.zindex = page->zindex.value_or(0) + 1;
  }

  page->zindex = std::max(*elem.zindex, page->zindex.value_or(0));
  page->shape_elements.emplace_back(std::move(elem));
  page->elements.emplace_back(std::move(elem));
}

} // namespace clip
+6 −3
Original line number Diff line number Diff line
@@ -13,8 +13,9 @@
 */
#pragma once
#include <stdlib.h>
#include <vector>
#include <string>
#include <variant>
#include <vector>

#include "color.h"
#include "text.h"
@@ -37,7 +38,6 @@ struct PageTextElement {
  Point origin;

  TextStyle style;
  std::optional<uint32_t> zindex;
  Rectangle clip;
  std::optional<mat3> transform;
};
@@ -46,10 +46,13 @@ struct PageShapeElement {
  Path path;
  StrokeStyle stroke_style;
  std::optional<Color> fill_color;
  std::optional<uint32_t> zindex;
  Rectangle clip;
  std::optional<AntialiasingMode> antialiasing_mode;
};

using PageElement = std::variant<
    PageTextElement,
    PageShapeElement>;

} // namespace clip
+12 −35
Original line number Diff line number Diff line
@@ -27,48 +27,25 @@ struct DrawOp {
ReturnCode page_export_png(
    const Page& page,
    std::string* buffer) {
  // create a list of drawing operations
  std::vector<DrawOp> ops;
  for (const auto& e : page.text_elements) {
    DrawOp op;
    op.draw_fn = bind(&Rasterizer::drawText, _1, e.glyphs, e.style, e.transform);
    op.draw_idx = e.zindex.value_or(0);
    ops.push_back(op);
  }

  for (const auto& e : page.shape_elements) {
    DrawOp op;
    op.draw_idx = e.zindex.value_or(0);
    op.draw_fn = bind(
        &Rasterizer::drawShape,
        _1,
        e.path,
        e.stroke_style,
        e.fill_color,
        e.clip);

    ops.push_back(op);
  }

  // sort drawing operations
  std::sort(
      ops.begin(),
      ops.end(),
      [] (const auto& a, const auto& b) {
        return a.draw_idx < b.draw_idx;
      });

  // execute drawing operations
  Rasterizer rasterizer(page.width, page.height, page.dpi);
  rasterizer.clear(page.background_color);

  for (const auto& op : ops) {
    if (auto rc = op.draw_fn(&rasterizer); !rc) {
  for (const auto& elem : page.elements) {
    auto rc = std::visit([&rasterizer] (const auto& e) {
      using T = std::decay_t<decltype(e)>;
      if constexpr (std::is_same_v<T, PageTextElement>)
        return rasterizer.drawText(e.glyphs, e.style, e.transform);
      if constexpr (std::is_same_v<T, PageShapeElement>)
        return rasterizer.drawShape(e.path, e.stroke_style, e.fill_color, e.clip);

      return ERROR;
    }, elem);

    if (!rc) {
      return rc;
    }
  }

  // return the image
  *buffer = rasterizer.to_png(); // TODO
  return OK;
}
+12 −28
Original line number Diff line number Diff line
@@ -280,44 +280,28 @@ struct SVGDrawOp {
ReturnCode page_export_svg(
    const Page& page,
    std::string* buffer) {
  // create a list of drawing operations
  std::vector<SVGDrawOp> svg_ops;
  for (const auto& e : page.text_elements) {
    SVGDrawOp svg_op;
    svg_op.draw_fn = bind(&svg_text_span, e, page.dpi, _1);
    svg_op.draw_idx = e.zindex.value_or(0);
    svg_ops.push_back(svg_op);
  }

  for (const auto& e : page.shape_elements) {
    SVGDrawOp svg_op;
    svg_op.draw_fn = bind(&svg_shape, e, _1);
    svg_op.draw_idx = e.zindex.value_or(0);
    svg_ops.push_back(svg_op);
  }

  // sort and execute operations
  std::sort(
      svg_ops.begin(),
      svg_ops.end(),
      [] (const auto& a, const auto& b) {
        return a.draw_idx < b.draw_idx;
      });

  auto svg = std::make_shared<SVGData>();
  svg->width = page.width;
  svg->height = page.height;
  svg->proj = mul(translate2({0, page.height}), scale2({1, -1}));

  for (const auto& op : svg_ops) {
    if (auto rc = op.draw_fn(svg); !rc) {
  for (const auto& elem : page.elements) {
    auto rc = std::visit([svg, &page] (const auto& e) {
      using T = std::decay_t<decltype(e)>;
      if constexpr (std::is_same_v<T, PageTextElement>)
        return svg_text_span(e, page.dpi, svg);
      if constexpr (std::is_same_v<T, PageShapeElement>)
        return svg_shape(e, svg);

      return ERROR;
    }, elem);

    if (!rc) {
      return rc;
    }
  }

  // return the svg document
  std::stringstream svg_doc;

  svg_doc
    << "<svg"
      << svg_attr("xmlns", "http://www.w3.org/2000/svg")
Loading