Commit 8dbb2142 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

delete obsolete svgtarget.h, canvas.h

parent c1be45c9
Loading
Loading
Loading
Loading

src/signaltk/core/canvas.h

deleted100644 → 0
+0 −239
Original line number Diff line number Diff line
/**
 * This file is part of the "libstx" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * libstx is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#ifndef _libstx_CANVAS_H
#define _libstx_CANVAS_H
#include <memory>
#include <vector>
#include <string>
#include <tuple>
#include "cplot/axisdefinition.h"
#include "cplot/drawable.h"
#include "cplot/legenddefinition.h"

namespace signaltk {
namespace chart {
class RenderTarget;

class Canvas {
public:
  static const int kAxisPadding = 0; // FIXPAUL make configurable
  static const int kTickLength = 5; // FIXPAUL make configurable
  static const int kAxisLabelHeight = 25; // FIXPAUL make configurable
  static const int kAxisLabelWidth = 50; // FIXPAUL make configurable
  static const int kAxisTitleLength = 20; // FIXPAUL make configurable
  static const int kCharWidth = 6.0f; // FIXPAUL make configurable
  static const int kTitleLineHeight = 20; // FIXPAUL make configurable
  static const int kSubtitleLineHeight = 20; // FIXPAUL make configurable
  static const int kLegendLabelPadding = 20; // FIXPAUL make configurable
  static const int kLegendLineHeight = 20; // FIXPAUL make configurable
  static const int kLegendInsideVertPadding = 10;
  static const int kLegendInsideHorizPadding = 15;
  static const int kLegendOutsideVertPadding = 10;
  static const int kLegendOutsideHorizPadding = 25;
  static const int kLegendPointY = 6;
  static const int kLegendPointWidth = 8;
  static const int kLegendPointSize = 3;

  Canvas();

  /**
   * Set the title for this canvas
   */
  void setTitle(const std::string& title);

  /**
   * Set the subtitle for this canvas
   */
  void setSubtitle(const std::string& subtitle);

  void setDimensions(int width, int height);

  /**
   * FIXPAUL overcomplicated, just accept a ptr
   *
   * The returned pointer is owned by the canvas instance and must not be freed
   * by the caller.
   */
  template <typename ChartType, typename... Args>
  ChartType* addChart(Args... args) {
    auto drawable = new ChartType(this, args...);
    drawables_.emplace_back(drawable);
    return drawable;
  }

  /**
   * Add an axis to this canvas. Usually axes are not specified manually via
   * this method but through one of the Chart subclasses. However it is safe
   * to call this method to explicitly define a custom axis.
   *
   * The returned pointer is owned by the canvas instance and must not be freed
   * by the caller.
   */
  AxisDefinition* addAxis(AxisDefinition::kPosition position);

  /**
   * Add a leged to this canvas. Usually legends are not specified manually via
   * this method but through one of the Chart subclasses. However it is safe
   * to call this method to explicitly define a custom legend.
   *
   * The returned pointer is owned by the canvas instance and must not be freed
   * by the caller.
   */
  LegendDefinition* addLegend(
      LegendDefinition::kVerticalPosition vert_pos,
      LegendDefinition::kHorizontalPosition horiz_pos,
      LegendDefinition::kPlacement placement,
      const std::string& title);

  /**
   * Add a grid to this canvas. Usually grids are not specified manually via
   * this method but through one of the Chart subclasses. However it is safe
   * to call this method to explicitly define a custom grid.
   *
   * The returned pointer is owned by the canvas instance and must not be freed
   * by the caller.
   */
  GridDefinition* addGrid(GridDefinition::kPlacement placement);

  /**
   * Return the legend or nullptr
   */
  LegendDefinition* legend() const;

  /**
   * Render the contents of this canvas to the provided render target
   *
   * @param target a RenderTarget subclass instance. Does not transfer ownership
   */
  void render(RenderTarget* target) const;

