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
32namespace 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