FastUIDraw
glyph_render_data_restricted_rays.hpp
Go to the documentation of this file.
1 /*!
2  * \file glyph_render_data_restricted_rays.hpp
3  * \brief file glyph_render_data_restricted_rays.hpp
4  *
5  * Copyright 2018 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_GLYPH_RENDER_DATA_RESTRICTED_RAYS_HPP
21 #define FASTUIDRAW_GLYPH_RENDER_DATA_RESTRICTED_RAYS_HPP
22 
23 #include <fastuidraw/util/rect.hpp>
26 
27 namespace fastuidraw
28 {
29 /*!\addtogroup Glyph
30  * @{
31  */
32 
33  /*!
34  * A GlyphRenderDataRestrictedRays represents the data needed to
35  * build a glyph to render it. The technique operates as follows:
36  * - a hierarchy of boxes is created on CPU and traversed by
37  * the GPU; the hierarchy is such a form that traversal on
38  * the GPU is a simple loop that checks bits
39  * - each box has a list of what curves are within it and
40  * a point P whose winding number at that point is also stored.
41  * The point P is guaranteed to be away from any curve so its
42  * winding number is defined and numerically stable
43  * - On the GPU, the fragment shader computes what box the fragment
44  * is contained and computes the difference of the winding
45  * number between the fragment and the reference point P.
46  * The computation is numerically stable becuase instead of
47  * using directl 0 <= t <= 1 when computing if an intersection
48  * contributes, we instead walk the algebra of what that condition
49  * means in terms of the points of the bezier curve [q1, q2, q2].
50  * Whhen the quadratic term of the bezier curve is poisition,
51  * the condition is:
52  * -- use t1 if (q1 >= q2 && q1 >= 0.0) && (q3 > q2 || q3 < 0.0)
53  * -- use t2 if (q3 > q2 && q3 > 0.0) && (q1 >= q2 || q1 <= 0.0)
54  *
55  * NOTE: this is NOT the techinque as patented by Eric Lengyel that
56  * computes by a lookup table keyed by the 3 conditions of examing
57  * q1, q2, q3 against 0. The Lengyel technique does give a fast shader,
58  * but we cannot use it because of the patent on it.
59  */
61  {
62  public:
63  /*!
64  * Enumeration to describe the hierarchy of bounding
65  * boxes as packed into the data. A node in the
66  * hierarchy is a single 32-bit value. A leaf in the
67  * hierarchy is a single 32-bit value followed by a
68  * single sample point which has a winding value
69  * and offset position packed as according to \ref
70  * winding_sample_packing_t.
71  */
73  {
74 
75  /*!
76  * This is the number of bits used to store the
77  * offsets to a child node.
78  */
80 
81  /*!
82  * For case where the element is leaf, i.e. the
83  * bit \ref hierarchy_is_node_bit is down. This
84  * is the number bit used to encode the offset
85  * to where the list of curves for the box is
86  * located. The list of curves is packed as
87  * according to \ref curve_list_packing_t.
88  */
90 
91  /*!
92  * For case where the element is leaf, i.e. the
93  * bit \ref hierarchy_is_node_bit is down. This
94  * is the number of bits used to encode the size
95  * of the list of curves for the box is located.
96  * The list of curves is packed as according to
97  * \ref curve_list_packing_t.
98  */
100 
101  /*!
102  * If this bit is up, indicates that the 32-bit value
103  * is holding node data. If the bit is down indicates
104  * that the element is a leaf and the value holds the
105  * properties of the curve list in the box and the next
106  * value holds the winding sample information for the
107  * box and are packed as according to \ref
108  * winding_sample_packing_t.
109  */
111 
112  /*!
113  * For case where the element is a node, i.e. the
114  * bit \ref hierarchy_is_node_bit is up. This bit
115  * indicates if the split of the node is horizontal
116  * of verical. A value of 0 indicates that the split
117  * happens in the x-coordinate (i.e. the child nodes
118  * have the same values for min-y and max-y) and a
119  * value of 1 indicates the split happens in the
120  * y-coordinate.
121  */
123 
124  /*!
125  * For case where the element is a node, i.e. the
126  * bit \ref hierarchy_is_node_bit is up. This is
127  * the first bit holding the offset from the start
128  * of the geomertic data of the glyph for the child
129  * node which comes before the split, i.e. the child
130  * on the left or bottom side.
131  */
133 
134  /*!
135  * For case where the element is a node, i.e. the
136  * bit \ref hierarchy_is_node_bit is up. This is
137  * the first bit holding the offset from the start
138  * of the geomertic data of the glyph for the child
139  * node which comes after the split, i.e. the child
140  * on the right or top side.
141  */
143 
144  /*!
145  * For case where the element is leaf, i.e. the
146  * bit \ref hierarchy_is_node_bit is down. This
147  * is the first bit used to encode the offset
148  * to where the list of curves for the box is
149  * located. The list of curves is packed as
150  * according to \ref curve_list_packing_t.
151  */
153 
154  /*!
155  * For case where the element is leaf, i.e. the
156  * bit \ref hierarchy_is_node_bit is down. This
157  * is the first bit used to encode the size
158  * of the list of curves for the box is located.
159  * The list of curves is packed as according to
160  * \ref curve_list_packing_t.
161  */
163  };
164 
165  /*!
166  * Enumeration to describe how the winding samples
167  * of a leaf-box of the hierarchy are packed. The
168  * position of the sample is the bottom left corner
169  * of the node offset by a delta:
170  * $ Delta = RelativeDelta * BoxDimensions / DeltaFactor $
171  * where PackedDelta is extracted from the 32-bit
172  * value as a pair of 8-bit values located at bits
173  * \ref delta_x_bit0 and \ref delta_y_bit0; DeltaFactor
174  * is given by \ref delta_div_factor and BoxDimensions
175  * is the width and height of the box of the leaf.
176  */
178  {
179  /*!
180  * Winding values are stored biased (in order
181  * to be able to store negative winding values)
182  * This is the value to add to the unpacked
183  * winding number found at bit \ref
184  * winding_value_bit0
185  */
186  winding_bias = 32768u,
187 
188  /*!
189  * The first bit used to encode the winding value
190  * (which is stored biased by \ref winding_bias).
191  */
193 
194  /*!
195  * The number of bits used to encode the winding value
196  * (which is stored biased by \ref winding_bias).
197  */
199 
200  /*!
201  * The amount by which to divide the delta
202  */
204 
205  /*!
206  * The first bit used to store the delta x-coordinate
207  */
209 
210  /*!
211  * The first bit used to store the delta y-coordinate
212  */
214 
215  /*!
216  * The number of bits used to store the delta x-coordinate
217  * and delta y-coordinate values.
218  */
220  };
221 
222  /*!
223  * Enumeration to describe how a list of curves is packed.
224  * Each 32-bit value holds the data for two curves.
225  * A curve entry is 16-bit value whose highest bit gives the
226  * degree of the curve and the remaining 15-bits give the
227  * offset to the location of the curve's control points.
228  */
230  {
231  /*!
232  * The number of bits to store a single curve entry.
233  */
235 
236  /*!
237  * The first bit used for the first curve of the entry.
238  */
240 
241  /*!
242  * The first bit used for the second curve of the entry.
243  */
245 
246  /*!
247  * Given an unpacked curve entry (which is 16-bits wide),
248  * if this bit of the value is up, then the curve referenced
249  * is a quadratic Bezier curve having control points. Otherwise,
250  * it is a line segment connecting its two points.
251  */
253 
254  /*!
255  * Given an unpacked curve entry (which is 16-bits wide),
256  * this is the first bit used to store the offset to the
257  * location of the points of the curve (packed as according
258  * to \ref point_packing_t).
259  */
261 
262  /*!
263  * Given an unpacked curve entry (which is 16-bits wide),
264  * this is the number of bits used to store the offset to the
265  * location of the points of the curve (packed as according
266  * to \ref point_packing_t).
267  */
269  };
270 
271  /*!
272  * Points are packed as (fp16, fp16) pairs.
273  */
275  {
276  };
277 
278  enum
279  {
280  /*!
281  * The glyph coordinate value in each coordiante varies
282  * from -\ref glyph_coord_value to +\ref glyph_coord_value,
283  * i.e. the glyph is drawn as rect with min-corner
284  * (-\ref glyph_coord_value, -\ref glyph_coord_value)
285  * and max-corner (+\ref glyph_coord_value, +\ref glyph_coord_value)
286  */
288  };
289 
290  /*!
291  * This enumeration describes the meaning of the
292  * attributes. The glyph shader is to assume that
293  * the glyph-coordinates at the min-corner is
294  * (-\ref glyph_coord_value, -\ref glyph_coord_value)
295  * and the glyph coordiantes at the max-corner is
296  * (+\ref glyph_coord_value, +\ref glyph_coord_value)
297  */
299  {
300  /*!
301  * Value is 0 if on min-x side of glyph, value is
302  * 1 if on max-x side of glyph; packed as uint.
303  */
305 
306  /*!
307  * Value is 0 if on min-y side of glyph, value is
308  * 1 if on max-y side of glyph; packed as uint.
309  */
311 
312  /*!
313  * the index into GlyphAttribute::m_data storing
314  * the fill rule and the offset into the store for
315  * the glyph data. The offset is encoded as follows
316  * - bits0-bits29 encode the offset
317  * - bit30 indicates to complement fill
318  * - bit31 up indicates odd-even fill rule and
319  * down indicates non-zero fill rule.
320  */
322 
323  /*!
324  * Number attribute values needed.
325  */
327  };
328 
329  /*!
330  * A query_info holds data about a \ref GlyphRenderDataRestrictedRays
331  * value (after its finalized method).
332  */
334  {
335  public:
336  /*!
337  * Default ctor, initializing the value as empty
338  */
340  {}
341 
342  /*!
343  * Set the value of a \ref vecN of \ref GlyphAttribute values
344  * derived from this query_info object
345  * \param out_attribs location to which to write GlyphAttribute values
346  * \param fill_rule fill rule with which to fill the glyphs
347  * \param offset location of glyph data
348  */
349  void
351  enum PainterEnums::fill_rule_t fill_rule,
352  uint32_t offset);
353 
354  /*!
355  * The GPU data of the queried \ref GlyphRenderDataRestrictedRays
356  * object; the data pointed to by the array is backed
357  * internally by the queried \ref GlyphRenderDataRestrictedRays;
358  * thus, if the point becomes invalid once the queried
359  * \ref GlyphRenderDataRestrictedRays goes out of scope.
360  */
362  };
363 
364  /*!
365  * Ctor.
366  */
368 
370 
371  /*!
372  * Start a contour. Before starting a new contour
373  * the previous contour must be closed by calling
374  * line_to() or quadratic_to() connecting to the
375  * start point of the previous contour.
376  * \param pt start point of the new contour
377  */
378  void
379  move_to(vec2 pt);
380 
381  /*!
382  * Add a line segment connecting the end point of the
383  * last curve or line segment of the current contour to
384  * a given point.
385  * \param pt end point of the new line segment
386  */
387  void
388  line_to(vec2 pt);
389 
390  /*!
391  * Add a quadratic curveconnecting the end point of the
392  * last curve or line segment of the current contour
393  * \param ct control point of the quadratic curve
394  * \param pt end point of the quadratic curve
395  */
396  void
397  quadratic_to(vec2 ct, vec2 pt);
398 
399  /*!
400  * Finalize the input data after which no more contours or curves may be added;
401  * all added contours must be closed before calling finalize(). Once finalize()
402  * is called, no further data can be added. How the data is broken into bounding
403  * boxes is specified by
404  * - units_per_EM argument (see below)
405  * - GlyphGenerateParams::restricted_rays_minimum_render_size()
406  * - GlyphGenerateParams::restricted_rays_split_thresh()
407  * - GlyphGenerateParams::restricted_rays_max_recursion()
408  * All contours added must be closed as well.
409  * \param f fill rule to use for rendering
410  * \param glyph_rect the rect of the glyph
411  * \param units_per_EM the units per EM for the glyph; this value together with
412  * GlyphGenerateParams::restricted_rays_minimum_render_size()
413  * is used to decide how close a curve may be to a bounding
414  * box to decide if it is included.
415  */
416  void
417  finalize(enum PainterEnums::fill_rule_t f, const Rect &glyph_rect,
418  float units_per_EM);
419 
420  /*!
421  * Finalize the input data after which no more contours or curves may be added;
422  * all added contours must be closed before calling finale(). Once finalize()
423  * is called, no further data can be added. Instead of using methods from
424  * \ref GlyphGenerateParams, directly specify how the data is broken into
425  * boxes.
426  * \param f fill rule to use for rendering
427  * \param glyph_rect the rect of the glyph
428  * \param split_thresh if the number of curves within a box is greater than
429  * this value, the box is split
430  * \param max_recursion the maximum level of recursion allowed in splitting
431  * the data into boxes
432  * \param near_thresh horizontal and vertical threshhold to decide if a curve
433  * outside of a box should be added to a box
434  */
435  void
436  finalize(enum PainterEnums::fill_rule_t f, const Rect &glyph_rect,
437  int split_thresh, int max_recursion, vec2 near_thresh);
438 
439  /*!
440  * Query the data; may only be called after finalize(). Returns
441  * \ref routine_fail if finalize() has not yet been called.
442  * \param out_info location to which to write information about
443  * this object.
444  */
445  enum return_code
446  query(query_info *out_info) const;
447 
448  virtual
450  render_info_labels(void) const;
451 
452  virtual
454  upload_to_atlas(GlyphAtlasProxy &atlas_proxy,
455  GlyphAttribute::Array &attributes,
456  c_array<float> render_costs) const;
457 
458  private:
459  void *m_d;
460  };
461 /*! @} */
462 }
463 
464 #endif
Represents an opaque array of GlyphAttribute values.
virtual c_array< const c_string > render_info_labels(void) const
GlyphRenderData provides an interface to specify data used for rendering glyphs and to pack that data...
file glyph_render_data.hpp
all classes and functions of FastUIDraw are in the namespace fastuidraw.
Definition: colorstop.hpp:28
return_code
Enumeration for simple return codes for functions for success or failure.
Definition: util.hpp:142
vecN is a simple static array class with no virtual functions and no memory overhead. Supports runtim array index checking and STL style iterators via pointer iterators.
Definition: vecN.hpp:42
An GlyphAtlasProxy is a proxy for a GlyphAtlas; one can allocate through it. Internally it tracks all...
virtual enum fastuidraw::return_code upload_to_atlas(GlyphAtlasProxy &atlas_proxy, GlyphAttribute::Array &attributes, c_array< float > render_costs) const
void set_glyph_attributes(vecN< GlyphAttribute, glyph_num_attributes > *out_attribs, enum PainterEnums::fill_rule_t fill_rule, uint32_t offset)
void finalize(enum PainterEnums::fill_rule_t f, const Rect &glyph_rect, float units_per_EM)
file painter_enums.hpp
fill_rule_t
Enumerations specifying common fill rules.
enum return_code query(query_info *out_info) const