1 | /*! |
2 | * \file partitioned_tessellated_path.hpp |
3 | * \brief file partitioned_tessellated_path.hpp |
4 | * |
5 | * Copyright 2019 by Intel. |
6 | * |
7 | * Contact: kevin.rogovin@gmail.com |
8 | * |
9 | * This Source Code Form is subject to the |
10 | * terms of the Mozilla Public License, v. 2.0. |
11 | * If a copy of the MPL was not distributed with |
12 | * this file, You can obtain one at |
13 | * http://mozilla.org/MPL/2.0/. |
14 | * |
15 | * \author Kevin Rogovin <kevin.rogovin@gmail.com> |
16 | * |
17 | */ |
18 | |
19 | |
20 | #ifndef FASTUIDRAW_PARTITIONED_TESSELLATED_PATH_HPP |
21 | #define FASTUIDRAW_PARTITIONED_TESSELLATED_PATH_HPP |
22 | |
23 | #include <fastuidraw/util/matrix.hpp> |
24 | #include <fastuidraw/util/vecN.hpp> |
25 | #include <fastuidraw/util/c_array.hpp> |
26 | #include <fastuidraw/util/util.hpp> |
27 | #include <fastuidraw/util/rect.hpp> |
28 | #include <fastuidraw/tessellated_path.hpp> |
29 | #include <fastuidraw/path_enums.hpp> |
30 | #include <fastuidraw/path_effect.hpp> |
31 | |
32 | namespace fastuidraw { |
33 | |
34 | /*!\addtogroup Paths |
35 | * @{ |
36 | */ |
37 | |
38 | /*! |
39 | * \brief |
40 | * A PartitionedTessellatedPath represents partitioning a \ref |
41 | * TessellatedPath for quick computation of what \ref |
42 | * TessellatedPath::segment intersect a region. |
43 | * |
44 | * The partitioning creates reectangular regions of the source |
45 | * \ref TessellatedPath that are disjoint. One side effect of |
46 | * that is that a \ref TessellatedPath::segment value from the |
47 | * source \ref TessellatedPath may be split into multiple \ref |
48 | * TessellatedPath::segment values. |
49 | */ |
50 | class PartitionedTessellatedPath: |
51 | public reference_counted<PartitionedTessellatedPath>::non_concurrent |
52 | { |
53 | public: |
54 | /*! |
55 | * A \ref segment is the same as found in \ref TessellatedPath |
56 | */ |
57 | typedef TessellatedPath::segment segment; |
58 | |
59 | /*! |
60 | * A \ref segment_chain is the same as found in \ref TessellatedPath |
61 | */ |
62 | typedef TessellatedPath::segment_chain segment_chain; |
63 | |
64 | /*! |
65 | * A \ref join is the same as found in \ref TessellatedPath |
66 | */ |
67 | typedef TessellatedPath::join join; |
68 | |
69 | /*! |
70 | * A \ref cap is the same as found in \ref TessellatedPath |
71 | */ |
72 | typedef TessellatedPath::cap cap; |
73 | |
74 | /*! |
75 | * \brief |
76 | * A Subset represents a handle to a portion of a \ref |
77 | * PartitionedTessellatedPath. The handle is invalid once the |
78 | * \ref PartitionedTessellatedPath from which it comes goes |
79 | * out of scope. Do not save these handle values without also |
80 | * saving a handle of the \ref PartitionedTessellatedPath |
81 | * from which they come. |
82 | */ |
83 | class Subset |
84 | { |
85 | private: |
86 | typedef bool (Subset::*unspecified_bool_type)(void) const; |
87 | |
88 | public: |
89 | /*! |
90 | * Ctor to initialize value to "null" handle. |
91 | */ |
92 | Subset(void): |
93 | m_d(nullptr) |
94 | {} |
95 | |
96 | /*! |
97 | * Allows one to legally write to test if Subset |
98 | * is a null-handle: |
99 | * \code |
100 | * Subset p; |
101 | * |
102 | * if (p) |
103 | * { |
104 | * // p does refers to data |
105 | * } |
106 | * |
107 | * if (!p) |
108 | * { |
109 | * // p does not referr to any data |
110 | * } |
111 | * \endcode |
112 | */ |
113 | operator unspecified_bool_type() const |
114 | { |
115 | return m_d ? &Subset::has_children : 0; |
116 | } |
117 | |
118 | /*! |
119 | * Returns the bounding box. |
120 | */ |
121 | const Rect& |
122 | bounding_box(void) const; |
123 | |
124 | /*! |
125 | * Returns the segments that are within this |
126 | * \ref Subset |
127 | */ |
128 | c_array<const segment_chain> |
129 | segment_chains(void) const; |
130 | |
131 | /*! |
132 | * Returns the joins within this \ref Subset |
133 | */ |
134 | c_array<const join> |
135 | joins(void) const; |
136 | |
137 | /*! |
138 | * Returns the caps within this \ref Subset |
139 | */ |
140 | c_array<const cap> |
141 | caps(void) const; |
142 | |
143 | /*! |
144 | * Returns the ID of this Subset, i.e. the value to |
145 | * feed to \ref PartitionedTessellatedPath::subset() |
146 | * to get this \ref Subset. |
147 | */ |
148 | unsigned int |
149 | ID(void) const; |
150 | |
151 | /*! |
152 | * Returns true if this Subset has child Subset |
153 | */ |
154 | bool |
155 | has_children(void) const; |
156 | |
157 | /*! |
158 | * Returns the children of this Subset. It is an |
159 | * error to call this if \ref has_children() returns |
160 | * false. |
161 | */ |
162 | vecN<Subset, 2> |
163 | children(void) const; |
164 | |
165 | private: |
166 | friend class PartitionedTessellatedPath; |
167 | |
168 | Subset(void *d); |
169 | |
170 | void *m_d; |
171 | }; |
172 | |
173 | /*! |
174 | * A SubsetSelection represents what \ref Subset |
175 | * objects intersect a clipped region. |
176 | */ |
177 | class SubsetSelection:fastuidraw::noncopyable |
178 | { |
179 | public: |
180 | /*! |
181 | * Ctor. |
182 | */ |
183 | SubsetSelection(); |
184 | ~SubsetSelection(); |
185 | |
186 | /*! |
187 | * The ID's of what Subset objects are selected. |
188 | */ |
189 | c_array<const unsigned int> |
190 | subset_ids(void) const; |
191 | |
192 | /*! |
193 | * ID's of what Subset objects are selected for joins. |
194 | * This value is different from \ref subset_ids() only |
195 | * when PartitionedTessellatedPath::select_subset_ids() |
196 | * was specified to enlarge the join footprints for |
197 | * miter-join stroking. |
198 | */ |
199 | c_array<const unsigned int> |
200 | join_subset_ids(void) const; |
201 | |
202 | /*! |
203 | * Returns the source for the data. |
204 | */ |
205 | const reference_counted_ptr<const PartitionedTessellatedPath>& |
206 | source(void) const; |
207 | |
208 | /*! |
209 | * Clears the SubsetSelection to be empty. |
210 | * \param src value for \ref source() to return |
211 | */ |
212 | void |
213 | clear(const reference_counted_ptr<const PartitionedTessellatedPath> &src = |
214 | reference_counted_ptr<const PartitionedTessellatedPath>()); |
215 | |
216 | /*! |
217 | * Apply a \ref PathEffect to the segments, joins and caps of the |
218 | * \ref Subset values within this \ref SubsetSelection. |
219 | * \param effect \ref PathEffect to apply |
220 | * \param dst \ref PathEffect::Storage to which to add results |
221 | */ |
222 | void |
223 | apply_path_effect(const PathEffect &effect, PathEffect::Storage &dst) const; |
224 | |
225 | private: |
226 | friend class PartitionedTessellatedPath; |
227 | |
228 | void *m_d; |
229 | }; |
230 | |
231 | /*! |
232 | * Constuct a PartitionedTessellatedPath from arrays of |
233 | * \ref segment_chain, \ref join and \ref caps values. |
234 | * Values are -COPIED- from the passed arrays. |
235 | * \param chains segment chain values to copy and partition |
236 | * \param joins join values to copy and partition |
237 | * \param caps cap values to copy and partition |
238 | */ |
239 | PartitionedTessellatedPath(c_array<const segment_chain> chains, |
240 | c_array<const join> joins, |
241 | c_array<const cap> caps); |
242 | |
243 | ~PartitionedTessellatedPath(); |
244 | |
245 | /*! |
246 | * Returns true if any of the \ref segment values of any |
247 | * of the \ref segment_chain values of any of the \ref |
248 | * Subset::segment_chains() has \ref segment::m_type equal |
249 | * to \ref TessellatedPath::arc_segment. |
250 | */ |
251 | bool |
252 | has_arcs(void) const; |
253 | |
254 | /*! |
255 | * Returns the number of Subset objects of the StrokedPath. |
256 | */ |
257 | unsigned int |
258 | number_subsets(void) const; |
259 | |
260 | /*! |
261 | * Return the named Subset object of the StrokedPath. |
262 | */ |
263 | Subset |
264 | subset(unsigned int I) const; |
265 | |
266 | /*! |
267 | * Returns the joins of the path. |
268 | */ |
269 | c_array<const join> |
270 | joins(void) const; |
271 | |
272 | /*! |
273 | * Returns the caps of the path. |
274 | */ |
275 | c_array<const cap> |
276 | caps(void) const; |
277 | |
278 | /*! |
279 | * Returns the root-subset of the StrokedPath, this |
280 | * is the \ref Subset that includes the entire |
281 | * StrokedPath. |
282 | */ |
283 | Subset |
284 | root_subset(void) const; |
285 | |
286 | /*! |
287 | * Given a set of clip equations in clip coordinates |
288 | * and a tranformation from local coordiante to clip |
289 | * coordinates, compute what Subset are not completely |
290 | * culled by the clip equations. |
291 | * \param clip_equations array of clip equations |
292 | * \param clip_matrix_local 3x3 transformation from local (x, y, 1) |
293 | * coordinates to clip coordinates. |
294 | * \param one_pixel_width holds the size of a single pixel in |
295 | * normalized device coordinates |
296 | * \param geometry_inflation amount path geometry is inflated, array |
297 | * is indexed by the enumeration \ref |
298 | * PathEnums::path_geometry_inflation_index_t |
299 | * \param select_miter_joins if true, when selecting what joins are in |
300 | * the area, enlarge the join footprint for if |
301 | * the joins are stroked as a type of miter join. |
302 | * \param[out] dst location to which to write the subset-selection. |
303 | */ |
304 | void |
305 | select_subsets(c_array<const vec3> clip_equations, |
306 | const float3x3 &clip_matrix_local, |
307 | const vec2 &one_pixel_width, |
308 | c_array<const float> geometry_inflation, |
309 | bool select_miter_joins, |
310 | SubsetSelection &dst) const; |
311 | private: |
312 | friend class TessellatedPath; |
313 | |
314 | // Only TessellatedPath can construct a PartitionedTessellatedPath |
315 | explicit |
316 | PartitionedTessellatedPath(const TessellatedPath &path); |
317 | |
318 | void *m_d; |
319 | }; |
320 | |
321 | /*! @} */ |
322 | } |
323 | |
324 | #endif |
325 | |