You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by pf...@apache.org on 2011/10/16 06:13:21 UTC
svn commit: r1184758 [4/17] - in /incubator/ooo/trunk/main: ./ agg/inc/
agg/source/ solenv/config/
Modified: incubator/ooo/trunk/main/agg/inc/agg_path_storage.h
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/agg/inc/agg_path_storage.h?rev=1184758&r1=1184757&r2=1184758&view=diff
==============================================================================
--- incubator/ooo/trunk/main/agg/inc/agg_path_storage.h (original)
+++ incubator/ooo/trunk/main/agg/inc/agg_path_storage.h Sun Oct 16 04:13:16 2011
@@ -1,5 +1,5 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.3
+// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
@@ -16,349 +16,1530 @@
#ifndef AGG_PATH_STORAGE_INCLUDED
#define AGG_PATH_STORAGE_INCLUDED
-#include "agg_basics.h"
+#include <string.h>
+#include <math.h>
+#include "agg_math.h"
+#include "agg_array.h"
+#include "agg_bezier_arc.h"
namespace agg
{
- //------------------------------------------------------------path_storage
- // A container to store vertices with their flags.
- // A path consists of a number of contours separated with "move_to"
- // commands. The path storage can keep and maintain more than one
- // path.
- // To navigate to the beginning of a particular path, use rewind(path_id);
- // Where path_id is what start_new_path() returns. So, when you call
- // start_new_path() you need to store its return value somewhere else
- // to navigate to the path afterwards.
- //
- // See Implementation: agg_path_storage.cpp
- // See also: vertex_source concept
- //------------------------------------------------------------------------
- class path_storage
+
+ //----------------------------------------------------vertex_block_storage
+ template<class T, unsigned BlockShift=8, unsigned BlockPool=256>
+ class vertex_block_storage
{
+ public:
// Allocation parameters
- enum
+ enum block_scale_e
{
- block_shift = 8,
+ block_shift = BlockShift,
block_size = 1 << block_shift,
block_mask = block_size - 1,
- block_pool = 256
+ block_pool = BlockPool
};
- public:
-
- //--------------------------------------------------------------------
- class const_iterator
- {
- void vertex()
- {
- if(m_vertex_idx < m_path->total_vertices())
- {
- m_vertex.cmd = m_path->vertex(m_vertex_idx, &m_vertex.x, &m_vertex.y);
- }
- else
- {
- m_vertex.cmd = path_cmd_stop;
- m_vertex.x = m_vertex.y = 0.0;
- }
- }
+ typedef T value_type;
+ typedef vertex_block_storage<T, BlockShift, BlockPool> self_type;
- public:
- const_iterator() {}
- const_iterator(unsigned cmd) { m_vertex.cmd = cmd; }
- const_iterator(const const_iterator& i) :
- m_path(i.m_path),
- m_vertex_idx(i.m_vertex_idx),
- m_vertex(i.m_vertex)
- {
- }
+ ~vertex_block_storage();
+ vertex_block_storage();
+ vertex_block_storage(const self_type& v);
+ const self_type& operator = (const self_type& ps);
- const_iterator(const path_storage& p, unsigned id) :
- m_path(&p),
- m_vertex_idx(id)
- {
- vertex();
- }
+ void remove_all();
+ void free_all();
- const_iterator& operator++()
- {
- ++m_vertex_idx;
- vertex();
- return *this;
- }
+ void add_vertex(double x, double y, unsigned cmd);
+ void modify_vertex(unsigned idx, double x, double y);
+ void modify_vertex(unsigned idx, double x, double y, unsigned cmd);
+ void modify_command(unsigned idx, unsigned cmd);
+ void swap_vertices(unsigned v1, unsigned v2);
- const vertex_type& operator*() const { return m_vertex; }
- const vertex_type* operator->() const { return &m_vertex; }
+ unsigned last_command() const;
+ unsigned last_vertex(double* x, double* y) const;
+ unsigned prev_vertex(double* x, double* y) const;
- bool operator != (const const_iterator& i)
- {
- return m_vertex.cmd != i.m_vertex.cmd;
- }
+ double last_x() const;
+ double last_y() const;
- private:
- const path_storage* m_path;
- unsigned m_vertex_idx;
- vertex_type m_vertex;
- };
+ unsigned total_vertices() const;
+ unsigned vertex(unsigned idx, double* x, double* y) const;
+ unsigned command(unsigned idx) const;
- ~path_storage();
- path_storage();
- path_storage(const path_storage& ps);
+ private:
+ void allocate_block(unsigned nb);
+ int8u* storage_ptrs(T** xy_ptr);
- void remove_all();
+ private:
+ unsigned m_total_vertices;
+ unsigned m_total_blocks;
+ unsigned m_max_blocks;
+ T** m_coord_blocks;
+ int8u** m_cmd_blocks;
+ };
- unsigned last_vertex(double* x, double* y) const;
- unsigned prev_vertex(double* x, double* y) const;
- void rel_to_abs(double* x, double* y) const;
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ void vertex_block_storage<T,S,P>::free_all()
+ {
+ if(m_total_blocks)
+ {
+ T** coord_blk = m_coord_blocks + m_total_blocks - 1;
+ while(m_total_blocks--)
+ {
+ pod_allocator<T>::deallocate(
+ *coord_blk,
+ block_size * 2 +
+ block_size / (sizeof(T) / sizeof(unsigned char)));
+ --coord_blk;
+ }
+ pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2);
+ m_total_blocks = 0;
+ m_max_blocks = 0;
+ m_coord_blocks = 0;
+ m_cmd_blocks = 0;
+ m_total_vertices = 0;
+ }
+ }
- void move_to(double x, double y);
- void move_rel(double dx, double dy);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ vertex_block_storage<T,S,P>::~vertex_block_storage()
+ {
+ free_all();
+ }
- void line_to(double x, double y);
- void line_rel(double dx, double dy);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ vertex_block_storage<T,S,P>::vertex_block_storage() :
+ m_total_vertices(0),
+ m_total_blocks(0),
+ m_max_blocks(0),
+ m_coord_blocks(0),
+ m_cmd_blocks(0)
+ {
+ }
- void arc_to(double rx, double ry,
- double angle,
- bool large_arc_flag,
- bool sweep_flag,
- double x, double y);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ vertex_block_storage<T,S,P>::vertex_block_storage(const vertex_block_storage<T,S,P>& v) :
+ m_total_vertices(0),
+ m_total_blocks(0),
+ m_max_blocks(0),
+ m_coord_blocks(0),
+ m_cmd_blocks(0)
+ {
+ *this = v;
+ }
- void arc_rel(double rx, double ry,
- double angle,
- bool large_arc_flag,
- bool sweep_flag,
- double dx, double dy);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ const vertex_block_storage<T,S,P>&
+ vertex_block_storage<T,S,P>::operator = (const vertex_block_storage<T,S,P>& v)
+ {
+ remove_all();
+ unsigned i;
+ for(i = 0; i < v.total_vertices(); i++)
+ {
+ double x, y;
+ unsigned cmd = v.vertex(i, &x, &y);
+ add_vertex(x, y, cmd);
+ }
+ return *this;
+ }
- void curve3(double x_ctrl, double y_ctrl,
- double x_to, double y_to);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::remove_all()
+ {
+ m_total_vertices = 0;
+ }
- void curve3_rel(double dx_ctrl, double dy_ctrl,
- double dx_to, double dy_to);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::add_vertex(double x, double y,
+ unsigned cmd)
+ {
+ T* coord_ptr = 0;
+ *storage_ptrs(&coord_ptr) = (int8u)cmd;
+ coord_ptr[0] = T(x);
+ coord_ptr[1] = T(y);
+ m_total_vertices++;
+ }
- void curve3(double x_to, double y_to);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx,
+ double x, double y)
+ {
+ T* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1);
+ pv[0] = T(x);
+ pv[1] = T(y);
+ }
- void curve3_rel(double dx_to, double dy_to);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx,
+ double x, double y,
+ unsigned cmd)
+ {
+ unsigned block = idx >> block_shift;
+ unsigned offset = idx & block_mask;
+ T* pv = m_coord_blocks[block] + (offset << 1);
+ pv[0] = T(x);
+ pv[1] = T(y);
+ m_cmd_blocks[block][offset] = (int8u)cmd;
+ }
- void curve4(double x_ctrl1, double y_ctrl1,
- double x_ctrl2, double y_ctrl2,
- double x_to, double y_to);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::modify_command(unsigned idx,
+ unsigned cmd)
+ {
+ m_cmd_blocks[idx >> block_shift][idx & block_mask] = (int8u)cmd;
+ }
- void curve4_rel(double dx_ctrl1, double dy_ctrl1,
- double dx_ctrl2, double dy_ctrl2,
- double dx_to, double dy_to);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline void vertex_block_storage<T,S,P>::swap_vertices(unsigned v1, unsigned v2)
+ {
+ unsigned b1 = v1 >> block_shift;
+ unsigned b2 = v2 >> block_shift;
+ unsigned o1 = v1 & block_mask;
+ unsigned o2 = v2 & block_mask;
+ T* pv1 = m_coord_blocks[b1] + (o1 << 1);
+ T* pv2 = m_coord_blocks[b2] + (o2 << 1);
+ T val;
+ val = pv1[0]; pv1[0] = pv2[0]; pv2[0] = val;
+ val = pv1[1]; pv1[1] = pv2[1]; pv2[1] = val;
+ int8u cmd = m_cmd_blocks[b1][o1];
+ m_cmd_blocks[b1][o1] = m_cmd_blocks[b2][o2];
+ m_cmd_blocks[b2][o2] = cmd;
+ }
- void curve4(double x_ctrl2, double y_ctrl2,
- double x_to, double y_to);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::last_command() const
+ {
+ if(m_total_vertices) return command(m_total_vertices - 1);
+ return path_cmd_stop;
+ }
- void curve4_rel(double x_ctrl2, double y_ctrl2,
- double x_to, double y_to);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::last_vertex(double* x, double* y) const
+ {
+ if(m_total_vertices) return vertex(m_total_vertices - 1, x, y);
+ return path_cmd_stop;
+ }
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::prev_vertex(double* x, double* y) const
+ {
+ if(m_total_vertices > 1) return vertex(m_total_vertices - 2, x, y);
+ return path_cmd_stop;
+ }
- void end_poly(unsigned flags = path_flags_close);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline double vertex_block_storage<T,S,P>::last_x() const
+ {
+ if(m_total_vertices)
+ {
+ unsigned idx = m_total_vertices - 1;
+ return m_coord_blocks[idx >> block_shift][(idx & block_mask) << 1];
+ }
+ return 0.0;
+ }
- void close_polygon(unsigned flags = path_flags_none)
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline double vertex_block_storage<T,S,P>::last_y() const
+ {
+ if(m_total_vertices)
{
- end_poly(path_flags_close | flags);
+ unsigned idx = m_total_vertices - 1;
+ return m_coord_blocks[idx >> block_shift][((idx & block_mask) << 1) + 1];
}
+ return 0.0;
+ }
- void add_poly(const double* vertices, unsigned num,
- bool solid_path = false,
- unsigned end_flags = path_flags_none);
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::total_vertices() const
+ {
+ return m_total_vertices;
+ }
- template<class VertexSource>
- void add_path(VertexSource& vs,
- unsigned path_id = 0,
- bool solid_path = true)
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::vertex(unsigned idx,
+ double* x, double* y) const
+ {
+ unsigned nb = idx >> block_shift;
+ const T* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1);
+ *x = pv[0];
+ *y = pv[1];
+ return m_cmd_blocks[nb][idx & block_mask];
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ inline unsigned vertex_block_storage<T,S,P>::command(unsigned idx) const
+ {
+ return m_cmd_blocks[idx >> block_shift][idx & block_mask];
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ void vertex_block_storage<T,S,P>::allocate_block(unsigned nb)
+ {
+ if(nb >= m_max_blocks)
{
- double x, y;
- unsigned cmd;
- vs.rewind(path_id);
- while(!is_stop(cmd = vs.vertex(&x, &y)))
+ T** new_coords =
+ pod_allocator<T*>::allocate((m_max_blocks + block_pool) * 2);
+
+ unsigned char** new_cmds =
+ (unsigned char**)(new_coords + m_max_blocks + block_pool);
+
+ if(m_coord_blocks)
{
- if(is_move_to(cmd) && solid_path && m_total_vertices)
- {
- cmd = path_cmd_line_to;
- }
- add_vertex(x, y, cmd);
+ memcpy(new_coords,
+ m_coord_blocks,
+ m_max_blocks * sizeof(T*));
+
+ memcpy(new_cmds,
+ m_cmd_blocks,
+ m_max_blocks * sizeof(unsigned char*));
+
+ pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2);
}
+ m_coord_blocks = new_coords;
+ m_cmd_blocks = new_cmds;
+ m_max_blocks += block_pool;
}
+ m_coord_blocks[nb] =
+ pod_allocator<T>::allocate(block_size * 2 +
+ block_size / (sizeof(T) / sizeof(unsigned char)));
- unsigned start_new_path();
+ m_cmd_blocks[nb] =
+ (unsigned char*)(m_coord_blocks[nb] + block_size * 2);
- void copy_from(const path_storage& ps);
- const path_storage& operator = (const path_storage& ps)
+ m_total_blocks++;
+ }
+
+ //------------------------------------------------------------------------
+ template<class T, unsigned S, unsigned P>
+ int8u* vertex_block_storage<T,S,P>::storage_ptrs(T** xy_ptr)
+ {
+ unsigned nb = m_total_vertices >> block_shift;
+ if(nb >= m_total_blocks)
{
- copy_from(ps);
- return *this;
+ allocate_block(nb);
}
+ *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1);
+ return m_cmd_blocks[nb] + (m_total_vertices & block_mask);
+ }
- unsigned total_vertices() const { return m_total_vertices; }
- unsigned vertex(unsigned idx, double* x, double* y) const
+
+
+ //-----------------------------------------------------poly_plain_adaptor
+ template<class T> class poly_plain_adaptor
+ {
+ public:
+ typedef T value_type;
+
+ poly_plain_adaptor() :
+ m_data(0),
+ m_ptr(0),
+ m_end(0),
+ m_closed(false),
+ m_stop(false)
+ {}
+
+ poly_plain_adaptor(const T* data, unsigned num_points, bool closed) :
+ m_data(data),
+ m_ptr(data),
+ m_end(data + num_points * 2),
+ m_closed(closed),
+ m_stop(false)
+ {}
+
+ void init(const T* data, unsigned num_points, bool closed)
{
- unsigned nb = idx >> block_shift;
- const double* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1);
- *x = *pv++;
- *y = *pv;
- return m_cmd_blocks[nb][idx & block_mask];
+ m_data = data;
+ m_ptr = data;
+ m_end = data + num_points * 2;
+ m_closed = closed;
+ m_stop = false;
}
- unsigned command(unsigned idx) const
+
+ void rewind(unsigned)
{
- return m_cmd_blocks[idx >> block_shift][idx & block_mask];
+ m_ptr = m_data;
+ m_stop = false;
}
- void rewind(unsigned path_id);
- unsigned vertex(double* x, double* y);
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_ptr < m_end)
+ {
+ bool first = m_ptr == m_data;
+ *x = *m_ptr++;
+ *y = *m_ptr++;
+ return first ? path_cmd_move_to : path_cmd_line_to;
+ }
+ *x = *y = 0.0;
+ if(m_closed && !m_stop)
+ {
+ m_stop = true;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ return path_cmd_stop;
+ }
- const_iterator begin(unsigned id) const { return const_iterator(*this, id); }
- const_iterator begin() const { return const_iterator(*this, 0); }
- const_iterator end() const { return const_iterator(path_cmd_stop); }
-
- // Arrange the orientation of all the polygons. After calling this
- // method all the polygons will have the same orientation
- // determined by the new_orientation flag, i.e.,
- // path_flags_cw or path_flags_ccw
- unsigned arrange_orientations(unsigned path_id, path_flags_e new_orientation);
- void arrange_orientations_all_paths(path_flags_e new_orientation);
+ private:
+ const T* m_data;
+ const T* m_ptr;
+ const T* m_end;
+ bool m_closed;
+ bool m_stop;
+ };
- // Flip all the vertices horizontally or vertically
- void flip_x(double x1, double x2);
- void flip_y(double y1, double y2);
-
- // This function adds a vertex with its flags directly. Since there's no
- // checking for errors, keeping proper path integrity is the responsibility
- // of the caller. It can be said the function is "not very public".
- void add_vertex(double x, double y, unsigned cmd);
- // Allows you to modify vertex coordinates. The caller must know
- // the index of the vertex.
- void modify_vertex(unsigned idx, double x, double y)
+
+
+
+ //-------------------------------------------------poly_container_adaptor
+ template<class Container> class poly_container_adaptor
+ {
+ public:
+ typedef typename Container::value_type vertex_type;
+
+ poly_container_adaptor() :
+ m_container(0),
+ m_index(0),
+ m_closed(false),
+ m_stop(false)
+ {}
+
+ poly_container_adaptor(const Container& data, bool closed) :
+ m_container(&data),
+ m_index(0),
+ m_closed(closed),
+ m_stop(false)
+ {}
+
+ void init(const Container& data, bool closed)
{
- double* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1);
- *pv++ = x;
- *pv = y;
+ m_container = &data;
+ m_index = 0;
+ m_closed = closed;
+ m_stop = false;
}
- // Allows you to modify vertex command. The caller must know
- // the index of the vertex.
- void modify_command(unsigned idx, unsigned cmd)
+ void rewind(unsigned)
{
- m_cmd_blocks[idx >> block_shift][idx & block_mask] = (unsigned char)cmd;
+ m_index = 0;
+ m_stop = false;
}
+ unsigned vertex(double* x, double* y)
+ {
+ if(m_index < m_container->size())
+ {
+ bool first = m_index == 0;
+ const vertex_type& v = (*m_container)[m_index++];
+ *x = v.x;
+ *y = v.y;
+ return first ? path_cmd_move_to : path_cmd_line_to;
+ }
+ *x = *y = 0.0;
+ if(m_closed && !m_stop)
+ {
+ m_stop = true;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ return path_cmd_stop;
+ }
private:
- void allocate_block(unsigned nb);
- unsigned char* storage_ptrs(double** xy_ptr);
- unsigned perceive_polygon_orientation(unsigned idx,
- double xs, double ys,
- unsigned* orientation);
- void reverse_polygon(unsigned start, unsigned end);
-
- private:
- unsigned m_total_vertices;
- unsigned m_total_blocks;
- unsigned m_max_blocks;
- double** m_coord_blocks;
- unsigned char** m_cmd_blocks;
- unsigned m_iterator;
+ const Container* m_container;
+ unsigned m_index;
+ bool m_closed;
+ bool m_stop;
};
- //------------------------------------------------------------------------
- inline unsigned path_storage::vertex(double* x, double* y)
- {
- if(m_iterator >= m_total_vertices) return path_cmd_stop;
- return vertex(m_iterator++, x, y);
- }
- //------------------------------------------------------------------------
- inline unsigned path_storage::prev_vertex(double* x, double* y) const
+ //-----------------------------------------poly_container_reverse_adaptor
+ template<class Container> class poly_container_reverse_adaptor
{
- if(m_total_vertices > 1)
+ public:
+ typedef typename Container::value_type vertex_type;
+
+ poly_container_reverse_adaptor() :
+ m_container(0),
+ m_index(-1),
+ m_closed(false),
+ m_stop(false)
+ {}
+
+ poly_container_reverse_adaptor(const Container& data, bool closed) :
+ m_container(&data),
+ m_index(-1),
+ m_closed(closed),
+ m_stop(false)
+ {}
+
+ void init(const Container& data, bool closed)
{
- return vertex(m_total_vertices - 2, x, y);
+ m_container = &data;
+ m_index = m_container->size() - 1;
+ m_closed = closed;
+ m_stop = false;
}
- return path_cmd_stop;
- }
- //------------------------------------------------------------------------
- inline unsigned path_storage::last_vertex(double* x, double* y) const
- {
- if(m_total_vertices)
+ void rewind(unsigned)
{
- return vertex(m_total_vertices - 1, x, y);
+ m_index = m_container->size() - 1;
+ m_stop = false;
}
- return path_cmd_stop;
- }
- //------------------------------------------------------------------------
- inline void path_storage::rel_to_abs(double* x, double* y) const
- {
- if(m_total_vertices)
+ unsigned vertex(double* x, double* y)
{
- double x2;
- double y2;
- if(is_vertex(vertex(m_total_vertices - 1, &x2, &y2)))
+ if(m_index >= 0)
{
- *x += x2;
- *y += y2;
+ bool first = m_index == int(m_container->size() - 1);
+ const vertex_type& v = (*m_container)[m_index--];
+ *x = v.x;
+ *y = v.y;
+ return first ? path_cmd_move_to : path_cmd_line_to;
}
+ *x = *y = 0.0;
+ if(m_closed && !m_stop)
+ {
+ m_stop = true;
+ return path_cmd_end_poly | path_flags_close;
+ }
+ return path_cmd_stop;
}
- }
- //------------------------------------------------------------------------
- inline unsigned char* path_storage::storage_ptrs(double** xy_ptr)
- {
- unsigned nb = m_total_vertices >> block_shift;
- if(nb >= m_total_blocks)
- {
- allocate_block(nb);
- }
- *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1);
- return m_cmd_blocks[nb] + (m_total_vertices & block_mask);
- }
+ private:
+ const Container* m_container;
+ int m_index;
+ bool m_closed;
+ bool m_stop;
+ };
- //------------------------------------------------------------------------
- inline void path_storage::add_vertex(double x, double y, unsigned cmd)
- {
- double* coord_ptr = 0;
- unsigned char* cmd_ptr = storage_ptrs(&coord_ptr);
- *cmd_ptr = (unsigned char)cmd;
- *coord_ptr++ = x;
- *coord_ptr = y;
- m_total_vertices++;
- }
- //------------------------------------------------------------------------
- inline void path_storage::move_to(double x, double y)
- {
- add_vertex(x, y, path_cmd_move_to);
- }
- //------------------------------------------------------------------------
- inline void path_storage::move_rel(double dx, double dy)
+
+ //--------------------------------------------------------line_adaptor
+ class line_adaptor
+ {
+ public:
+ typedef double value_type;
+
+ line_adaptor() : m_line(m_coord, 2, false) {}
+ line_adaptor(double x1, double y1, double x2, double y2) :
+ m_line(m_coord, 2, false)
+ {
+ m_coord[0] = x1;
+ m_coord[1] = y1;
+ m_coord[2] = x2;
+ m_coord[3] = y2;
+ }
+
+ void init(double x1, double y1, double x2, double y2)
+ {
+ m_coord[0] = x1;
+ m_coord[1] = y1;
+ m_coord[2] = x2;
+ m_coord[3] = y2;
+ m_line.rewind(0);
+ }
+
+ void rewind(unsigned)
+ {
+ m_line.rewind(0);
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ return m_line.vertex(x, y);
+ }
+
+ private:
+ double m_coord[4];
+ poly_plain_adaptor<double> m_line;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //---------------------------------------------------------------path_base
+ // A container to store vertices with their flags.
+ // A path consists of a number of contours separated with "move_to"
+ // commands. The path storage can keep and maintain more than one
+ // path.
+ // To navigate to the beginning of a particular path, use rewind(path_id);
+ // Where path_id is what start_new_path() returns. So, when you call
+ // start_new_path() you need to store its return value somewhere else
+ // to navigate to the path afterwards.
+ //
+ // See also: vertex_source concept
+ //------------------------------------------------------------------------
+ template<class VertexContainer> class path_base
+ {
+ public:
+ typedef VertexContainer container_type;
+ typedef path_base<VertexContainer> self_type;
+
+ //--------------------------------------------------------------------
+ path_base() : m_vertices(), m_iterator(0) {}
+ void remove_all() { m_vertices.remove_all(); m_iterator = 0; }
+ void free_all() { m_vertices.free_all(); m_iterator = 0; }
+
+ // Make path functions
+ //--------------------------------------------------------------------
+ unsigned start_new_path();
+
+ void move_to(double x, double y);
+ void move_rel(double dx, double dy);
+
+ void line_to(double x, double y);
+ void line_rel(double dx, double dy);
+
+ void hline_to(double x);
+ void hline_rel(double dx);
+
+ void vline_to(double y);
+ void vline_rel(double dy);
+
+ void arc_to(double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double x, double y);
+
+ void arc_rel(double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double dx, double dy);
+
+ void curve3(double x_ctrl, double y_ctrl,
+ double x_to, double y_to);
+
+ void curve3_rel(double dx_ctrl, double dy_ctrl,
+ double dx_to, double dy_to);
+
+ void curve3(double x_to, double y_to);
+
+ void curve3_rel(double dx_to, double dy_to);
+
+ void curve4(double x_ctrl1, double y_ctrl1,
+ double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to);
+
+ void curve4_rel(double dx_ctrl1, double dy_ctrl1,
+ double dx_ctrl2, double dy_ctrl2,
+ double dx_to, double dy_to);
+
+ void curve4(double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to);
+
+ void curve4_rel(double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to);
+
+
+ void end_poly(unsigned flags = path_flags_close);
+ void close_polygon(unsigned flags = path_flags_none);
+
+ // Accessors
+ //--------------------------------------------------------------------
+ const container_type& vertices() const { return m_vertices; }
+ container_type& vertices() { return m_vertices; }
+
+ unsigned total_vertices() const;
+
+ void rel_to_abs(double* x, double* y) const;
+
+ unsigned last_vertex(double* x, double* y) const;
+ unsigned prev_vertex(double* x, double* y) const;
+
+ double last_x() const;
+ double last_y() const;
+
+ unsigned vertex(unsigned idx, double* x, double* y) const;
+ unsigned command(unsigned idx) const;
+
+ void modify_vertex(unsigned idx, double x, double y);
+ void modify_vertex(unsigned idx, double x, double y, unsigned cmd);
+ void modify_command(unsigned idx, unsigned cmd);
+
+ // VertexSource interface
+ //--------------------------------------------------------------------
+ void rewind(unsigned path_id);
+ unsigned vertex(double* x, double* y);
+
+ // Arrange the orientation of a polygon, all polygons in a path,
+ // or in all paths. After calling arrange_orientations() or
+ // arrange_orientations_all_paths(), all the polygons will have
+ // the same orientation, i.e. path_flags_cw or path_flags_ccw
+ //--------------------------------------------------------------------
+ unsigned arrange_polygon_orientation(unsigned start, path_flags_e orientation);
+ unsigned arrange_orientations(unsigned path_id, path_flags_e orientation);
+ void arrange_orientations_all_paths(path_flags_e orientation);
+ void invert_polygon(unsigned start);
+
+ // Flip all vertices horizontally or vertically,
+ // between x1 and x2, or between y1 and y2 respectively
+ //--------------------------------------------------------------------
+ void flip_x(double x1, double x2);
+ void flip_y(double y1, double y2);
+
+ // Concatenate path. The path is added as is.
+ //--------------------------------------------------------------------
+ template<class VertexSource>
+ void concat_path(VertexSource& vs, unsigned path_id = 0)
+ {
+ double x, y;
+ unsigned cmd;
+ vs.rewind(path_id);
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ m_vertices.add_vertex(x, y, cmd);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ // Join path. The path is joined with the existing one, that is,
+ // it behaves as if the pen of a plotter was always down (drawing)
+ template<class VertexSource>
+ void join_path(VertexSource& vs, unsigned path_id = 0)
+ {
+ double x, y;
+ unsigned cmd;
+ vs.rewind(path_id);
+ cmd = vs.vertex(&x, &y);
+ if(!is_stop(cmd))
+ {
+ if(is_vertex(cmd))
+ {
+ double x0, y0;
+ unsigned cmd0 = last_vertex(&x0, &y0);
+ if(is_vertex(cmd0))
+ {
+ if(calc_distance(x, y, x0, y0) > vertex_dist_epsilon)
+ {
+ if(is_move_to(cmd)) cmd = path_cmd_line_to;
+ m_vertices.add_vertex(x, y, cmd);
+ }
+ }
+ else
+ {
+ if(is_stop(cmd0))
+ {
+ cmd = path_cmd_move_to;
+ }
+ else
+ {
+ if(is_move_to(cmd)) cmd = path_cmd_line_to;
+ }
+ m_vertices.add_vertex(x, y, cmd);
+ }
+ }
+ while(!is_stop(cmd = vs.vertex(&x, &y)))
+ {
+ m_vertices.add_vertex(x, y, is_move_to(cmd) ?
+ unsigned(path_cmd_line_to) :
+ cmd);
+ }
+ }
+ }
+
+ // Concatenate polygon/polyline.
+ //--------------------------------------------------------------------
+ template<class T> void concat_poly(const T* data,
+ unsigned num_points,
+ bool closed)
+ {
+ poly_plain_adaptor<T> poly(data, num_points, closed);
+ concat_path(poly);
+ }
+
+ // Join polygon/polyline continuously.
+ //--------------------------------------------------------------------
+ template<class T> void join_poly(const T* data,
+ unsigned num_points,
+ bool closed)
+ {
+ poly_plain_adaptor<T> poly(data, num_points, closed);
+ join_path(poly);
+ }
+
+ //--------------------------------------------------------------------
+ void translate(double dx, double dy, unsigned path_id=0);
+ void translate_all_paths(double dx, double dy);
+
+ //--------------------------------------------------------------------
+ template<class Trans>
+ void transform(const Trans& trans, unsigned path_id=0)
+ {
+ unsigned num_ver = m_vertices.total_vertices();
+ for(; path_id < num_ver; path_id++)
+ {
+ double x, y;
+ unsigned cmd = m_vertices.vertex(path_id, &x, &y);
+ if(is_stop(cmd)) break;
+ if(is_vertex(cmd))
+ {
+ trans.transform(&x, &y);
+ m_vertices.modify_vertex(path_id, x, y);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ template<class Trans>
+ void transform_all_paths(const Trans& trans)
+ {
+ unsigned idx;
+ unsigned num_ver = m_vertices.total_vertices();
+ for(idx = 0; idx < num_ver; idx++)
+ {
+ double x, y;
+ if(is_vertex(m_vertices.vertex(idx, &x, &y)))
+ {
+ trans.transform(&x, &y);
+ m_vertices.modify_vertex(idx, x, y);
+ }
+ }
+ }
+
+
+
+ private:
+ unsigned perceive_polygon_orientation(unsigned start, unsigned end);
+ void invert_polygon(unsigned start, unsigned end);
+
+ VertexContainer m_vertices;
+ unsigned m_iterator;
+ };
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ unsigned path_base<VC>::start_new_path()
+ {
+ if(!is_stop(m_vertices.last_command()))
+ {
+ m_vertices.add_vertex(0.0, 0.0, path_cmd_stop);
+ }
+ return m_vertices.total_vertices();
+ }
+
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::rel_to_abs(double* x, double* y) const
+ {
+ if(m_vertices.total_vertices())
+ {
+ double x2;
+ double y2;
+ if(is_vertex(m_vertices.last_vertex(&x2, &y2)))
+ {
+ *x += x2;
+ *y += y2;
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::move_to(double x, double y)
+ {
+ m_vertices.add_vertex(x, y, path_cmd_move_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::move_rel(double dx, double dy)
{
rel_to_abs(&dx, &dy);
- add_vertex(dx, dy, path_cmd_move_to);
+ m_vertices.add_vertex(dx, dy, path_cmd_move_to);
}
//------------------------------------------------------------------------
- inline void path_storage::line_to(double x, double y)
+ template<class VC>
+ inline void path_base<VC>::line_to(double x, double y)
{
- add_vertex(x, y, path_cmd_line_to);
+ m_vertices.add_vertex(x, y, path_cmd_line_to);
}
//------------------------------------------------------------------------
- inline void path_storage::line_rel(double dx, double dy)
+ template<class VC>
+ inline void path_base<VC>::line_rel(double dx, double dy)
{
rel_to_abs(&dx, &dy);
- add_vertex(dx, dy, path_cmd_line_to);
+ m_vertices.add_vertex(dx, dy, path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::hline_to(double x)
+ {
+ m_vertices.add_vertex(x, last_y(), path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::hline_rel(double dx)
+ {
+ double dy = 0;
+ rel_to_abs(&dx, &dy);
+ m_vertices.add_vertex(dx, dy, path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::vline_to(double y)
+ {
+ m_vertices.add_vertex(last_x(), y, path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::vline_rel(double dy)
+ {
+ double dx = 0;
+ rel_to_abs(&dx, &dy);
+ m_vertices.add_vertex(dx, dy, path_cmd_line_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::arc_to(double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double x, double y)
+ {
+ if(m_vertices.total_vertices() && is_vertex(m_vertices.last_command()))
+ {
+ const double epsilon = 1e-30;
+ double x0 = 0.0;
+ double y0 = 0.0;
+ m_vertices.last_vertex(&x0, &y0);
+
+ rx = fabs(rx);
+ ry = fabs(ry);
+
+ // Ensure radii are valid
+ //-------------------------
+ if(rx < epsilon || ry < epsilon)
+ {
+ line_to(x, y);
+ return;
+ }
+
+ if(calc_distance(x0, y0, x, y) < epsilon)
+ {
+ // If the endpoints (x, y) and (x0, y0) are identical, then this
+ // is equivalent to omitting the elliptical arc segment entirely.
+ return;
+ }
+ bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y);
+ if(a.radii_ok())
+ {
+ join_path(a);
+ }
+ else
+ {
+ line_to(x, y);
+ }
+ }
+ else
+ {
+ move_to(x, y);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::arc_rel(double rx, double ry,
+ double angle,
+ bool large_arc_flag,
+ bool sweep_flag,
+ double dx, double dy)
+ {
+ rel_to_abs(&dx, &dy);
+ arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve3(double x_ctrl, double y_ctrl,
+ double x_to, double y_to)
+ {
+ m_vertices.add_vertex(x_ctrl, y_ctrl, path_cmd_curve3);
+ m_vertices.add_vertex(x_to, y_to, path_cmd_curve3);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve3_rel(double dx_ctrl, double dy_ctrl,
+ double dx_to, double dy_to)
+ {
+ rel_to_abs(&dx_ctrl, &dy_ctrl);
+ rel_to_abs(&dx_to, &dy_to);
+ m_vertices.add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3);
+ m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve3);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve3(double x_to, double y_to)
+ {
+ double x0;
+ double y0;
+ if(is_vertex(m_vertices.last_vertex(&x0, &y0)))
+ {
+ double x_ctrl;
+ double y_ctrl;
+ unsigned cmd = m_vertices.prev_vertex(&x_ctrl, &y_ctrl);
+ if(is_curve(cmd))
+ {
+ x_ctrl = x0 + x0 - x_ctrl;
+ y_ctrl = y0 + y0 - y_ctrl;
+ }
+ else
+ {
+ x_ctrl = x0;
+ y_ctrl = y0;
+ }
+ curve3(x_ctrl, y_ctrl, x_to, y_to);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve3_rel(double dx_to, double dy_to)
+ {
+ rel_to_abs(&dx_to, &dy_to);
+ curve3(dx_to, dy_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve4(double x_ctrl1, double y_ctrl1,
+ double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to)
+ {
+ m_vertices.add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4);
+ m_vertices.add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4);
+ m_vertices.add_vertex(x_to, y_to, path_cmd_curve4);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve4_rel(double dx_ctrl1, double dy_ctrl1,
+ double dx_ctrl2, double dy_ctrl2,
+ double dx_to, double dy_to)
+ {
+ rel_to_abs(&dx_ctrl1, &dy_ctrl1);
+ rel_to_abs(&dx_ctrl2, &dy_ctrl2);
+ rel_to_abs(&dx_to, &dy_to);
+ m_vertices.add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4);
+ m_vertices.add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4);
+ m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve4);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve4(double x_ctrl2, double y_ctrl2,
+ double x_to, double y_to)
+ {
+ double x0;
+ double y0;
+ if(is_vertex(last_vertex(&x0, &y0)))
+ {
+ double x_ctrl1;
+ double y_ctrl1;
+ unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1);
+ if(is_curve(cmd))
+ {
+ x_ctrl1 = x0 + x0 - x_ctrl1;
+ y_ctrl1 = y0 + y0 - y_ctrl1;
+ }
+ else
+ {
+ x_ctrl1 = x0;
+ y_ctrl1 = y0;
+ }
+ curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::curve4_rel(double dx_ctrl2, double dy_ctrl2,
+ double dx_to, double dy_to)
+ {
+ rel_to_abs(&dx_ctrl2, &dy_ctrl2);
+ rel_to_abs(&dx_to, &dy_to);
+ curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::end_poly(unsigned flags)
+ {
+ if(is_vertex(m_vertices.last_command()))
+ {
+ m_vertices.add_vertex(0.0, 0.0, path_cmd_end_poly | flags);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::close_polygon(unsigned flags)
+ {
+ end_poly(path_flags_close | flags);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::total_vertices() const
+ {
+ return m_vertices.total_vertices();
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::last_vertex(double* x, double* y) const
+ {
+ return m_vertices.last_vertex(x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::prev_vertex(double* x, double* y) const
+ {
+ return m_vertices.prev_vertex(x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline double path_base<VC>::last_x() const
+ {
+ return m_vertices.last_x();
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline double path_base<VC>::last_y() const
+ {
+ return m_vertices.last_y();
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::vertex(unsigned idx, double* x, double* y) const
+ {
+ return m_vertices.vertex(idx, x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::command(unsigned idx) const
+ {
+ return m_vertices.command(idx);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::modify_vertex(unsigned idx, double x, double y)
+ {
+ m_vertices.modify_vertex(idx, x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::modify_vertex(unsigned idx, double x, double y, unsigned cmd)
+ {
+ m_vertices.modify_vertex(idx, x, y, cmd);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::modify_command(unsigned idx, unsigned cmd)
+ {
+ m_vertices.modify_command(idx, cmd);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline void path_base<VC>::rewind(unsigned path_id)
+ {
+ m_iterator = path_id;
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ inline unsigned path_base<VC>::vertex(double* x, double* y)
+ {
+ if(m_iterator >= m_vertices.total_vertices()) return path_cmd_stop;
+ return m_vertices.vertex(m_iterator++, x, y);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ unsigned path_base<VC>::perceive_polygon_orientation(unsigned start,
+ unsigned end)
+ {
+ // Calculate signed area (double area to be exact)
+ //---------------------
+ unsigned np = end - start;
+ double area = 0.0;
+ unsigned i;
+ for(i = 0; i < np; i++)
+ {
+ double x1, y1, x2, y2;
+ m_vertices.vertex(start + i, &x1, &y1);
+ m_vertices.vertex(start + (i + 1) % np, &x2, &y2);
+ area += x1 * y2 - y1 * x2;
+ }
+ return (area < 0.0) ? path_flags_cw : path_flags_ccw;
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::invert_polygon(unsigned start, unsigned end)
+ {
+ unsigned i;
+ unsigned tmp_cmd = m_vertices.command(start);
+
+ --end; // Make "end" inclusive
+
+ // Shift all commands to one position
+ for(i = start; i < end; i++)
+ {
+ m_vertices.modify_command(i, m_vertices.command(i + 1));
+ }
+
+ // Assign starting command to the ending command
+ m_vertices.modify_command(end, tmp_cmd);
+
+ // Reverse the polygon
+ while(end > start)
+ {
+ m_vertices.swap_vertices(start++, end--);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::invert_polygon(unsigned start)
+ {
+ // Skip all non-vertices at the beginning
+ while(start < m_vertices.total_vertices() &&
+ !is_vertex(m_vertices.command(start))) ++start;
+
+ // Skip all insignificant move_to
+ while(start+1 < m_vertices.total_vertices() &&
+ is_move_to(m_vertices.command(start)) &&
+ is_move_to(m_vertices.command(start+1))) ++start;
+
+ // Find the last vertex
+ unsigned end = start + 1;
+ while(end < m_vertices.total_vertices() &&
+ !is_next_poly(m_vertices.command(end))) ++end;
+
+ invert_polygon(start, end);
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ unsigned path_base<VC>::arrange_polygon_orientation(unsigned start,
+ path_flags_e orientation)
+ {
+ if(orientation == path_flags_none) return start;
+
+ // Skip all non-vertices at the beginning
+ while(start < m_vertices.total_vertices() &&
+ !is_vertex(m_vertices.command(start))) ++start;
+
+ // Skip all insignificant move_to
+ while(start+1 < m_vertices.total_vertices() &&
+ is_move_to(m_vertices.command(start)) &&
+ is_move_to(m_vertices.command(start+1))) ++start;
+
+ // Find the last vertex
+ unsigned end = start + 1;
+ while(end < m_vertices.total_vertices() &&
+ !is_next_poly(m_vertices.command(end))) ++end;
+
+ if(end - start > 2)
+ {
+ if(perceive_polygon_orientation(start, end) != unsigned(orientation))
+ {
+ // Invert polygon, set orientation flag, and skip all end_poly
+ invert_polygon(start, end);
+ unsigned cmd;
+ while(end < m_vertices.total_vertices() &&
+ is_end_poly(cmd = m_vertices.command(end)))
+ {
+ m_vertices.modify_command(end++, set_orientation(cmd, orientation));
+ }
+ }
+ }
+ return end;
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ unsigned path_base<VC>::arrange_orientations(unsigned start,
+ path_flags_e orientation)
+ {
+ if(orientation != path_flags_none)
+ {
+ while(start < m_vertices.total_vertices())
+ {
+ start = arrange_polygon_orientation(start, orientation);
+ if(is_stop(m_vertices.command(start)))
+ {
+ ++start;
+ break;
+ }
+ }
+ }
+ return start;
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::arrange_orientations_all_paths(path_flags_e orientation)
+ {
+ if(orientation != path_flags_none)
+ {
+ unsigned start = 0;
+ while(start < m_vertices.total_vertices())
+ {
+ start = arrange_orientations(start, orientation);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::flip_x(double x1, double x2)
+ {
+ unsigned i;
+ double x, y;
+ for(i = 0; i < m_vertices.total_vertices(); i++)
+ {
+ unsigned cmd = m_vertices.vertex(i, &x, &y);
+ if(is_vertex(cmd))
+ {
+ m_vertices.modify_vertex(i, x2 - x + x1, y);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::flip_y(double y1, double y2)
+ {
+ unsigned i;
+ double x, y;
+ for(i = 0; i < m_vertices.total_vertices(); i++)
+ {
+ unsigned cmd = m_vertices.vertex(i, &x, &y);
+ if(is_vertex(cmd))
+ {
+ m_vertices.modify_vertex(i, x, y2 - y + y1);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::translate(double dx, double dy, unsigned path_id)
+ {
+ unsigned num_ver = m_vertices.total_vertices();
+ for(; path_id < num_ver; path_id++)
+ {
+ double x, y;
+ unsigned cmd = m_vertices.vertex(path_id, &x, &y);
+ if(is_stop(cmd)) break;
+ if(is_vertex(cmd))
+ {
+ x += dx;
+ y += dy;
+ m_vertices.modify_vertex(path_id, x, y);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ template<class VC>
+ void path_base<VC>::translate_all_paths(double dx, double dy)
+ {
+ unsigned idx;
+ unsigned num_ver = m_vertices.total_vertices();
+ for(idx = 0; idx < num_ver; idx++)
+ {
+ double x, y;
+ if(is_vertex(m_vertices.vertex(idx, &x, &y)))
+ {
+ x += dx;
+ y += dy;
+ m_vertices.modify_vertex(idx, x, y);
+ }
+ }
}
+
+ //-----------------------------------------------------vertex_stl_storage
+ template<class Container> class vertex_stl_storage
+ {
+ public:
+ typedef typename Container::value_type vertex_type;
+ typedef typename vertex_type::value_type value_type;
+
+ void remove_all() { m_vertices.clear(); }
+ void free_all() { m_vertices.clear(); }
+
+ void add_vertex(double x, double y, unsigned cmd)
+ {
+ m_vertices.push_back(vertex_type(value_type(x),
+ value_type(y),
+ int8u(cmd)));
+ }
+
+ void modify_vertex(unsigned idx, double x, double y)
+ {
+ vertex_type& v = m_vertices[idx];
+ v.x = value_type(x);
+ v.y = value_type(y);
+ }
+
+ void modify_vertex(unsigned idx, double x, double y, unsigned cmd)
+ {
+ vertex_type& v = m_vertices[idx];
+ v.x = value_type(x);
+ v.y = value_type(y);
+ v.cmd = int8u(cmd);
+ }
+
+ void modify_command(unsigned idx, unsigned cmd)
+ {
+ m_vertices[idx].cmd = int8u(cmd);
+ }
+
+ void swap_vertices(unsigned v1, unsigned v2)
+ {
+ vertex_type t = m_vertices[v1];
+ m_vertices[v1] = m_vertices[v2];
+ m_vertices[v2] = t;
+ }
+
+ unsigned last_command() const
+ {
+ return m_vertices.size() ?
+ m_vertices[m_vertices.size() - 1].cmd :
+ path_cmd_stop;
+ }
+
+ unsigned last_vertex(double* x, double* y) const
+ {
+ if(m_vertices.size() == 0)
+ {
+ *x = *y = 0.0;
+ return path_cmd_stop;
+ }
+ return vertex(m_vertices.size() - 1, x, y);
+ }
+
+ unsigned prev_vertex(double* x, double* y) const
+ {
+ if(m_vertices.size() < 2)
+ {
+ *x = *y = 0.0;
+ return path_cmd_stop;
+ }
+ return vertex(m_vertices.size() - 2, x, y);
+ }
+
+ double last_x() const
+ {
+ return m_vertices.size() ? m_vertices[m_vertices.size() - 1].x : 0.0;
+ }
+
+ double last_y() const
+ {
+ return m_vertices.size() ? m_vertices[m_vertices.size() - 1].y : 0.0;
+ }
+
+ unsigned total_vertices() const
+ {
+ return m_vertices.size();
+ }
+
+ unsigned vertex(unsigned idx, double* x, double* y) const
+ {
+ const vertex_type& v = m_vertices[idx];
+ *x = v.x;
+ *y = v.y;
+ return v.cmd;
+ }
+
+ unsigned command(unsigned idx) const
+ {
+ return m_vertices[idx].cmd;
+ }
+
+ private:
+ Container m_vertices;
+ };
+
+ //-----------------------------------------------------------path_storage
+ typedef path_base<vertex_block_storage<double> > path_storage;
+
+ // Example of declarations path_storage with pod_bvector as a container
+ //-----------------------------------------------------------------------
+ //typedef path_base<vertex_stl_storage<pod_bvector<vertex_d> > > path_storage;
+
}
+// Example of declarations path_storage with std::vector as a container
+//---------------------------------------------------------------------------
+//#include <vector>
+//namespace agg
+//{
+// typedef path_base<vertex_stl_storage<std::vector<vertex_d> > > stl_path_storage;
+//}
+
+
+
+
#endif
Modified: incubator/ooo/trunk/main/agg/inc/agg_path_storage_integer.h
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/agg/inc/agg_path_storage_integer.h?rev=1184758&r1=1184757&r2=1184758&view=diff
==============================================================================
--- incubator/ooo/trunk/main/agg/inc/agg_path_storage_integer.h (original)
+++ incubator/ooo/trunk/main/agg/inc/agg_path_storage_integer.h Sun Oct 16 04:13:16 2011
@@ -1,5 +1,5 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.3
+// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
@@ -21,7 +21,6 @@
namespace agg
{
-
//---------------------------------------------------------vertex_integer
template<class T, unsigned CoordShift=6> struct vertex_integer
{
@@ -33,10 +32,10 @@ namespace agg
cmd_curve4 = 3
};
- enum
+ enum coord_scale_e
{
coord_shift = CoordShift,
- coord_mult = 1 << coord_shift
+ coord_scale = 1 << coord_shift
};
T x,y;
@@ -49,8 +48,8 @@ namespace agg
double dx=0, double dy=0,
double scale=1.0) const
{
- *x_ = dx + (double(x >> 1) / coord_mult) * scale;
- *y_ = dy + (double(y >> 1) / coord_mult) * scale;
+ *x_ = dx + (double(x >> 1) / coord_scale) * scale;
+ *y_ = dy + (double(y >> 1) / coord_scale) * scale;
switch(((y & 1) << 1) | (x & 1))
{
case cmd_move_to: return path_cmd_move_to;
@@ -67,6 +66,7 @@ namespace agg
template<class T, unsigned CoordShift=6> class path_storage_integer
{
public:
+ typedef T value_type;
typedef vertex_integer<T, CoordShift> vertex_integer_type;
//--------------------------------------------------------------------
@@ -110,12 +110,9 @@ namespace agg
//--------------------------------------------------------------------
unsigned size() const { return m_storage.size(); }
- unsigned vertex(unsigned idx, T* x, T* y) const
+ unsigned vertex(unsigned idx, double* x, double* y) const
{
- const vertex_integer_type& v = m_storage[idx];
- *x = v.x >> 1;
- *y = v.y >> 1;
- return ((v.y & 1) << 1) | (v.x & 1);
+ return m_storage[idx].vertex(x, y);
}
//--------------------------------------------------------------------
@@ -130,7 +127,6 @@ namespace agg
}
}
-
//--------------------------------------------------------------------
void rewind(unsigned)
{
@@ -191,11 +187,10 @@ namespace agg
return bounds;
}
-
private:
- pod_deque<vertex_integer_type, 6> m_storage;
- unsigned m_vertex_idx;
- bool m_closed;
+ pod_bvector<vertex_integer_type, 6> m_storage;
+ unsigned m_vertex_idx;
+ bool m_closed;
};
Modified: incubator/ooo/trunk/main/agg/inc/agg_pattern_filters_rgba.h
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/agg/inc/agg_pattern_filters_rgba.h?rev=1184758&r1=1184757&r2=1184758&view=diff
==============================================================================
--- incubator/ooo/trunk/main/agg/inc/agg_pattern_filters_rgba.h (original)
+++ incubator/ooo/trunk/main/agg/inc/agg_pattern_filters_rgba.h Sun Oct 16 04:13:16 2011
@@ -1,5 +1,5 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.3
+// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
@@ -67,7 +67,7 @@ namespace agg
color_type* p, int x, int y)
{
calc_type r, g, b, a;
- r = g = b = a = line_subpixel_size * line_subpixel_size / 2;
+ r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2;
calc_type weight;
int x_lr = x >> line_subpixel_shift;
@@ -77,8 +77,8 @@ namespace agg
y &= line_subpixel_mask;
const color_type* ptr = buf[y_lr] + x_lr;
- weight = (line_subpixel_size - x) *
- (line_subpixel_size - y);
+ weight = (line_subpixel_scale - x) *
+ (line_subpixel_scale - y);
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
@@ -86,7 +86,7 @@ namespace agg
++ptr;
- weight = x * (line_subpixel_size - y);
+ weight = x * (line_subpixel_scale - y);
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
@@ -94,7 +94,7 @@ namespace agg
ptr = buf[y_lr + 1] + x_lr;
- weight = (line_subpixel_size - x) * y;
+ weight = (line_subpixel_scale - x) * y;
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
Modified: incubator/ooo/trunk/main/agg/inc/agg_pixfmt_amask_adaptor.h
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/agg/inc/agg_pixfmt_amask_adaptor.h?rev=1184758&r1=1184757&r2=1184758&view=diff
==============================================================================
--- incubator/ooo/trunk/main/agg/inc/agg_pixfmt_amask_adaptor.h (original)
+++ incubator/ooo/trunk/main/agg/inc/agg_pixfmt_amask_adaptor.h Sun Oct 16 04:13:16 2011
@@ -1,5 +1,5 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.3
+// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
@@ -18,6 +18,7 @@
#include <string.h>
+#include "agg_array.h"
#include "agg_rendering_buffer.h"
@@ -29,47 +30,50 @@ namespace agg
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
+ typedef typename pixfmt_type::row_data row_data;
typedef AlphaMask amask_type;
typedef typename amask_type::cover_type cover_type;
private:
- enum { span_extra_tail = 256 };
+ enum span_extra_tail_e { span_extra_tail = 256 };
void realloc_span(unsigned len)
{
- if(len > m_max_len)
+ if(len > m_span.size())
{
- delete [] m_span;
- m_span = new cover_type[m_max_len = len + span_extra_tail];
+ m_span.resize(len + span_extra_tail);
}
}
void init_span(unsigned len)
{
realloc_span(len);
-
- // ATTN! May work incorrectly if cover_type is more that one byte
- memset(m_span, amask_type::cover_full, len * sizeof(cover_type));
+ memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
}
void init_span(unsigned len, const cover_type* covers)
{
realloc_span(len);
- memcpy(m_span, covers, len * sizeof(cover_type));
+ memcpy(&m_span[0], covers, len * sizeof(cover_type));
}
public:
- ~pixfmt_amask_adaptor() { delete [] m_span; }
-
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) :
- m_pixf(&pixf), m_mask(&mask), m_span(0), m_max_len(0)
+ m_pixf(&pixf), m_mask(&mask), m_span()
{}
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
//--------------------------------------------------------------------
+ template<class PixFmt2>
+ bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2)
+ {
+ return m_pixf->attach(pixf, x1, y1, x2, y2);
+ }
+
+ //--------------------------------------------------------------------
unsigned width() const { return m_pixf->width(); }
unsigned height() const { return m_pixf->height(); }
@@ -97,8 +101,8 @@ namespace agg
const color_type& c)
{
realloc_span(len);
- m_mask->fill_hspan(x, y, m_span, len);
- m_pixf->blend_solid_hspan(x, y, len, c, m_span);
+ m_mask->fill_hspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
@@ -108,8 +112,8 @@ namespace agg
cover_type cover)
{
init_span(len);
- m_mask->combine_hspan(x, y, m_span, len);
- m_pixf->blend_solid_hspan(x, y, len, c, m_span);
+ m_mask->combine_hspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
@@ -118,8 +122,8 @@ namespace agg
const color_type& c)
{
realloc_span(len);
- m_mask->fill_vspan(x, y, m_span, len);
- m_pixf->blend_solid_vspan(x, y, len, c, m_span);
+ m_mask->fill_vspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
@@ -129,8 +133,8 @@ namespace agg
cover_type cover)
{
init_span(len);
- m_mask->combine_vspan(x, y, m_span, len);
- m_pixf->blend_solid_vspan(x, y, len, c, m_span);
+ m_mask->combine_vspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
@@ -150,8 +154,8 @@ namespace agg
const cover_type* covers)
{
init_span(len, covers);
- m_mask->combine_hspan(x, y, m_span, len);
- m_pixf->blend_solid_hspan(x, y, len, c, m_span);
+ m_mask->combine_hspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
@@ -162,10 +166,26 @@ namespace agg
const cover_type* covers)
{
init_span(len, covers);
- m_mask->combine_vspan(x, y, m_span, len);
- m_pixf->blend_solid_vspan(x, y, len, c, m_span);
+ m_mask->combine_vspan(x, y, &m_span[0], len);
+ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
+ }
+
+
+ //--------------------------------------------------------------------
+ void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
+ {
+ realloc_span(len);
+ m_mask->fill_hspan(x, y, &m_span[0], len);
+ m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full);
}
+ //--------------------------------------------------------------------
+ void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
+ {
+ realloc_span(len);
+ m_mask->fill_vspan(x, y, &m_span[0], len);
+ m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full);
+ }
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
@@ -177,14 +197,14 @@ namespace agg
if(covers)
{
init_span(len, covers);
- m_mask->combine_hspan(x, y, m_span, len);
+ m_mask->combine_hspan(x, y, &m_span[0], len);
}
else
{
realloc_span(len);
- m_mask->fill_hspan(x, y, m_span, len);
+ m_mask->fill_hspan(x, y, &m_span[0], len);
}
- m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover);
+ m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
}
@@ -198,65 +218,20 @@ namespace agg
if(covers)
{
init_span(len, covers);
- m_mask->combine_vspan(x, y, m_span, len);
- }
- else
- {
- realloc_span(len);
- m_mask->fill_vspan(x, y, m_span, len);
- }
- m_pixf->blend_color_vspan(x, y, len, colors, m_span, cover);
- }
-
-
- //--------------------------------------------------------------------
- void blend_opaque_color_hspan(int x, int y,
- unsigned len,
- const color_type* colors,
- const cover_type* covers,
- cover_type cover = cover_full)
- {
- if(covers)
- {
- init_span(len, covers);
- m_mask->combine_hspan(x, y, m_span, len);
- }
- else
- {
- realloc_span(len);
- m_mask->fill_hspan(x, y, m_span, len);
- }
- m_pixf->blend_opaque_color_hspan(x, y, len, colors, m_span, cover);
- }
-
-
- //--------------------------------------------------------------------
- void blend_opaque_color_vspan(int x, int y,
- unsigned len,
- const color_type* colors,
- const cover_type* covers,
- cover_type cover = cover_full)
- {
- if(covers)
- {
- init_span(len, covers);
- m_mask->combine_vspan(x, y, m_span, len);
+ m_mask->combine_vspan(x, y, &m_span[0], len);
}
else
{
realloc_span(len);
- m_mask->fill_vspan(x, y, m_span, len);
+ m_mask->fill_vspan(x, y, &m_span[0], len);
}
- m_pixf->blend_opaque_color_vspan(x, y, len, colors, m_span, cover);
+ m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
}
-
private:
- pixfmt_type* m_pixf;
- const amask_type* m_mask;
-
- cover_type* m_span;
- unsigned m_max_len;
+ pixfmt_type* m_pixf;
+ const amask_type* m_mask;
+ pod_array<cover_type> m_span;
};
}