protected:

  // FIXPAUL
  int estimateTextLength(const std::string& str) const {
    return str.size() * kCharWidth;
  }

  /**
   * Render the chart title
   */
  void renderTitle(RenderTarget* target, Viewport* viewport) const;

  /**
   * Render the charts
   */
  void renderCharts(RenderTarget* target, Viewport* viewport) const;

  /**
   * Render the axes
   */
  void renderAxes(RenderTarget* target, Viewport* viewport) const;

  /**
   * Render a top axis
   *
   * @param target the render target
   * @param axis the axis definition
   * @param padding the padding state
   * @param top the top padding for this axis
   */
  void renderTopAxis(
      RenderTarget* target,
      Viewport* viewport,
      AxisDefinition* axis,
      int top) const;

  /**
   * Render a right axis
   *
   * @param target the render target
   * @param axis the axis definition
   * @param padding the padding state
   * @param right the right padding for this axis
   */
  void renderRightAxis(
      RenderTarget* target,
      Viewport* viewport,
      AxisDefinition* axis,
      int right) const;

  /**
   * Render a bottom axis
   *
   * @param target the render target
   * @param axis the axis definition
   * @param padding the padding state
   * @param bottom the bottom padding for this axis
   */
  void renderBottomAxis(
      RenderTarget* target,
      Viewport* viewport,
      AxisDefinition* axis,
      int bottom) const;

  /**
   * Render a left axis
   *
   * @param target the render target
   * @param axis the axis definition
   * @param padding the padding state
   * @param left the left padding for this axis
   */
  void renderLeftAxis(
      RenderTarget* target,
      Viewport* viewport,
      AxisDefinition* axis,
      int left) const;

  /**
   * Render the legends
   */
  void renderOutsideLegends(RenderTarget* target, Viewport* viewport) const;

  /**
   * Render the legends
   */
  void renderInsideLegends(RenderTarget* target, Viewport* viewport) const;

  void renderRightLegend(
      RenderTarget* target,
      Viewport* viewport,
      LegendDefinition* legend,
      double horiz_padding,
      bool bottom,
      bool outside) const;

  void renderLeftLegend(
      RenderTarget* target,
      Viewport* viewport,
      LegendDefinition* legend,
      double horiz_padding,
      bool bottom,
      bool outside) const;

  /**
   * Render the grids
   */
  void renderGrids(RenderTarget* target, Viewport* viewport) const;

  // FIXPAUL this belongs into the rendertarget
  int width_;
  int height_;
  std::vector<std::unique_ptr<AxisDefinition>> axes_;
  std::vector<std::unique_ptr<LegendDefinition>> legends_;
  std::vector<std::unique_ptr<GridDefinition>> grids_;
  std::vector<std::unique_ptr<Drawable>> drawables_;
  std::string title_;
  std::string subtitle_;
};

}
}
#endif

src/signaltk/core/svgtarget.h

deleted100644 → 0
+0 −247
Original line number Diff line number Diff line
/**
 * This file is part of the "libstx" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * libstx is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */

#ifndef _libstx_SVGTARGET_H
#define _libstx_SVGTARGET_H
#include <stdlib.h>
#include <vector>
#include <string>
#include "rendertarget.h"
#include "../plot/styles/style_default.h"
#include "../util/outputstream.h"

namespace signaltk {
namespace chart {

class SVGTarget : public RenderTarget {
public:

  /**
   * Create a new SVG target.
   *
   * @param output_stream the output stream to write to. does not transfer
   *                      ownership!
   */
  SVGTarget(
      OutputStream* output_stream) :
      output_(output_stream),
      viewbox_(true),
      indent_(0) {}

#define SVG_append(...) { output_->printf(__VA_ARGS__); }

#define SVG_appendLine(...) { \
    for(int __i = 0; __i < indent_ * 2; ++__i) SVG_append(" "); \
    SVG_append(__VA_ARGS__); }

  void beginChart(
      int width,
      int height,
      const std::string& class_name) {
    if (viewbox_) {
      SVG_appendLine(
          "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox='0 0 %i %i' class='%s' viewport-fill='white'>\n",
          width,
          height,
          escapeString(class_name).c_str());
    } else {
      SVG_appendLine(
          "<sv xmlns=\"http://www.w3.org/2000/svg\"g width='%i' height='%i' class='%s' viewport-fill='white'>\n",
          width,
          height,
          escapeString(class_name).c_str());
    }

    indent_++;
    SVG_appendLine("<style type='text/css'>\n");
    SVG_appendLine("<![CDATA[%s  ]]>\n", kStyleSheetDefault.c_str());
    SVG_appendLine("</style>\n");
  }

