gsl-shell.git - gsl-shell

index : gsl-shell.git
gsl-shell
summary refs log tree commit diff
path: root/agg-plot
diff options
context:
space:
mode:
Diffstat (limited to 'agg-plot')
-rw-r--r--agg-plot/Makefile 2
-rw-r--r--agg-plot/agg-parse-trans.cpp 5
-rw-r--r--agg-plot/canvas_svg.cpp 42
-rw-r--r--agg-plot/canvas_svg.h 80
-rw-r--r--agg-plot/draw_svg.cpp 63
-rw-r--r--agg-plot/draw_svg.h 95
-rw-r--r--agg-plot/drawable.h 4
-rw-r--r--agg-plot/lua-plot.cpp 28
-rw-r--r--agg-plot/lua-text.cpp 2
-rw-r--r--agg-plot/my_list.h 2
-rw-r--r--agg-plot/plot.h 147
-rw-r--r--agg-plot/scalable.h 24
-rw-r--r--agg-plot/strpp.h 48
-rw-r--r--agg-plot/text.cpp 67
-rw-r--r--agg-plot/text.h 54
-rw-r--r--agg-plot/trans.h 98
16 files changed, 632 insertions, 129 deletions
diff --git a/agg-plot/Makefile b/agg-plot/Makefile
index 047ddce5..8e40ee19 100644
--- a/agg-plot/Makefile
+++ b/agg-plot/Makefile
@@ -36,7 +36,7 @@ endif
INCLUDES += $(AGG_INCLUDES) -I$(GSH_BASE_DIR) -I$(LUADIR)/src
-AGGPLOT_SRC_FILES = $(PLATSUP_SRC_FILES) utils.cpp units.cpp colors.cpp markers.cpp lua-draw.cpp lua-text.cpp text.cpp agg-parse-trans.cpp window_registry.cpp window.cpp lua-plot.cpp canvas-window.cpp bitmap-plot.cpp
+AGGPLOT_SRC_FILES = $(PLATSUP_SRC_FILES) utils.cpp units.cpp colors.cpp markers.cpp draw_svg.cpp canvas_svg.cpp lua-draw.cpp lua-text.cpp text.cpp agg-parse-trans.cpp window_registry.cpp window.cpp lua-plot.cpp canvas-window.cpp bitmap-plot.cpp
AGGPLOT_OBJ_FILES := $(AGGPLOT_SRC_FILES:%.cpp=%.o)
diff --git a/agg-plot/agg-parse-trans.cpp b/agg-plot/agg-parse-trans.cpp
index 24bfd33e..8578b01b 100644
--- a/agg-plot/agg-parse-trans.cpp
+++ b/agg-plot/agg-parse-trans.cpp
@@ -81,7 +81,7 @@ typename context::base_type* build_stroke (lua_State *L, int specindex, typename
typename trans<context>::stroke_base& stroke = s->self();
- stroke.width(width);
+ s->width(width);
if (cap_str)
{
@@ -122,7 +122,6 @@ build_dash (lua_State *L, int specindex, typename context::base_type *obj)
typedef typename trans<context>::dash dash_type;
dash_type *d = new dash_type(obj);
- typename trans<context>::dash_base& dash = d->self();
for (int j = 2; /* */; j += 2)
{
@@ -137,7 +136,7 @@ build_dash (lua_State *L, int specindex, typename context::base_type *obj)
double b = (lua_isnumber (L, -1) ? lua_tonumber (L, -1) : a);
- dash.add_dash(a, b);
+ d->add_dash(a, b);
lua_pop (L,1);
}
else
diff --git a/agg-plot/canvas_svg.cpp b/agg-plot/canvas_svg.cpp
new file mode 100644
index 00000000..d8f05cb9
--- /dev/null
+++ b/agg-plot/canvas_svg.cpp
@@ -0,0 +1,42 @@
+#include "canvas_svg.h"
+
+const double canvas_svg::default_stroke_width = 1.0;
+
+static void canvas_draw_svg(svg_vs* vs, FILE* f, int id, agg::rgba8 c)
+{
+ str s = vs->write_svg(id, c);
+ canvas_svg::writeln(f, s, " ");
+}
+
+static void canvas_draw_outline_svg(svg_vs* vs, FILE* f, int id, agg::rgba8 c)
+{
+ str path;
+ svg_property_list* ls = vs->svg_path(path);
+ str s = svg_stroke_path(path, canvas_svg::default_stroke_width, id, c, ls);
+ list::free(ls);
+ canvas_svg::writeln(f, s, " ");
+}
+
+template <>
+void canvas_svg::draw<svg_vs>(svg_vs& vs, agg::rgba8 c)
+{
+ canvas_draw_svg(&vs, m_output, m_current_id++, c);
+}
+
+template <>
+void canvas_svg::draw_outline<svg_vs>(svg_vs& vs, agg::rgba8 c)
+{
+ canvas_draw_outline_svg(&vs, m_output, m_current_id++, c);
+}
+
+template <>
+void canvas_svg::draw<drawable>(drawable& vs, agg::rgba8 c)
+{
+ canvas_draw_svg(&vs, m_output, m_current_id++, c);
+}
+
+template <>
+void canvas_svg::draw_outline<drawable>(drawable& vs, agg::rgba8 c)
+{
+ canvas_draw_outline_svg(&vs, m_output, m_current_id++, c);
+}
diff --git a/agg-plot/canvas_svg.h b/agg-plot/canvas_svg.h
new file mode 100644
index 00000000..b5d70332
--- /dev/null
+++ b/agg-plot/canvas_svg.h
@@ -0,0 +1,80 @@
+#ifndef CANVAS_SVG_H
+#define CANVAS_SVG_H
+
+#include <stdio.h>
+
+#include <agg_trans_affine.h>
+#include <agg_color_rgba.h>
+
+#include "defs.h"
+#include "strpp.h"
+#include "drawable.h"
+#include "draw_svg.h"
+
+static const char *svg_header = \
+ "<?xml version=\"1.0\" standalone=\"no\"?>\n" \
+ "<svg\n" \
+ " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n" \
+ " xmlns:cc=\"http://creativecommons.org/ns#\"\n" \
+ " xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" \
+ " xmlns:svg=\"http://www.w3.org/2000/svg\"\n" \
+ " xmlns=\"http://www.w3.org/2000/svg\"\n" \
+ " version=\"1.1\"\n" \
+ " width=\"%g\"\n" \
+ " height=\"%g\"\n" \
+ " id=\"svg2\">\n" \
+ " <g id=\"layer1\" font-family=\"Helvetica\">\n";
+
+static const char *svg_end = " </g>\n" "</svg>\n";
+
+class canvas_svg {
+public:
+ canvas_svg(FILE *f) : m_output(f), m_current_id(0) { }
+
+ void clip_box(const agg::rect_base<int>& clip) { }
+
+ void reset_clipping() { }
+
+ template <class VertexSource>
+ void draw(VertexSource& vs, agg::rgba8 c)
+ {
+ str path;
+ svg_coords_from_vs(&vs, path);
+ str s = svg_fill_path(path, m_current_id++, c);
+ writeln(m_output, s, " ");
+ }
+
+ template <class VertexSource>
+ void draw_outline(VertexSource& vs, agg::rgba8 c)
+ {
+ str path;
+ svg_coords_from_vs(&vs, path);
+ str s = svg_stroke_path(path, default_stroke_width, m_current_id++, c);
+ writeln(m_output, s, " ");
+ }
+
+ void write_header(double w, double h) { fprintf(m_output, svg_header, w, h); }
+ void write_end() { fputs(svg_end, m_output); }
+
+ static void writeln(FILE* f, str& s, const char* indent = 0) {
+ if (str_is_null(&s))
+ return;
+ if (indent)
+ fputs(indent, f);
+ fprintf(f, "%s\n", s.cstr());
+ }
+
+ static const double default_stroke_width;
+
+private:
+ FILE *m_output;
+ int m_current_id;
+};
+
+template <> void canvas_svg::draw<svg_vs>(svg_vs& vs, agg::rgba8 c);
+template <> void canvas_svg::draw_outline<svg_vs>(svg_vs& vs, agg::rgba8 c);
+
+template <> void canvas_svg::draw<drawable>(drawable& vs, agg::rgba8 c);
+template <> void canvas_svg::draw_outline<drawable>(drawable& vs, agg::rgba8 c);
+
+#endif
diff --git a/agg-plot/draw_svg.cpp b/agg-plot/draw_svg.cpp
new file mode 100644
index 00000000..a86da5b1
--- /dev/null
+++ b/agg-plot/draw_svg.cpp
@@ -0,0 +1,63 @@
+#include "agg_color_rgba.h"
+
+#include "draw_svg.h"
+
+const char *svg_path_property_name[] = {"stroke-dasharray"};
+
+void format_rgb(char rgbstr[], agg::rgba8 c)
+{
+ sprintf(rgbstr, "#%02X%02X%02X", (int)c.r, (int)c.g, (int)c.b);
+}
+
+static void append_properties(str& s, svg_property_list* properties)
+{
+ for (svg_property_list* p = properties; p; p = p->next())
+ {
+ svg_property_item& item = p->content();
+ const char* name = svg_path_property_name[item.key];
+ s.printf_add(";%s:%s", name, item.value);
+ }
+}
+
+str svg_stroke_path(str& path_coords, double width, int id, agg::rgba8 c,
+ svg_property_list* properties)
+{
+ char rgbstr[8];
+ format_rgb(rgbstr, c);
+
+ str s = str::print("<path d=\"%s\" "
+ "id=\"path%i\" "
+ "style=\"fill:none;stroke:%s;"
+ "stroke-width:%gpx;stroke-linecap:butt;"
+ "stroke-linejoin:miter",
+ path_coords.cstr(), id, rgbstr, width);
+
+ if (c.a < 255) {
+ double alpha = (double)c.a / 255;
+ s.printf_add(";stroke-opacity:%g", alpha);
+ }
+
+ append_properties(s, properties);
+ s.append("\" />");
+
+ return s;
+}
+
+str svg_fill_path(str& path_coords, int id, agg::rgba8 c,
+ svg_property_list* properties)
+{
+ char rgbstr[8];
+ format_rgb(rgbstr, c);
+
+ double alpha = (double)c.a / 255;
+
+ str s = str::print("<path d=\"%s\" "
+ "id=\"path%i\" "
+ "style=\"fill:%s;fill-opacity:%g;stroke:none\" />",
+ path_coords.cstr(), id, rgbstr, alpha);
+
+ append_properties(s, properties);
+ s.append("\" />");
+
+ return s;
+}
diff --git a/agg-plot/draw_svg.h b/agg-plot/draw_svg.h
new file mode 100644
index 00000000..b5fe7889
--- /dev/null
+++ b/agg-plot/draw_svg.h
@@ -0,0 +1,95 @@
+#ifndef DRAW_SVG_H
+#define DRAW_SVG_H
+
+#include "agg_basics.h"
+#include "agg_color_rgba.h"
+#include "my_list.h"
+#include "strpp.h"
+
+enum svg_path_property_e {
+ stroke_dasharray = 0,
+};
+
+extern const char *svg_path_property_name[];
+
+struct svg_property_item {
+ enum svg_path_property_e key;
+ const char* value;
+
+ svg_property_item(enum svg_path_property_e k, const char *v) : key(k), value(v) { }
+};
+
+typedef pod_list<svg_property_item> svg_property_list;
+
+template <typename VertexSource>
+void svg_coords_from_vs(VertexSource* vs, str& s)
+{
+ unsigned cmd;
+ double x, y;
+ const char * const space = " ";
+ const char *sep = "";
+
+ vs->rewind(0);
+
+ while ((cmd = vs->vertex(&x, &y)))
+ {
+ if (agg::is_move_to(cmd)) {
+ s.printf_add("%sM %g,%g", sep, x, y);
+ } else if (agg::is_line_to(cmd)) {
+ s.printf_add("%s%g,%g", sep, x, y);
+ } else if (agg::is_close(cmd)) {
+ s.printf_add("%sz", sep);
+ } else if (agg::is_curve3(cmd)) {
+ vs->vertex(&x, &y);
+ s.printf_add("%s%g,%g", sep, x, y);
+ } else if (agg::is_curve4(cmd)) {
+ vs->vertex(&x, &y);
+ vs->vertex(&x, &y);
+ s.printf_add("%s%g,%g", sep, x, y);
+ }
+ sep = space;
+ }
+}
+
+template <typename VertexSource>
+void svg_curve_coords_from_vs(VertexSource* vs, str& s)
+{
+ unsigned cmd;
+ double x, y;
+ const char * const space = " ";
+ const char *sep = "";
+ bool omit_line_to = false;
+
+ vs->rewind(0);
+
+ while ((cmd = vs->vertex(&x, &y)))
+ {
+ if (agg::is_move_to(cmd)) {
+ s.printf_add("%sM %g,%g", sep, x, y);
+ omit_line_to = true;
+ } else if (agg::is_line_to(cmd)) {
+ s.printf_add("%s%s%g,%g", sep, omit_line_to ? "" : "L ", x, y);
+ } else if (agg::is_curve4(cmd)) {
+ double x1 = x, y1 = y;
+ double x2, y2;
+ vs->vertex(&x2, &y2);
+ vs->vertex(&x, &y);
+ s.printf_add("%sC %g,%g %g,%g %g,%g", sep, x1, y1, x2, x2, x, y);
+ omit_line_to = false;
+ } else if (agg::is_curve3(cmd)) {
+ double x1 = x, y1 = y;
+ vs->vertex(&x, &y);
+ s.printf_add("%sQ %g,%g %g,%g", sep, x1, y1, x, y);
+ omit_line_to = false;
+ } else if (agg::is_close(cmd)) {
+ s.printf_add("%sz", sep);
+ }
+ sep = space;
+ }
+}
+
+extern str svg_stroke_path(str& path_coords, double width, int id, agg::rgba8 c, svg_property_list* properties = 0);
+extern str svg_fill_path(str& path_coords, int id, agg::rgba8 c, svg_property_list* properties = 0);
+extern void format_rgb(char rgbstr[], agg::rgba8 c);
+
+#endif
diff --git a/agg-plot/drawable.h b/agg-plot/drawable.h
index a4fb7df6..d3ddfa82 100644
--- a/agg-plot/drawable.h
+++ b/agg-plot/drawable.h
@@ -7,6 +7,7 @@
#include "agg_trans_affine.h"
#include "agg_conv_transform.h"
#include "agg_bounding_rect.h"
+#include "agg_color_rgba.h"
struct drawable : public vertex_source {
virtual void bounding_box(double *x1, double *y1, double *x2, double *y2) = 0;
@@ -25,6 +26,9 @@ class boxed_drawable : public drawable {
virtual unsigned vertex(double* x, double* y) { return m_object->vertex(x, y); };
virtual void apply_transform(const agg::trans_affine& m, double as) { m_object->apply_transform(m, as); };
+ virtual str write_svg(int id, agg::rgba8 c) { return m_object->write_svg(id, c); }
+ virtual svg_property_list* svg_path(str& s) { return m_object->svg_path(s); }
+
virtual void bounding_box(double *x1, double *y1, double *x2, double *y2)
{
m_object->bounding_box(x1, y1, x2, y2);
diff --git a/agg-plot/lua-plot.cpp b/agg-plot/lua-plot.cpp
index d953ac50..b1bf2a75 100644
--- a/agg-plot/lua-plot.cpp
+++ b/agg-plot/lua-plot.cpp
@@ -38,6 +38,7 @@ extern "C" {
#include "drawable.h"
#include "resource-manager.h"
#include "agg-parse-trans.h"
+#include "canvas_svg.h"
__BEGIN_DECLS
@@ -58,6 +59,7 @@ static int plot_set_limits (lua_State *L);
static int plot_push_layer (lua_State *L);
static int plot_pop_layer (lua_State *L);
static int plot_clear (lua_State *L);
+static int plot_save_svg (lua_State *L);
static int plot_sync_mode_get (lua_State *L);
static int plot_sync_mode_set (lua_State *L);
@@ -95,6 +97,7 @@ static const struct luaL_Reg plot_methods[] = {
{"poplayer", plot_pop_layer },
{"clear", plot_clear },
{"save", bitmap_save_image },
+ {"save_svg", plot_save_svg },
{NULL, NULL}
};
@@ -421,6 +424,31 @@ plot_clear (lua_State *L)
return 0;
}
+int
+plot_save_svg (lua_State *L)
+{
+ lua_plot *p = object_check<lua_plot>(L, 1, GS_PLOT);
+ const char *filename = lua_tostring(L, 2);
+ double w = luaL_optnumber(L, 3, 800.0);
+ double h = luaL_optnumber(L, 4, 600.0);
+
+ if (!filename)
+ return gs_type_error(L, 2, "string");
+
+ FILE* f = fopen(filename, "w");
+ if (!f)
+ return luaL_error(L, "cannot open filename: %s", filename);
+
+ canvas_svg canvas(f);
+ agg::trans_affine m(w, 0.0, 0.0, -h, 0.0, h);
+ canvas.write_header(w, h);
+ p->draw(canvas, m);
+ canvas.write_end();
+ fclose(f);
+
+ return 0;
+}
+
static int plot_pad_mode_set (lua_State *L)
{
lua_plot *p = object_check<lua_plot>(L, 1, GS_PLOT);
diff --git a/agg-plot/lua-text.cpp b/agg-plot/lua-text.cpp
index 065211a7..91a606bc 100644
--- a/agg-plot/lua-text.cpp
+++ b/agg-plot/lua-text.cpp
@@ -66,7 +66,7 @@ int
agg_text_new (lua_State *L)
{
double size = luaL_optnumber (L, 1, 10.0);
- double width = luaL_optnumber (L, 2, 1.0);
+ double width = luaL_optnumber (L, 2, 1.0) + 0.7;
new(L, GS_DRAW_TEXT) draw::text(size, width);
return 1;
}
diff --git a/agg-plot/my_list.h b/agg-plot/my_list.h
index fdaebb72..12880d69 100644
--- a/agg-plot/my_list.h
+++ b/agg-plot/my_list.h
@@ -46,7 +46,7 @@ namespace list {
pod_list<T> *n;
for (/* */; p; p = n)
{
- n = p->m_next;
+ n = p->next();
delete p;
}
}
diff --git a/agg-plot/plot.h b/agg-plot/plot.h
index 53348c1b..67507494 100644
--- a/agg-plot/plot.h
+++ b/agg-plot/plot.h
@@ -25,12 +25,16 @@
#include "utils.h"
#include "my_list.h"
+#include "strpp.h"
#include "drawable.h"
#include "canvas.h"
#include "units.h"
#include "resource-manager.h"
#include "colors.h"
#include "rect.h"
+#include "canvas_svg.h"
+#include "trans.h"
+#include "text.h"
#include "agg_array.h"
#include "agg_bounding_rect.h"
@@ -72,14 +76,10 @@ public:
m_root_layer(), m_layers(), m_current_layer(&m_root_layer),
m_drawing_queue(0), m_clip_flag(true),
m_need_redraw(true), m_rect(),
- m_use_units(use_units), m_pad_units(false), m_title_buf(),
+ m_use_units(use_units), m_pad_units(false), m_title(),
m_sync_mode(true)
{
compute_user_trans();
-
- m_title_buf.capacity(32);
- m_title = m_title_buf.data();
- m_title[0] = '0円';
};
virtual ~plot()
@@ -94,7 +94,7 @@ public:
};
void set_title(const char *text);
- const char *title() const { return m_title; };
+ const char *title() const { return m_title.cstr(); };
void set_units(bool use_units);
bool use_units() const { return m_use_units; };
@@ -104,7 +104,8 @@ public:
virtual void add(vertex_source* vs, agg::rgba8& color, bool outline);
virtual void before_draw() { };
- void draw(canvas &canvas, agg::trans_affine& m);
+ template <class Canvas>
+ void draw(Canvas &canvas, agg::trans_affine& m);
virtual bool push_layer();
virtual bool pop_layer();
@@ -139,14 +140,21 @@ public:
bool pad_mode() { return m_pad_units; };
protected:
- void draw_elements(canvas &canvas, agg::trans_affine& m);
- void draw_element(item& c, canvas &canvas, agg::trans_affine& m);
- void draw_title(canvas& canvas, agg::trans_affine& m);
- void draw_axis(canvas& can, agg::trans_affine& m);
+ template <typename Canvas>
+ void draw_elements(Canvas &canvas, agg::trans_affine& m);
+
+ template <typename Canvas>
+ void draw_element(item& c, Canvas &canvas, agg::trans_affine& m);
+
+ template <typename Canvas>
+ void draw_title(Canvas& canvas, agg::trans_affine& m);
+
+ template <typename Canvas>
+ void draw_axis(Canvas& can, agg::trans_affine& m);
agg::trans_affine get_scaled_matrix(agg::trans_affine& canvas_mtx);
- void clip_plot_area(canvas &canvas, agg::trans_affine& canvas_mtx);
+ template <class Canvas> void clip_plot_area(Canvas &canvas, agg::trans_affine& canvas_mtx);
void compute_user_trans();
@@ -176,15 +184,14 @@ protected:
private:
bool m_pad_units;
- agg::pod_vector<char> m_title_buf;
- char *m_title;
+ str m_title;
bool m_sync_mode;
};
static double
compute_scale(agg::trans_affine& m) {
- return min(m.sy, m.sx) / 480.0;
+ return min(fabs(m.sy), fabs(m.sx)) / 480.0;
}
static double
@@ -218,10 +225,7 @@ void plot<VS,RM>::add(VS* vs, agg::rgba8& color, bool outline)
template <class VS, class RM>
void plot<VS,RM>::set_title(const char *text)
{
- unsigned int len = strlen(text);
- m_title_buf.resize(len+1);
- m_title = m_title_buf.data();
- memcpy (m_title, text, len+1);
+ str_copy_c(&m_title, text);
}
template <class VS, class RM>
@@ -248,7 +252,7 @@ void plot<VS,RM>::clear_drawing_queue()
}
template <class VS, class RM>
-void plot<VS,RM>::draw(canvas &canvas, agg::trans_affine& canvas_mtx)
+template <class Canvas> void plot<VS,RM>::draw(Canvas &canvas, agg::trans_affine& canvas_mtx)
{
before_draw();
draw_title(canvas, canvas_mtx);
@@ -258,9 +262,9 @@ void plot<VS,RM>::draw(canvas &canvas, agg::trans_affine& canvas_mtx)
};
template <class VS, class RM>
-void plot<VS,RM>::draw_title(canvas &canvas, agg::trans_affine& canvas_mtx)
+template <class Canvas> void plot<VS,RM>::draw_title(Canvas &canvas, agg::trans_affine& canvas_mtx)
{
- double xt = 0.5, yt = 1;
+ double xt = 0.5, yt = 1.05;
agg::trans_affine m;
this->viewport_scale(m);
@@ -268,27 +272,17 @@ void plot<VS,RM>::draw_title(canvas &canvas, agg::trans_affine& canvas_mtx)
double scale = compute_scale(canvas_mtx);
- agg::gsv_text title;
- agg::conv_stroke<agg::gsv_text> titlestroke(title);
-
- title.size(12.0 * scale);
- title.text(m_title);
-
- titlestroke.width(std_line_width(scale));
- titlestroke.line_cap(agg::round_cap);
- titlestroke.line_join(agg::round_join);
+ draw::text title(12.0 * scale, std_line_width(scale));
+ title.set_text(m_title.cstr());
+ title.hjustif(0.5);
+ title.set_point(xt, yt);
+ title.apply_transform(m, 1.0);
- m.transform(&xt, &yt);
-
- xt += -title.text_width() / 2;
- yt += 10.0 * scale;
-
- title.start_point(xt, yt);
- canvas.draw(titlestroke, agg::rgba(0, 0, 0));
+ canvas.draw(*(drawable *) &title, agg::rgba(0, 0, 0));
}
template<class VS, class RM>
-void plot<VS,RM>::draw_element(item& c, canvas &canvas, agg::trans_affine& m)
+template <class Canvas> void plot<VS,RM>::draw_element(item& c, Canvas &canvas, agg::trans_affine& m)
{
VS& vs = c.vertex_source();
vs.apply_transform(m, 1.0);
@@ -309,7 +303,7 @@ agg::trans_affine plot<VS,RM>::get_scaled_matrix(agg::trans_affine& canvas_mtx)
}
template<class VS, class RM>
-void plot<VS,RM>::clip_plot_area(canvas &canvas, agg::trans_affine& canvas_mtx)
+template <class Canvas> void plot<VS,RM>::clip_plot_area(Canvas &canvas, agg::trans_affine& canvas_mtx)
{
if (this->clip_is_active())
{
@@ -322,7 +316,7 @@ void plot<VS,RM>::clip_plot_area(canvas &canvas, agg::trans_affine& canvas_mtx)
}
template<class VS, class RM>
-void plot<VS,RM>::draw_elements(canvas &canvas, agg::trans_affine& canvas_mtx)
+template <class Canvas> void plot<VS,RM>::draw_elements(Canvas &canvas, agg::trans_affine& canvas_mtx)
{
agg::trans_affine m = get_scaled_matrix(canvas_mtx);
@@ -400,7 +394,7 @@ void plot<VS,RM>::compute_user_trans()
}
template <class VS, class RM>
-void plot<VS,RM>::draw_axis(canvas &canvas, agg::trans_affine& canvas_mtx)
+template <class Canvas> void plot<VS,RM>::draw_axis(Canvas &canvas, agg::trans_affine& canvas_mtx)
{
typedef agg::path_storage path_type;
typedef agg::conv_dash<agg::conv_transform<path_type>, agg::vcgen_markers_term> dash_type;
@@ -420,12 +414,15 @@ void plot<VS,RM>::draw_axis(canvas &canvas, agg::trans_affine& canvas_mtx)
agg::path_storage ln;
agg::conv_transform<path_type> lntr(ln, m);
- dash_type lndash(lntr);
- agg::conv_stroke<dash_type> lns(lndash);
+ svg_proxy<agg::conv_transform<path_type> > lntrsvg(&lntr);
+ trans<svg_context>::dash lndashsvg(&lntrsvg);
+ trans<svg_context>::stroke lns(&lndashsvg);
const double yeps = 1.0e-3;
const double xeps = 1.0e-3;
+ double line_width = std_line_width(scale);
+
{
int jinf = m_uy.begin(), jsup = m_uy.end();
for (int j = jinf; j <= jsup; j++)
@@ -434,32 +431,26 @@ void plot<VS,RM>::draw_axis(canvas &canvas, agg::trans_affine& canvas_mtx)
this->m_trans.transform(&x, &y);
if (y >= - yeps && y <= 1.0 + yeps)
{
- agg::gsv_text lab;
- agg::conv_stroke<agg::gsv_text> labs(lab);
+ draw::text label(12.0 * scale, line_width);
char lab_text[32];
- double xlab = 0, ylab = y;
- lab.size(12.0 * scale);
m_uy.mark_label(lab_text, 32, j);
- lab.text(lab_text);
- labs.width(std_line_width(scale));
+ label.set_text(lab_text);
- m.transform(&xlab, &ylab);
+ label.hjustif(1.0);
+ label.vjustif(0.5);
+ label.set_point(-0.02, y);
+ label.apply_transform(m, 1.0);
- xlab += -lab.text_width() - 10.0 * scale;
- ylab += -5.0 * scale;
-
- lab.start_point(xlab, ylab);
- canvas.draw(labs, agg::rgba(0, 0, 0));
+ canvas.draw(*(drawable *) &label, agg::rgba(0, 0, 0));
mark.move_to(0.0, y);
mark.line_to(-0.01, y);
- if (j > jinf && j < jsup)
- {
- ln.move_to(0.0, y);
- ln.line_to(1.0, y);
- }
+ if (j > jinf && j < jsup) {
+ ln.move_to(0.0, y);
+ ln.line_to(1.0, y);
+ }
}
}
}
@@ -468,44 +459,38 @@ void plot<VS,RM>::draw_axis(canvas &canvas, agg::trans_affine& canvas_mtx)
int jinf = m_ux.begin(), jsup = m_ux.end();
for (int j = jinf; j <= jsup; j++)
{
- double x = m_ux.mark_value(j), y = m_uy.mark_value(j);
+ double x = m_ux.mark_value(j), y = 0.0;
this->m_trans.transform(&x, &y);
if (x >= - xeps && x <= 1.0 + xeps)
{
- agg::gsv_text lab;
- agg::conv_stroke<agg::gsv_text> labs(lab);
+ draw::text label(12.0 * scale, line_width);
char lab_text[32];
- double xlab = x, ylab = 0;
- lab.size(12.0 * scale);
m_ux.mark_label(lab_text, 32, j);
- lab.text(lab_text);
- labs.width(std_line_width(scale));
-
- m.transform(&xlab, &ylab);
+ label.set_text(lab_text);
- xlab += -lab.text_width()/2.0;
- ylab += -24.0 * scale;
+ label.hjustif(0.5);
+ label.vjustif(1.6);
+ label.set_point(x, 0);
+ label.apply_transform(m, 1.0);
- lab.start_point(xlab, ylab);
- canvas.draw(labs, agg::rgba(0, 0, 0));
+ canvas.draw(*(drawable *) &label, agg::rgba(0, 0, 0));
mark.move_to(x, 0.0);
mark.line_to(x, -0.01);
- if (j > jinf && j < jsup)
- {
- ln.move_to(x, 0.0);
- ln.line_to(x, 1.0);
- }
+ if (j > jinf && j < jsup) {
+ ln.move_to(x, 0.0);
+ ln.line_to(x, 1.0);
+ }
}
}
}
- lndash.add_dash(7.0, 3.0);
+ lndashsvg.add_dash(7.0, 3.0);
lns.width(std_line_width(scale, 0.25));
- canvas.draw(lns, colors::black);
+ canvas.draw(*(svg_vs *) &lns, colors::black);
mark_stroke.width(std_line_width(scale, 0.75));
canvas.draw(mark_stroke, colors::black);
diff --git a/agg-plot/scalable.h b/agg-plot/scalable.h
index 745323da..29002645 100644
--- a/agg-plot/scalable.h
+++ b/agg-plot/scalable.h
@@ -22,12 +22,34 @@
#define AGGPLOT_SCALABLE_H
#include "agg_trans_affine.h"
+#include "draw_svg.h"
+#include "strpp.h"
+
+struct svg_vs {
-struct vertex_source {
virtual void rewind(unsigned path_id) = 0;
virtual unsigned vertex(double* x, double* y) = 0;
+
+ virtual str write_svg(int id, agg::rgba8 c) {
+ str path;
+ svg_property_list* ls = this->svg_path(path);
+ str s = svg_fill_path(path, id, c, ls);
+ list::free(ls);
+ return s;
+ }
+
+ virtual svg_property_list* svg_path(str& s) {
+ svg_coords_from_vs(this, s);
+ return 0;
+ }
+
+ virtual ~svg_vs() { }
+};
+
+struct vertex_source : public svg_vs {
virtual void apply_transform(const agg::trans_affine& m, double as) = 0;
virtual bool affine_compose(agg::trans_affine& m) { return false; };
+
virtual ~vertex_source() { };
};
diff --git a/agg-plot/strpp.h b/agg-plot/strpp.h
new file mode 100644
index 00000000..f1fdfe80
--- /dev/null
+++ b/agg-plot/strpp.h
@@ -0,0 +1,48 @@
+#ifndef STRPP_H
+#define STRPP_H
+
+#include "str.h"
+
+class str : public _str {
+public:
+ str(int sz = 64) { str_init(this, sz); }
+ str(const char *s) { str_init_from_c(this, s); }
+ str(const str& s) { str_init_from_str(this, &s); }
+
+ ~str() { str_free(this); }
+
+ const str& operator = (const str& s) {
+ str_copy(this, &s);
+ return *this;
+ }
+
+ const char* cstr() const { return CSTR(this); }
+
+ void append(const str& s, int sep = 0) { str_append(this, &s, sep); }
+ void append(const char* s, int sep = 0) { str_append_c(this, s, sep); }
+
+ void printf(const char* fmt, ...) {
+ va_list ap;
+ va_start (ap, fmt);
+ str_vprintf (this, fmt, 0, ap);
+ va_end (ap);
+ }
+
+ void printf_add(const char* fmt, ...) {
+ va_list ap;
+ va_start (ap, fmt);
+ str_vprintf (this, fmt, 1, ap);
+ va_end (ap);
+ }
+
+ static str print(const char* fmt, ...) {
+ va_list ap;
+ va_start (ap, fmt);
+ str s;
+ str_vprintf (&s, fmt, 0, ap);
+ va_end (ap);
+ return s;
+ }
+};
+
+#endif
diff --git a/agg-plot/text.cpp b/agg-plot/text.cpp
index b1935d1b..1a382c37 100644
--- a/agg-plot/text.cpp
+++ b/agg-plot/text.cpp
@@ -1,4 +1,6 @@
+#include "agg_trans_affine.h"
+
#include "text.h"
namespace draw {
@@ -19,13 +21,17 @@ namespace draw {
void
text::apply_transform(const agg::trans_affine& m, double as)
{
- double& x = m_matrix.tx;
- double& y = m_matrix.ty;
+ m_user_matrix.tx = m_x;
+ m_user_matrix.ty = m_y;
+
+ m.transform(&m_user_matrix.tx, &m_user_matrix.ty);
- x = m_x;
- y = m_y;
+ m_matrix = m_user_matrix;
- m.transform(&x, &y);
+ if (m.sy < 0.0) {
+ m_matrix.shy *= -1.0;
+ m_matrix.sy *= -1.0;
+ }
m_stroke.approximation_scale(as);
}
@@ -36,4 +42,55 @@ namespace draw {
*x1 = *x2 = m_x;
*y1 = *y2 = m_y;
}
+
+ str
+ text::write_svg(int id, agg::rgba8 c)
+ {
+ const agg::trans_affine& m = m_user_matrix;
+ const double eps = 1.0e-6;
+ str s;
+
+ if (str_is_null(&m_text_buf))
+ return s;
+
+ str style;
+ int hjust = lrint(m_hjustif * 2.0);
+ if (hjust == 1)
+ style.append(";text-anchor:middle");
+ else if (hjust >= 2)
+ style.append(";text-anchor:end");
+
+ if (c.r != 0 || c.g != 0 || c.b != 0) {
+ char rgbstr[8];
+ format_rgb(rgbstr, c);
+ style.printf_add(";fill:%s", rgbstr);
+ }
+
+ bool need_rotate = (fabs(m.sx - 1.0) > eps || fabs(m.shx) > eps || \
+ fabs(m.shy) > eps || fabs(m.sy - 1.0) > eps);
+
+ int txt_size = (int)(m_text_height * 1.5);
+
+ double x = 0.0, y = m_vjustif * m_text_height * 1.2;
+ if (!need_rotate) {
+ x += m.tx;
+ y += m.ty;
+ }
+
+ const char* cont = m_text_buf.cstr();
+ str txt = str::print("<text x=\"%g\" y=\"%g\" id=\"text%i\"" \
+ " style=\"font-size:%i%s\">" \
+ " <tspan x=\"%g\" y=\"%g\" id=\"tspan%i\">%s</tspan>" \
+ "</text>",
+ x, y, id, txt_size, style.cstr(), x, y, id, cont);
+
+ if (need_rotate) {
+ s = str::print("<g transform=\"matrix(%g,%g,%g,%g,%g,%g)\">%s</g>",
+ m.sx, m.shx, m.shy, m.sy, m.tx, m.ty, txt.cstr());
+ } else {
+ s = txt;
+ }
+
+ return s;
+ }
}
diff --git a/agg-plot/text.h b/agg-plot/text.h
index 7988fda7..20f56121 100644
--- a/agg-plot/text.h
+++ b/agg-plot/text.h
@@ -16,12 +16,13 @@ namespace draw {
typedef agg::conv_stroke<vs_trans_text> vs_stroked_text;
agg::trans_affine m_matrix;
+ agg::trans_affine m_user_matrix;
vs_text m_text;
vs_trans_text m_trans;
vs_stroked_text m_stroke;
- agg::pod_vector<char> m_text_buf;
+ str m_text_buf;
double m_x, m_y;
double m_angle;
@@ -34,63 +35,52 @@ namespace draw {
public:
text(double size = 10.0, double width = 1.0):
- m_matrix(), m_text(), m_trans(m_text, m_matrix), m_stroke(m_trans),
+ m_matrix(), m_user_matrix(),
+ m_text(), m_trans(m_text, m_matrix), m_stroke(m_trans),
m_text_buf(), m_x(0.0), m_y(0.0), m_angle(0.0),
m_text_width(0.0), m_text_height(size),
m_hjustif(0.0), m_vjustif(0.0)
{
- m_text_buf.capacity(32);
- m_text_buf[0] = '0円';
-
- m_stroke.width(width + 0.5);
- m_stroke.line_cap(agg::round_cap);
- m_stroke.line_join(agg::round_join);
+ m_stroke.width(width);
m_text.size(size);
- };
+ }
- void angle(double th)
- {
+ void angle(double th) {
double c = cos(th), s = sin(th);
m_angle = th;
- m_matrix.sx = c;
- m_matrix.shx = -s;
- m_matrix.shy = s;
- m_matrix.sy = c;
- };
+ m_user_matrix.sx = c;
+ m_user_matrix.shx = -s;
+ m_user_matrix.shy = s;
+ m_user_matrix.sy = c;
+ }
double angle() const { return m_angle; };
- void set_text(const char *txt)
- {
- size_t len = strlen (txt);
- m_text_buf.capacity(len+1);
- memcpy (m_text_buf.data(), txt, len+1);
-
+ void set_text(const char *txt) {
+ str_copy_c(&m_text_buf, txt);
m_text.text(txt);
m_text_width = m_text.text_width();
- };
+ }
- const char * get_text() const
- {
- return m_text_buf.data();
- };
+ const char * get_text() const { return m_text_buf.cstr(); }
- void set_point(double x, double y)
- {
+ void set_point(double x, double y) {
m_x = x;
m_y = y;
- };
+ }
- void hjustif(double hj) { m_hjustif = hj; };
- void vjustif(double vj) { m_vjustif = vj; };
+ void hjustif(double hj) { m_hjustif = hj; }
+ void vjustif(double vj) { m_vjustif = vj; }
virtual void rewind(unsigned path_id);
virtual unsigned vertex(double* x, double* y);
virtual void apply_transform(const agg::trans_affine& m, double as);
virtual void bounding_box(double *x1, double *y1, double *x2, double *y2);
+ virtual str write_svg(int id, agg::rgba8 c);
+
vs_text& self() { return m_text; };
};
}
diff --git a/agg-plot/trans.h b/agg-plot/trans.h
index 71727d12..54fb7eb4 100644
--- a/agg-plot/trans.h
+++ b/agg-plot/trans.h
@@ -6,6 +6,7 @@
#include "markers.h"
#include "utils.h"
#include "resource-manager.h"
+#include "draw_svg.h"
#include "agg_trans_affine.h"
#include "agg_path_storage.h"
@@ -34,7 +35,6 @@ struct scalable_context {
typedef scalable base_type;
};
-
struct drawable_context {
template <class conv_type, bool approx>
@@ -57,13 +57,65 @@ struct trans {
typedef typename context::base_type base_type;
typedef agg::conv_stroke<base_type> stroke_base;
- typedef typename context::template adapter<stroke_base, true> stroke;
+ typedef typename context::template adapter<stroke_base, true> vs_stroke;
+
+ class stroke : public vs_stroke {
+ public:
+ stroke(base_type* src) : vs_stroke(src), m_width(1.0) { }
+
+ void width(double w) {
+ this->m_output.width(w);
+ m_width = w;
+ }
+
+ virtual str write_svg(int id, agg::rgba8 c) {
+ str path;
+ svg_property_list* ls = this->m_source->svg_path(path);
+ str s = svg_stroke_path(path, m_width, id, c, ls);
+ list::free(ls);
+ return s;
+ }
+
+ private:
+ double m_width;
+ };
typedef agg::conv_curve<base_type> curve_base;
- typedef typename context::template adapter<curve_base, true> curve;
+ typedef typename context::template adapter<curve_base, true> vs_curve;
+
+ class curve : public vs_curve {
+ public:
+ curve(base_type* src) : vs_curve(src) { }
+
+ virtual svg_property_list* svg_path(str& s) {
+ svg_curve_coords_from_vs(this->m_source, s);
+ return 0;
+ }
+ };
typedef agg::conv_dash<base_type> dash_base;
- typedef typename context::template adapter<dash_base, false> dash;
+ typedef typename context::template adapter<dash_base, false> vs_dash;
+
+ class dash : public vs_dash {
+ public:
+ dash(base_type* src) : vs_dash(src), m_dasharray(16) { }
+
+ virtual svg_property_list* svg_path(str& s) {
+ svg_property_list* ls = this->m_source->svg_path(s);
+ svg_property_item item(stroke_dasharray, this->m_dasharray.cstr());
+ ls = new svg_property_list(item, ls);
+ return ls;
+ }
+
+ void add_dash(double a, double b) {
+ this->m_output.add_dash(a, b);
+ this->m_dasharray.append("", ',');
+ this->m_dasharray.printf_add("%g,%g", a, b);
+ }
+
+ private:
+ str m_dasharray;
+ };
typedef agg::conv_contour<base_type> extend_base;
typedef typename context::template adapter<extend_base, true> extend;
@@ -126,4 +178,42 @@ struct trans {
};
};
+template <class T>
+class svg_proxy : public svg_vs {
+protected:
+ T* m_base;
+
+public:
+ svg_proxy(T* src): svg_vs(), m_base(src) { }
+
+ virtual void rewind(unsigned path_id) { m_base->rewind(path_id); }
+ virtual unsigned vertex(double* x, double* y) { return m_base->vertex(x, y); }
+
+ T& self() { return *m_base; }
+};
+
+struct svg_context {
+
+ template <class conv_type, bool approx>
+ class adapter : public svg_vs
+ {
+ protected:
+ conv_type m_output;
+ svg_vs* m_source;
+
+ public:
+ adapter(svg_vs* src): m_output(*src), m_source(src) { }
+
+ template <class init_type>
+ adapter(svg_vs* src, init_type& val): m_output(*src, val), m_source(src) { }
+
+ virtual void rewind(unsigned path_id) { m_output.rewind(path_id); }
+ virtual unsigned vertex(double* x, double* y) { return m_output.vertex(x, y); }
+
+ conv_type& self() { return m_output; };
+ };
+
+ typedef svg_vs base_type;
+};
+
#endif
generated by cgit v1.2.3 (git 2.39.1) at 2025年09月16日 03:29:55 +0000

AltStyle によって変換されたページ (->オリジナル) /