926 lines
26 KiB
C++
926 lines
26 KiB
C++
#include <math.h>
|
|
#include <stdio.h>
|
|
#include "agg_basics.h"
|
|
#include "agg_rendering_buffer.h"
|
|
#include "agg_rasterizer_scanline_aa.h"
|
|
#include "agg_rasterizer_outline.h"
|
|
#include "agg_conv_stroke.h"
|
|
#include "agg_conv_dash.h"
|
|
#include "agg_conv_curve.h"
|
|
#include "agg_conv_contour.h"
|
|
#include "agg_conv_marker.h"
|
|
#include "agg_conv_shorten_path.h"
|
|
#include "agg_conv_marker_adaptor.h"
|
|
#include "agg_conv_concat.h"
|
|
#include "agg_arrowhead.h"
|
|
#include "agg_vcgen_markers_term.h"
|
|
#include "agg_scanline_p.h"
|
|
#include "agg_scanline_u.h"
|
|
#include "agg_renderer_scanline.h"
|
|
#include "agg_renderer_primitives.h"
|
|
#include "agg_span_allocator.h"
|
|
#include "agg_span_gradient.h"
|
|
#include "agg_span_interpolator_linear.h"
|
|
#include "agg_pixfmt_rgb.h"
|
|
#include "agg_pixfmt_rgba.h"
|
|
#include "ctrl/agg_slider_ctrl.h"
|
|
#include "ctrl/agg_rbox_ctrl.h"
|
|
#include "ctrl/agg_cbox_ctrl.h"
|
|
#include "platform/agg_platform_support.h"
|
|
|
|
#define AGG_BGR24
|
|
//#define AGG_BGR96
|
|
#include "pixel_formats.h"
|
|
|
|
enum flip_y_e { flip_y = true };
|
|
|
|
typedef agg::renderer_base<pixfmt> base_renderer;
|
|
typedef agg::renderer_primitives<base_renderer> primitives_renderer;
|
|
|
|
typedef agg::renderer_scanline_aa_solid<base_renderer> solid_renderer;
|
|
typedef agg::renderer_scanline_bin_solid<base_renderer> draft_renderer;
|
|
|
|
typedef agg::gradient_radial_d gradient_function;
|
|
typedef agg::span_interpolator_linear<> interpolator;
|
|
typedef agg::pod_auto_array<color_type, 256> color_array_type;
|
|
typedef agg::span_gradient<color_type,
|
|
interpolator,
|
|
gradient_function,
|
|
color_array_type> gradient_span_gen;
|
|
typedef agg::span_allocator<color_type> gradient_span_alloc;
|
|
|
|
typedef agg::renderer_scanline_aa<base_renderer,
|
|
gradient_span_alloc,
|
|
gradient_span_gen> gradient_renderer;
|
|
|
|
typedef agg::rasterizer_scanline_aa<> scanline_rasterizer;
|
|
typedef agg::rasterizer_outline<primitives_renderer> outline_rasterizer;
|
|
|
|
|
|
|
|
//============================================================================
|
|
class graph
|
|
{
|
|
public:
|
|
struct node
|
|
{
|
|
double x, y;
|
|
node() {}
|
|
node(double x_, double y_) : x(x_), y(y_) {}
|
|
};
|
|
|
|
struct edge
|
|
{
|
|
int node1;
|
|
int node2;
|
|
edge() {}
|
|
edge(int n1, int n2) : node1(n1), node2(n2) {}
|
|
};
|
|
|
|
~graph()
|
|
{
|
|
delete [] m_edges;
|
|
delete [] m_nodes;
|
|
}
|
|
|
|
graph(int num_nodes, int num_edges) :
|
|
m_num_nodes(num_nodes),
|
|
m_num_edges(num_edges),
|
|
m_nodes(new node[num_nodes]),
|
|
m_edges(new edge[num_edges])
|
|
{
|
|
int i;
|
|
|
|
srand(100);
|
|
|
|
for(i = 0; i < m_num_nodes; i++)
|
|
{
|
|
m_nodes[i].x = (double(rand()) / RAND_MAX) * 0.75 + 0.2;
|
|
m_nodes[i].y = (double(rand()) / RAND_MAX) * 0.85 + 0.1;
|
|
}
|
|
|
|
for(i = 0; i < m_num_edges; i++)
|
|
{
|
|
m_edges[i].node1 = rand() % m_num_nodes;
|
|
m_edges[i].node2 = rand() % m_num_nodes;
|
|
if(m_edges[i].node1 == m_edges[i].node2) i--;
|
|
}
|
|
}
|
|
|
|
int get_num_nodes() const { return m_num_nodes; }
|
|
int get_num_edges() const { return m_num_edges; }
|
|
|
|
node get_node(int idx, double w, double h) const
|
|
{
|
|
node p(0.0, 0.0);
|
|
if(idx < m_num_nodes)
|
|
{
|
|
p = m_nodes[idx];
|
|
p.x = p.x * w;
|
|
p.y = p.y * h;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
edge get_edge(int idx) const
|
|
{
|
|
edge b(0,0);
|
|
if(idx < m_num_edges)
|
|
{
|
|
b = m_edges[idx];
|
|
}
|
|
return b;
|
|
}
|
|
|
|
private:
|
|
graph(const graph&);
|
|
const graph& operator = (const graph&);
|
|
|
|
int m_num_nodes;
|
|
int m_num_edges;
|
|
node* m_nodes;
|
|
edge* m_edges;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
struct line
|
|
{
|
|
double x1, y1, x2, y2;
|
|
int f;
|
|
|
|
line(double x1_, double y1_, double x2_, double y2_) :
|
|
x1(x1_), y1(y1_), x2(x2_), y2(y2_), f(0) {}
|
|
|
|
void rewind(unsigned) { f = 0; }
|
|
unsigned vertex(double* x, double* y)
|
|
{
|
|
if(f == 0) { ++f; *x = x1; *y = y1; return agg::path_cmd_move_to; }
|
|
if(f == 1) { ++f; *x = x2; *y = y2; return agg::path_cmd_line_to; }
|
|
return agg::path_cmd_stop;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
struct curve
|
|
{
|
|
agg::curve4 c;
|
|
|
|
curve(double x1, double y1, double x2, double y2, double k=0.5)
|
|
{
|
|
c.init(x1, y1,
|
|
x1 - (y2 - y1) * k,
|
|
y1 + (x2 - x1) * k,
|
|
x2 + (y2 - y1) * k,
|
|
y2 - (x2 - x1) * k,
|
|
x2, y2);
|
|
}
|
|
|
|
void rewind(unsigned path_id) { c.rewind(path_id); }
|
|
unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
|
|
};
|
|
|
|
|
|
|
|
//============================================================================
|
|
template<class Source> struct stroke_draft_simple
|
|
{
|
|
Source& s;
|
|
stroke_draft_simple(Source& src, double w) :
|
|
s(src)
|
|
{
|
|
}
|
|
|
|
void rewind(unsigned path_id) { s.rewind(path_id); }
|
|
unsigned vertex(double* x, double* y) { return s.vertex(x, y); }
|
|
};
|
|
|
|
|
|
//============================================================================
|
|
template<class Source> struct stroke_draft_arrow
|
|
{
|
|
typedef agg::conv_marker_adaptor<Source, agg::vcgen_markers_term> stroke_type;
|
|
typedef agg::conv_marker<typename stroke_type::marker_type, agg::arrowhead> marker_type;
|
|
typedef agg::conv_concat<stroke_type, marker_type> concat_type;
|
|
|
|
stroke_type s;
|
|
agg::arrowhead ah;
|
|
marker_type m;
|
|
concat_type c;
|
|
|
|
stroke_draft_arrow(Source& src, double w) :
|
|
s(src),
|
|
ah(),
|
|
m(s.markers(), ah),
|
|
c(s, m)
|
|
{
|
|
ah.head(0, 10, 5, 0);
|
|
s.shorten(10.0);
|
|
}
|
|
|
|
void rewind(unsigned path_id) { c.rewind(path_id); }
|
|
unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
|
|
};
|
|
|
|
|
|
|
|
//============================================================================
|
|
template<class Source> struct stroke_fine_simple
|
|
{
|
|
typedef agg::conv_stroke<Source> stroke_type;
|
|
|
|
stroke_type s;
|
|
|
|
stroke_fine_simple(Source& src, double w) :
|
|
s(src)
|
|
{
|
|
s.width(w);
|
|
}
|
|
void rewind(unsigned path_id) { s.rewind(path_id); }
|
|
unsigned vertex(double* x, double* y) { return s.vertex(x, y); }
|
|
};
|
|
|
|
|
|
|
|
//============================================================================
|
|
template<class Source> struct stroke_fine_arrow
|
|
{
|
|
typedef agg::conv_stroke<Source, agg::vcgen_markers_term> stroke_type;
|
|
typedef agg::conv_marker<typename stroke_type::marker_type, agg::arrowhead> marker_type;
|
|
typedef agg::conv_concat<stroke_type, marker_type> concat_type;
|
|
|
|
stroke_type s;
|
|
agg::arrowhead ah;
|
|
marker_type m;
|
|
concat_type c;
|
|
|
|
stroke_fine_arrow(Source& src, double w) :
|
|
s(src),
|
|
ah(),
|
|
m(s.markers(), ah),
|
|
c(s, m)
|
|
{
|
|
s.width(w);
|
|
ah.head(0, 10, 5, 0);
|
|
s.shorten(w * 2.0);
|
|
}
|
|
|
|
void rewind(unsigned path_id) { c.rewind(path_id); }
|
|
unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
|
|
};
|
|
|
|
|
|
|
|
//============================================================================
|
|
template<class Source> struct dash_stroke_draft_simple
|
|
{
|
|
typedef agg::conv_dash<Source, agg::vcgen_markers_term> dash_type;
|
|
|
|
dash_type d;
|
|
|
|
dash_stroke_draft_simple(Source& src,
|
|
double dash_len,
|
|
double gap_len,
|
|
double w) :
|
|
d(src)
|
|
{
|
|
d.add_dash(dash_len, gap_len);
|
|
}
|
|
|
|
void rewind(unsigned path_id) { d.rewind(path_id); }
|
|
unsigned vertex(double* x, double* y) { return d.vertex(x, y); }
|
|
};
|
|
|
|
|
|
//============================================================================
|
|
template<class Source> struct dash_stroke_draft_arrow
|
|
{
|
|
typedef agg::conv_dash<Source, agg::vcgen_markers_term> dash_type;
|
|
typedef agg::conv_marker<typename dash_type::marker_type, agg::arrowhead> marker_type;
|
|
typedef agg::conv_concat<dash_type, marker_type> concat_type;
|
|
|
|
dash_type d;
|
|
agg::arrowhead ah;
|
|
marker_type m;
|
|
concat_type c;
|
|
|
|
dash_stroke_draft_arrow(Source& src,
|
|
double dash_len, double gap_len, double w) :
|
|
d(src),
|
|
ah(),
|
|
m(d.markers(), ah),
|
|
c(d, m)
|
|
{
|
|
d.add_dash(dash_len, gap_len);
|
|
ah.head(0, 10, 5, 0);
|
|
d.shorten(10.0);
|
|
}
|
|
|
|
void rewind(unsigned path_id) { c.rewind(path_id); }
|
|
unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
|
|
};
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
template<class Source> struct dash_stroke_fine_simple
|
|
{
|
|
typedef agg::conv_dash<Source> dash_type;
|
|
typedef agg::conv_stroke<dash_type> stroke_type;
|
|
|
|
dash_type d;
|
|
stroke_type s;
|
|
|
|
dash_stroke_fine_simple(Source& src,
|
|
double dash_len, double gap_len, double w) :
|
|
d(src),
|
|
s(d)
|
|
{
|
|
d.add_dash(dash_len, gap_len);
|
|
s.width(w);
|
|
}
|
|
|
|
void rewind(unsigned path_id) { s.rewind(path_id); }
|
|
unsigned vertex(double* x, double* y) { return s.vertex(x, y); }
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
template<class Source> struct dash_stroke_fine_arrow
|
|
{
|
|
typedef agg::conv_dash<Source, agg::vcgen_markers_term> dash_type;
|
|
typedef agg::conv_stroke<dash_type> stroke_type;
|
|
typedef agg::conv_marker<typename dash_type::marker_type, agg::arrowhead> marker_type;
|
|
typedef agg::conv_concat<stroke_type, marker_type> concat_type;
|
|
|
|
dash_type d;
|
|
stroke_type s;
|
|
agg::arrowhead ah;
|
|
marker_type m;
|
|
concat_type c;
|
|
|
|
dash_stroke_fine_arrow(Source& src,
|
|
double dash_len, double gap_len, double w) :
|
|
d(src),
|
|
s(d),
|
|
ah(),
|
|
m(d.markers(), ah),
|
|
c(s, m)
|
|
{
|
|
d.add_dash(dash_len, gap_len);
|
|
s.width(w);
|
|
ah.head(0, 10, 5, 0);
|
|
d.shorten(w * 2.0);
|
|
}
|
|
|
|
void rewind(unsigned path_id) { c.rewind(path_id); }
|
|
unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
|
|
};
|
|
|
|
|
|
|
|
//#define stroke_draft stroke_draft_simple
|
|
//#define dash_stroke_draft dash_stroke_draft_simple
|
|
//#define stroke_fine stroke_fine_simple
|
|
//#define dash_stroke_fine dash_stroke_fine_simple
|
|
|
|
#define stroke_draft stroke_draft_arrow
|
|
#define dash_stroke_draft dash_stroke_draft_arrow
|
|
#define stroke_fine stroke_fine_arrow
|
|
#define dash_stroke_fine dash_stroke_fine_arrow
|
|
|
|
|
|
|
|
|
|
|
|
class the_application : public agg::platform_support
|
|
{
|
|
agg::rbox_ctrl<agg::rgba> m_type;
|
|
agg::slider_ctrl<agg::rgba> m_width;
|
|
agg::cbox_ctrl<agg::rgba> m_benchmark;
|
|
agg::cbox_ctrl<agg::rgba> m_draw_nodes;
|
|
agg::cbox_ctrl<agg::rgba> m_draw_edges;
|
|
agg::cbox_ctrl<agg::rgba> m_draft;
|
|
agg::cbox_ctrl<agg::rgba> m_translucent;
|
|
graph m_graph;
|
|
color_array_type m_gradient_colors;
|
|
int m_draw;
|
|
agg::scanline_u8 m_sl;
|
|
|
|
|
|
public:
|
|
the_application(agg::pix_format_e format, bool flip_y) :
|
|
agg::platform_support(format, flip_y),
|
|
m_type(-1, -1, -1, -1, !flip_y),
|
|
m_width(110+80, 8.0, 110+200.0+80, 8.0 + 7.0, !flip_y),
|
|
m_benchmark(110+200+80+8, 8.0-2.0, "Benchmark", !flip_y),
|
|
m_draw_nodes(110+200+80+8, 8.0-2.0+15.0, "Draw Nodes", !flip_y),
|
|
m_draw_edges(200+200+80+8, 8.0-2.0+15.0, "Draw Edges", !flip_y),
|
|
m_draft(200+200+80+8, 8.0-2.0, "Draft Mode", !flip_y),
|
|
m_translucent(110+80, 8.0-2.0+15.0, "Translucent Mode", !flip_y),
|
|
m_graph(200, 100),
|
|
m_gradient_colors(),
|
|
m_draw(3)
|
|
{
|
|
add_ctrl(m_type);
|
|
m_type.text_size(8.0);
|
|
m_type.add_item("Solid lines");
|
|
m_type.add_item("Bezier curves");
|
|
m_type.add_item("Dashed curves");
|
|
m_type.add_item("Poygons AA");
|
|
m_type.add_item("Poygons Bin");
|
|
m_type.cur_item(0);
|
|
|
|
add_ctrl(m_width);
|
|
m_width.num_steps(20);
|
|
m_width.range(0.0, 5.0);
|
|
m_width.value(2.0);
|
|
m_width.label("Width=%1.2f");
|
|
|
|
m_benchmark.text_size(8.0);
|
|
m_draw_nodes.text_size(8.0);
|
|
m_draft.text_size(8.0);
|
|
m_draw_nodes.status(true);
|
|
m_draw_edges.status(true);
|
|
add_ctrl(m_benchmark);
|
|
add_ctrl(m_draw_nodes);
|
|
add_ctrl(m_draw_edges);
|
|
add_ctrl(m_draft);
|
|
add_ctrl(m_translucent);
|
|
|
|
agg::rgba c1(1, 1, 0, 0.25);
|
|
agg::rgba c2(0, 0, 1);
|
|
|
|
int i;
|
|
for(i = 0; i < 256; i++)
|
|
{
|
|
m_gradient_colors[i] = c1.gradient(c2, double(i) / 255.0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_nodes_draft()
|
|
{
|
|
pixfmt pixf(rbuf_window());
|
|
base_renderer rb(pixf);
|
|
primitives_renderer prim(rb);
|
|
int i;
|
|
for(i = 0; i < m_graph.get_num_nodes(); i++)
|
|
{
|
|
graph::node n = m_graph.get_node(i, width(), height());
|
|
prim.fill_color(m_gradient_colors[147]);
|
|
prim.line_color(m_gradient_colors[255]);
|
|
prim.outlined_ellipse(int(n.x), int(n.y), 10, 10);
|
|
prim.fill_color(m_gradient_colors[50]);
|
|
prim.solid_ellipse(int(n.x), int(n.y), 4, 4);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_nodes_fine(scanline_rasterizer& ras)
|
|
{
|
|
gradient_span_alloc sa;
|
|
pixfmt pixf(rbuf_window());
|
|
base_renderer rb(pixf);
|
|
int i;
|
|
for(i = 0; i < m_graph.get_num_nodes(); i++)
|
|
{
|
|
graph::node n = m_graph.get_node(i, width(), height());
|
|
agg::ellipse ell(n.x, n.y, 5.0 * m_width.value(), 5.0 * m_width.value());
|
|
|
|
double x, y;
|
|
switch(m_draw)
|
|
{
|
|
case 0:
|
|
ell.rewind(0);
|
|
while(!agg::is_stop(ell.vertex(&x, &y)));
|
|
break;
|
|
|
|
case 1:
|
|
ras.reset();
|
|
ras.add_path(ell);
|
|
break;
|
|
|
|
case 2:
|
|
ras.reset();
|
|
ras.add_path(ell);
|
|
ras.sort();
|
|
break;
|
|
|
|
case 3:
|
|
{
|
|
gradient_function gf;
|
|
agg::trans_affine mtx;
|
|
mtx *= agg::trans_affine_scaling(m_width.value() / 2.0);
|
|
mtx *= agg::trans_affine_translation(n.x, n.y);
|
|
mtx.invert();
|
|
interpolator inter(mtx);
|
|
gradient_span_gen sg(inter, gf, m_gradient_colors, 0.0, 10.0);
|
|
gradient_renderer ren(rb, sa, sg);
|
|
ras.add_path(ell);
|
|
agg::render_scanlines(ras, m_sl, ren);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
template<class Source>
|
|
void render_edge_fine(scanline_rasterizer& ras,
|
|
solid_renderer& ren_fine,
|
|
draft_renderer& ren_draft,
|
|
Source& src)
|
|
{
|
|
double x, y;
|
|
switch(m_draw)
|
|
{
|
|
case 0:
|
|
src.rewind(0);
|
|
while(!agg::is_stop(src.vertex(&x, &y)));
|
|
break;
|
|
|
|
case 1:
|
|
ras.reset();
|
|
ras.add_path(src);
|
|
break;
|
|
|
|
case 2:
|
|
ras.reset();
|
|
ras.add_path(src);
|
|
ras.sort();
|
|
break;
|
|
|
|
case 3:
|
|
{
|
|
int r = rand() & 0x7F;
|
|
int g = rand() & 0x7F;
|
|
int b = rand() & 0x7F;
|
|
int a = 255;
|
|
if(m_translucent.status()) a = 80;
|
|
ras.add_path(src);
|
|
|
|
if(m_type.cur_item() < 4)
|
|
{
|
|
ren_fine.color(agg::srgba8(r, g, b, a));
|
|
agg::render_scanlines(ras, m_sl, ren_fine);
|
|
}
|
|
else
|
|
{
|
|
ren_draft.color(agg::srgba8(r, g, b, a));
|
|
agg::render_scanlines(ras, m_sl, ren_draft);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_lines_draft()
|
|
{
|
|
pixfmt pixf(rbuf_window());
|
|
base_renderer rb(pixf);
|
|
primitives_renderer prim(rb);
|
|
outline_rasterizer ras(prim);
|
|
|
|
int i;
|
|
for(i = 0; i < m_graph.get_num_edges(); i++)
|
|
{
|
|
graph::edge e = m_graph.get_edge(i);
|
|
graph::node n1 = m_graph.get_node(e.node1, width(), height());
|
|
graph::node n2 = m_graph.get_node(e.node2, width(), height());
|
|
line l(n1.x, n1.y, n2.x, n2.y);
|
|
stroke_draft<line> s(l, m_width.value());
|
|
|
|
int r = rand() & 0x7F;
|
|
int g = rand() & 0x7F;
|
|
int b = rand() & 0x7F;
|
|
int a = 255;
|
|
if(m_translucent.status()) a = 80;
|
|
prim.line_color(agg::srgba8(r, g, b, a));
|
|
ras.add_path(s);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_curves_draft()
|
|
{
|
|
pixfmt pixf(rbuf_window());
|
|
base_renderer rb(pixf);
|
|
primitives_renderer prim(rb);
|
|
outline_rasterizer ras(prim);
|
|
|
|
int i;
|
|
for(i = 0; i < m_graph.get_num_edges(); i++)
|
|
{
|
|
graph::edge e = m_graph.get_edge(i);
|
|
graph::node n1 = m_graph.get_node(e.node1, width(), height());
|
|
graph::node n2 = m_graph.get_node(e.node2, width(), height());
|
|
curve c(n1.x, n1.y, n2.x, n2.y);
|
|
stroke_draft<curve> s(c, m_width.value());
|
|
|
|
int r = rand() & 0x7F;
|
|
int g = rand() & 0x7F;
|
|
int b = rand() & 0x7F;
|
|
int a = 255;
|
|
if(m_translucent.status()) a = 80;
|
|
prim.line_color(agg::srgba8(r, g, b, a));
|
|
ras.add_path(s);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_dashes_draft()
|
|
{
|
|
pixfmt pixf(rbuf_window());
|
|
base_renderer rb(pixf);
|
|
primitives_renderer prim(rb);
|
|
outline_rasterizer ras(prim);
|
|
|
|
int i;
|
|
for(i = 0; i < m_graph.get_num_edges(); i++)
|
|
{
|
|
graph::edge e = m_graph.get_edge(i);
|
|
graph::node n1 = m_graph.get_node(e.node1, width(), height());
|
|
graph::node n2 = m_graph.get_node(e.node2, width(), height());
|
|
curve c(n1.x, n1.y, n2.x, n2.y);
|
|
dash_stroke_draft<curve> s(c, 6.0, 3.0, m_width.value());
|
|
|
|
int r = rand() & 0x7F;
|
|
int g = rand() & 0x7F;
|
|
int b = rand() & 0x7F;
|
|
int a = 255;
|
|
if(m_translucent.status()) a = 80;
|
|
prim.line_color(agg::srgba8(r, g, b, a));
|
|
ras.add_path(s);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_lines_fine(scanline_rasterizer& ras,
|
|
solid_renderer& solid,
|
|
draft_renderer& draft)
|
|
{
|
|
int i;
|
|
for(i = 0; i < m_graph.get_num_edges(); i++)
|
|
{
|
|
graph::edge b = m_graph.get_edge(i);
|
|
graph::node n1 = m_graph.get_node(b.node1, width(), height());
|
|
graph::node n2 = m_graph.get_node(b.node2, width(), height());
|
|
line l(n1.x, n1.y, n2.x, n2.y);
|
|
stroke_fine<line> s(l, m_width.value());
|
|
render_edge_fine(ras, solid, draft, s);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_curves_fine(scanline_rasterizer& ras,
|
|
solid_renderer& solid,
|
|
draft_renderer& draft)
|
|
|
|
{
|
|
int i;
|
|
for(i = 0; i < m_graph.get_num_edges(); i++)
|
|
{
|
|
graph::edge b = m_graph.get_edge(i);
|
|
graph::node n1 = m_graph.get_node(b.node1, width(), height());
|
|
graph::node n2 = m_graph.get_node(b.node2, width(), height());
|
|
curve c(n1.x, n1.y, n2.x, n2.y);
|
|
stroke_fine<curve> s(c, m_width.value());
|
|
render_edge_fine(ras, solid, draft, s);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_dashes_fine(scanline_rasterizer& ras,
|
|
solid_renderer& solid,
|
|
draft_renderer& draft)
|
|
{
|
|
int i;
|
|
for(i = 0; i < m_graph.get_num_edges(); i++)
|
|
{
|
|
graph::edge b = m_graph.get_edge(i);
|
|
graph::node n1 = m_graph.get_node(b.node1, width(), height());
|
|
graph::node n2 = m_graph.get_node(b.node2, width(), height());
|
|
curve c(n1.x, n1.y, n2.x, n2.y);
|
|
dash_stroke_fine<curve> s(c, 6.0, 3.0, m_width.value());
|
|
render_edge_fine(ras, solid, draft, s);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_polygons(scanline_rasterizer& ras,
|
|
solid_renderer& solid,
|
|
draft_renderer& draft)
|
|
{
|
|
int i;
|
|
if(m_type.cur_item() == 4)
|
|
{
|
|
ras.gamma(agg::gamma_threshold(0.5));
|
|
}
|
|
for(i = 0; i < m_graph.get_num_edges(); i++)
|
|
{
|
|
graph::edge b = m_graph.get_edge(i);
|
|
graph::node n1 = m_graph.get_node(b.node1, width(), height());
|
|
graph::node n2 = m_graph.get_node(b.node2, width(), height());
|
|
curve c(n1.x, n1.y, n2.x, n2.y);
|
|
render_edge_fine(ras, solid, draft, c);
|
|
}
|
|
ras.gamma(agg::gamma_none());
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void draw_scene(scanline_rasterizer& ras,
|
|
solid_renderer& solid,
|
|
draft_renderer& draft)
|
|
{
|
|
ras.gamma(agg::gamma_none());
|
|
srand(100);
|
|
if(m_draw_nodes.status())
|
|
{
|
|
if(m_draft.status())
|
|
{
|
|
draw_nodes_draft();
|
|
}
|
|
else
|
|
{
|
|
draw_nodes_fine(ras);
|
|
}
|
|
}
|
|
|
|
if(m_draw_edges.status())
|
|
{
|
|
if(m_draft.status())
|
|
{
|
|
switch(m_type.cur_item())
|
|
{
|
|
case 0: draw_lines_draft(); break;
|
|
case 1: draw_curves_draft(); break;
|
|
case 2: draw_dashes_draft(); break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch(m_type.cur_item())
|
|
{
|
|
case 0: draw_lines_fine(ras, solid, draft); break;
|
|
case 1: draw_curves_fine(ras, solid, draft); break;
|
|
case 2: draw_dashes_fine(ras, solid, draft); break;
|
|
case 3:
|
|
case 4: draw_polygons(ras, solid, draft); break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
virtual void on_draw()
|
|
{
|
|
scanline_rasterizer ras;
|
|
|
|
pixfmt pixf(rbuf_window());
|
|
base_renderer rb(pixf);
|
|
solid_renderer solid(rb);
|
|
draft_renderer draft(rb);
|
|
|
|
rb.clear(agg::rgba(1, 1, 1));
|
|
draw_scene(ras, solid, draft);
|
|
|
|
ras.filling_rule(agg::fill_non_zero);
|
|
agg::render_ctrl(ras, m_sl, rb, m_type);
|
|
agg::render_ctrl(ras, m_sl, rb, m_width);
|
|
agg::render_ctrl(ras, m_sl, rb, m_benchmark);
|
|
agg::render_ctrl(ras, m_sl, rb, m_draw_nodes);
|
|
agg::render_ctrl(ras, m_sl, rb, m_draw_edges);
|
|
agg::render_ctrl(ras, m_sl, rb, m_draft);
|
|
agg::render_ctrl(ras, m_sl, rb, m_translucent);
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void on_ctrl_change()
|
|
{
|
|
if(m_benchmark.status())
|
|
{
|
|
int i;
|
|
on_draw();
|
|
update_window();
|
|
|
|
scanline_rasterizer ras;
|
|
|
|
pixfmt pixf(rbuf_window());
|
|
base_renderer rb(pixf);
|
|
solid_renderer solid(rb);
|
|
draft_renderer draft(rb);
|
|
|
|
char buf[256];
|
|
if(m_draft.status())
|
|
{
|
|
start_timer();
|
|
for(i = 0; i < 10; i++)
|
|
{
|
|
draw_scene(ras, solid, draft);
|
|
}
|
|
sprintf(buf, "%3.3f milliseconds", elapsed_time());
|
|
}
|
|
else
|
|
{
|
|
double times[5];
|
|
for(m_draw = 0; m_draw < 4; m_draw++)
|
|
{
|
|
start_timer();
|
|
for(i = 0; i < 10; i++)
|
|
{
|
|
draw_scene(ras, solid, draft);
|
|
}
|
|
times[m_draw] = elapsed_time();
|
|
}
|
|
m_draw = 3;
|
|
|
|
times[4] = times[3];
|
|
times[3] -= times[2];
|
|
times[2] -= times[1];
|
|
times[1] -= times[0];
|
|
|
|
FILE* fd = fopen(full_file_name("benchmark"), "a");
|
|
fprintf(fd, "%10.3f %10.3f %10.3f %10.3f %10.3f\n",
|
|
times[0], times[1], times[2], times[3], times[4]);
|
|
fclose(fd);
|
|
|
|
|
|
sprintf(buf, " pipeline add_path sort render total\n"
|
|
"%10.3f %10.3f %10.3f %10.3f %10.3f",
|
|
times[0], times[1], times[2], times[3], times[4]);
|
|
}
|
|
message(buf);
|
|
|
|
m_benchmark.status(false);
|
|
force_redraw();
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
int agg_main(int argc, char* argv[])
|
|
{
|
|
the_application app(pix_format, flip_y);
|
|
app.caption("AGG Example. Line Join");
|
|
|
|
if(app.init(600+100, 500+30, agg::window_resize))
|
|
{
|
|
return app.run();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|