  void finishChart() {
    indent_--;
    SVG_appendLine("</svg>\n");
  }

  void drawRect(
      double x,
      double y,
      double width,
      double height,
      const std::string& color,
      const std::string& class_name,
      const std::string& label,
      const std::string& series) override {
    std::string class_str(class_name);
    class_str += " ";

    std::string style_str;
    if (color.size() > 3 && color.size() < 8 && color[0] == '#') {
      style_str += "fill: " + color + ";";
    } else {
      class_str += color;
    }

    // FIXPAUL escape me
    SVG_appendLine(
        "<rect x='%f' y='%f' width='%f' height='%f' class='%s' "
            "style='%s'></rect>\n",
        x,
        y,
        width,
        height,
        escapeString(class_str).c_str(),
        escapeString(style_str).c_str());
  }

  void drawLine(
      double x1,
      double y1,
      double x2,
      double y2,
      const std::string& class_name) override {
    SVG_appendLine(
        "<line x1='%f' y1='%f' x2='%f' y2='%f' class='%s' />\n",
        x1,
        y1,
        x2,
        y2,
        escapeString(class_name).c_str());
  }

  void drawText(
      const std::string& text,
      double x,
      double y,
      const std::string& halign,
      const std::string& valign,
      const std::string& class_name,
      double rotate = 0.0f) override {
    char transform[256];

    if (rotate == 0.0f) {
      *transform = 0;
    } else {
      snprintf(
          transform,
          sizeof(transform),
          "transform='translate(0,0) rotate(%f %f %f)'",
          rotate,
          x,
          y);
    }

    SVG_appendLine(
        "<text x='%f' y='%f' style='text-anchor:%s; dominant-baseline:%s;' "
            "class='%s' %s>%s</text>\n",
        x,
        y,
        halign.c_str(),
        valign.c_str(),
        escapeString(class_name).c_str(),
        transform,
        escapeString(text).c_str());
  }

  void drawPoint(
      double x,
      double y,
      const std::string& point_type,
      double point_size,
      const std::string& color,
      const std::string& class_name /* = "" */,
      const std::string& label /* = "" */,
      const std::string& series /* = "" */) override {
    std::string class_str(class_name);
    class_str += " ";

    std::string style_str;
    if (color.size() > 3 && color.size() < 8 && color[0] == '#') {
      style_str += "fill: " + color + ";";
    } else {
      class_str += color;
    }

    /* point_type: circle */
    // FIXPAUL escape label
    SVG_appendLine(
        "<circle cx='%f' cy='%f' r='%f' class='%s' style='%s'></circle>\n",
        x,
        y,
        point_type == "none" ? 0 : point_size,
        escapeString(class_str).c_str(),
        escapeString(style_str).c_str());
  }

   void drawPath(
      const std::vector<std::pair<double, double>>& points,
      const std::string& line_style,
      double line_width,
      bool smooth,
      const std::string& color,
      const std::string& class_name = "") override {
    std::string class_str(class_name);
    class_str += " ";

    std::string style_str;
    if (color.size() > 3 && color.size() < 8 && color[0] == '#') {
      style_str += "stroke: " + color + ";";
    } else {
      class_str += color;
    }

    SVG_appendLine(
        "<path stroke-width='%f' class='%s' style='%s' d='",
        line_width,
        escapeString(class_str).c_str(),
        escapeString(style_str).c_str());

    for (int i = 0; i < points.size(); ++i) {
      if (i == 0) {
        SVG_append("M%f %f ", points[i].first, points[i].second);
      } else if (smooth) {
        SVG_append("L%f %f ", points[i].first, points[i].second);
      } else {
        SVG_append("L%f %f ", points[i].first, points[i].second);
      }
    }

    SVG_append("' />\n");
  }

  void beginGroup(const std::string& class_name) override {
    SVG_appendLine("<g class='%s'>\n", escapeString(class_name).c_str());
    indent_++;
  }

  void finishGroup() override {
    indent_--;
    SVG_appendLine("</g>\n");
  }

  // FIXPAUL
  std::string escapeString(const std::string& src) {
    return src;
  }

  void setViewbox(bool vb) {
    viewbox_ = vb;
  }

protected:
  bool viewbox_;
  OutputStream* output_;
  int indent_;
};


}
}
#endif