1
2 //----------------------------------------------------------------------------
3 // Anti-Grain Geometry - Version 2.3
4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5 //
6 // Permission to copy, use, modify, sell and distribute this software
7 // is granted provided this copyright notice appears in all copies.
8 // This software is provided "as is" without express or implied
9 // warranty, and with no claim as to its suitability for any purpose.
10 //
11 //----------------------------------------------------------------------------
12 // Contact: mcseem@antigrain.com
13 // mcseemagg@yahoo.com
14 // http://www.antigrain.com
15 //----------------------------------------------------------------------------
16 #ifndef AGG_PATH_STORAGE_INCLUDED
17 #define AGG_PATH_STORAGE_INCLUDED
18 #include "agg_basics.h"
19 namespace pdfium
20 {
21 namespace agg
22 {
23 class path_storage
24 {
25 enum block_scale_e {
26 block_shift = 8,
27 block_size = 1 << block_shift,
28 block_mask = block_size - 1,
29 block_pool = 256
30 };
31 public:
32 class vertex_source
33 {
34 public:
vertex_source()35 vertex_source() {}
vertex_source(const path_storage & p)36 vertex_source(const path_storage& p) : m_path(&p), m_vertex_idx(0) {}
rewind(unsigned path_id)37 void rewind(unsigned path_id)
38 {
39 m_vertex_idx = path_id;
40 }
vertex(float * x,float * y)41 unsigned vertex(float* x, float* y)
42 {
43 return (m_vertex_idx < m_path->total_vertices())
44 ? m_path->vertex(m_vertex_idx++, x, y)
45 : static_cast<unsigned>(path_cmd_stop);
46 }
47 private:
48 const path_storage* m_path;
49 unsigned m_vertex_idx;
50 };
51 ~path_storage();
52 path_storage();
53 path_storage(path_storage&& other);
54 path_storage& operator=(path_storage&&) = delete;
55 path_storage(const path_storage&) = delete;
56 path_storage& operator=(const path_storage&) = delete;
57 unsigned last_vertex(float* x, float* y) const;
58 unsigned prev_vertex(float* x, float* y) const;
59 void move_to(float x, float y);
60 void line_to(float x, float y);
61 void curve4(float x_ctrl1, float y_ctrl1,
62 float x_ctrl2, float y_ctrl2,
63 float x_to, float y_to);
64 template<class VertexSource>
65 void add_path(VertexSource& vs,
66 unsigned path_id = 0,
67 bool solid_path = true)
68 {
69 float x, y;
70 unsigned cmd;
71 vs.rewind(path_id);
72 while(!is_stop(cmd = vs.vertex(&x, &y))) {
73 if(is_move_to(cmd) && solid_path && m_total_vertices) {
74 cmd = path_cmd_line_to;
75 }
76 add_vertex(x, y, cmd);
77 }
78 }
total_vertices()79 unsigned total_vertices() const
80 {
81 return m_total_vertices;
82 }
vertex(unsigned idx,float * x,float * y)83 unsigned vertex(unsigned idx, float* x, float* y) const
84 {
85 unsigned nb = idx >> block_shift;
86 const float* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1);
87 *x = *pv++;
88 *y = *pv;
89 return m_cmd_blocks[nb][idx & block_mask];
90 }
command(unsigned idx)91 unsigned command(unsigned idx) const
92 {
93 return m_cmd_blocks[idx >> block_shift][idx & block_mask];
94 }
getflag(unsigned idx)95 unsigned getflag(unsigned idx) const
96 {
97 return m_cmd_blocks[idx >> block_shift][idx & block_mask] & path_flags_jr;
98 }
99 void rewind(unsigned path_id);
100 unsigned vertex(float* x, float* y);
101 void add_vertex(float x, float y, unsigned cmd);
102 void end_poly();
103 private:
104 void allocate_block(unsigned nb);
105 unsigned char* storage_ptrs(float** xy_ptr);
106 private:
107 unsigned m_total_vertices = 0;
108 unsigned m_total_blocks = 0;
109 unsigned m_max_blocks = 0;
110 float** m_coord_blocks = nullptr;
111 unsigned char** m_cmd_blocks = nullptr;
112 unsigned m_iterator = 0;
113 };
vertex(float * x,float * y)114 inline unsigned path_storage::vertex(float* x, float* y)
115 {
116 if(m_iterator >= m_total_vertices) {
117 return path_cmd_stop;
118 }
119 return vertex(m_iterator++, x, y);
120 }
prev_vertex(float * x,float * y)121 inline unsigned path_storage::prev_vertex(float* x, float* y) const
122 {
123 if(m_total_vertices > 1) {
124 return vertex(m_total_vertices - 2, x, y);
125 }
126 return path_cmd_stop;
127 }
last_vertex(float * x,float * y)128 inline unsigned path_storage::last_vertex(float* x, float* y) const
129 {
130 if(m_total_vertices) {
131 return vertex(m_total_vertices - 1, x, y);
132 }
133 return path_cmd_stop;
134 }
storage_ptrs(float ** xy_ptr)135 inline unsigned char* path_storage::storage_ptrs(float** xy_ptr)
136 {
137 unsigned nb = m_total_vertices >> block_shift;
138 if(nb >= m_total_blocks) {
139 allocate_block(nb);
140 }
141 *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1);
142 return m_cmd_blocks[nb] + (m_total_vertices & block_mask);
143 }
add_vertex(float x,float y,unsigned cmd)144 inline void path_storage::add_vertex(float x, float y, unsigned cmd)
145 {
146 float* coord_ptr = 0;
147 unsigned char* cmd_ptr = storage_ptrs(&coord_ptr);
148 *cmd_ptr = (unsigned char)cmd;
149 *coord_ptr++ = x;
150 *coord_ptr = y;
151 m_total_vertices++;
152 }
move_to(float x,float y)153 inline void path_storage::move_to(float x, float y)
154 {
155 add_vertex(x, y, path_cmd_move_to);
156 }
line_to(float x,float y)157 inline void path_storage::line_to(float x, float y)
158 {
159 add_vertex(x, y, path_cmd_line_to);
160 }
161 }
162 } // namespace pdfium
163 #endif
164