1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any purpose with
6  * or without fee is hereby granted, provided that the above copyright notice and this
7  * permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #ifndef DGL_NANO_WIDGET_HPP_INCLUDED
18 #define DGL_NANO_WIDGET_HPP_INCLUDED
19 
20 #include "Color.hpp"
21 #include "Widget.hpp"
22 
23 #ifndef DGL_NO_SHARED_RESOURCES
24 # define NANOVG_DEJAVU_SANS_TTF "__dpf_dejavusans_ttf__"
25 #endif
26 
27 struct NVGcontext;
28 struct NVGpaint;
29 
30 START_NAMESPACE_DGL
31 
32 // -----------------------------------------------------------------------
33 // Forward class names
34 
35 class BlendishWidget;
36 class NanoVG;
37 
38 // -----------------------------------------------------------------------
39 // NanoImage
40 
41 /**
42    NanoVG Image class.
43 
44    This implements NanoVG images as a C++ class where deletion is handled automatically.
45    Images need to be created within a NanoVG or NanoWidget class.
46  */
47 class NanoImage
48 {
49 private:
50     struct Handle {
51         NVGcontext* context;
52         int         imageId;
53 
HandleNanoImage::Handle54         Handle() noexcept
55             : context(nullptr),
56               imageId(0) {}
57 
HandleNanoImage::Handle58         Handle(NVGcontext* c, int id) noexcept
59             : context(c),
60               imageId(id) {}
61     };
62 
63 public:
64    /**
65       Constructor for an invalid/null image.
66     */
67     NanoImage();
68 
69    /**
70       Constructor.
71     */
72     NanoImage(const Handle& handle);
73 
74    /**
75       Destructor.
76     */
77     ~NanoImage();
78 
79    /**
80       Create a new image without recreating the C++ class.
81     */
82     NanoImage& operator=(const Handle& handle);
83 
84    /**
85       Wherever this image is valid.
86     */
87     bool isValid() const noexcept;
88 
89    /**
90       Get size.
91     */
92     Size<uint> getSize() const noexcept;
93 
94    /**
95       Get the OpenGL texture handle.
96     */
97     GLuint getTextureHandle() const;
98 
99 private:
100     Handle fHandle;
101     Size<uint> fSize;
102     friend class NanoVG;
103 
104    /** @internal */
105     void _updateSize();
106 
107     DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoImage)
108 };
109 
110 // -----------------------------------------------------------------------
111 // NanoVG
112 
113 /**
114    NanoVG class.
115 
116    This class exposes the NanoVG drawing API.
117    All calls should be wrapped in beginFrame() and endFrame().
118 
119    @section State Handling
120    NanoVG contains state which represents how paths will be rendered.
121    The state contains transform, fill and stroke styles, text and font styles, and scissor clipping.
122 
123    @section Render styles
124    Fill and stroke render style can be either a solid color or a paint which is a gradient or a pattern.
125    Solid color is simply defined as a color value, different kinds of paints can be created
126    using linearGradient(), boxGradient(), radialGradient() and imagePattern().
127 
128    Current render style can be saved and restored using save() and restore().
129 
130    @section Transforms
131    The paths, gradients, patterns and scissor region are transformed by an transformation
132    matrix at the time when they are passed to the API.
133    The current transformation matrix is a affine matrix:
134      [sx kx tx]
135      [ky sy ty]
136      [ 0  0  1]
137    Where: sx,sy define scaling, kx,ky skewing, and tx,ty translation.
138    The last row is assumed to be 0,0,1 and is not stored.
139 
140    Apart from resetTransform(), each transformation function first creates
141    specific transformation matrix and pre-multiplies the current transformation by it.
142 
143    Current coordinate system (transformation) can be saved and restored using save() and restore().
144 
145    @section Images
146    NanoVG allows you to load jpg, png, psd, tga, pic and gif files to be used for rendering.
147    In addition you can upload your own image. The image loading is provided by stb_image.
148 
149    @section Paints
150    NanoVG supports four types of paints: linear gradient, box gradient, radial gradient and image pattern.
151    These can be used as paints for strokes and fills.
152 
153    @section Scissoring
154    Scissoring allows you to clip the rendering into a rectangle. This is useful for various
155    user interface cases like rendering a text edit or a timeline.
156 
157    @section Paths
158    Drawing a new shape starts with beginPath(), it clears all the currently defined paths.
159    Then you define one or more paths and sub-paths which describe the shape. The are functions
160    to draw common shapes like rectangles and circles, and lower level step-by-step functions,
161    which allow to define a path curve by curve.
162 
163    NanoVG uses even-odd fill rule to draw the shapes. Solid shapes should have counter clockwise
164    winding and holes should have counter clockwise order. To specify winding of a path you can
165    call pathWinding(). This is useful especially for the common shapes, which are drawn CCW.
166 
167    Finally you can fill the path using current fill style by calling fill(), and stroke it
168    with current stroke style by calling stroke().
169 
170    The curve segments and sub-paths are transformed by the current transform.
171 
172    @section Text
173    NanoVG allows you to load .ttf files and use the font to render text.
174 
175    The appearance of the text can be defined by setting the current text style
176    and by specifying the fill color. Common text and font settings such as
177    font size, letter spacing and text align are supported. Font blur allows you
178    to create simple text effects such as drop shadows.
179 
180    At render time the font face can be set based on the font handles or name.
181 
182    Font measure functions return values in local space, the calculations are
183    carried in the same resolution as the final rendering. This is done because
184    the text glyph positions are snapped to the nearest pixels sharp rendering.
185 
186    The local space means that values are not rotated or scale as per the current
187    transformation. For example if you set font size to 12, which would mean that
188    line height is 16, then regardless of the current scaling and rotation, the
189    returned line height is always 16. Some measures may vary because of the scaling
190    since aforementioned pixel snapping.
191 
192    While this may sound a little odd, the setup allows you to always render the
193    same way regardless of scaling. i.e. following works regardless of scaling:
194 
195    @code
196        const char* txt = "Text me up.";
197        vg.textBounds(x,y, txt, NULL, bounds);
198        vg.beginPath();
199        vg.roundedRect(bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]);
200        vg.fill();
201    @endcode
202 
203    Note: currently only solid color fill is supported for text.
204  */
205 class NanoVG
206 {
207 public:
208     enum CreateFlags {
209        /**
210           Flag indicating if geometry based anti-aliasing is used (may not be needed when using MSAA).
211         */
212         CREATE_ANTIALIAS = 1 << 0,
213 
214        /**
215           Flag indicating if strokes should be drawn using stencil buffer. The rendering will be a little
216           slower, but path overlaps (i.e. self-intersecting or sharp turns) will be drawn just once.
217         */
218         CREATE_STENCIL_STROKES = 1 << 1,
219 
220        /**
221           Flag indicating that additional debug checks are done.
222         */
223         CREATE_DEBUG = 1 << 2,
224     };
225 
226     enum ImageFlags {
227         IMAGE_GENERATE_MIPMAPS = 1 << 0, // Generate mipmaps during creation of the image.
228         IMAGE_REPEAT_X         = 1 << 1, // Repeat image in X direction.
229         IMAGE_REPEAT_Y         = 1 << 2, // Repeat image in Y direction.
230         IMAGE_FLIP_Y           = 1 << 3, // Flips (inverses) image in Y direction when rendered.
231         IMAGE_PREMULTIPLIED    = 1 << 4  // Image data has premultiplied alpha.
232     };
233 
234     enum Align {
235         // Horizontal align
236         ALIGN_LEFT     = 1 << 0, // Align horizontally to left (default).
237         ALIGN_CENTER   = 1 << 1, // Align horizontally to center.
238         ALIGN_RIGHT    = 1 << 2, // Align horizontally to right.
239         // Vertical align
240         ALIGN_TOP      = 1 << 3, // Align vertically to top.
241         ALIGN_MIDDLE   = 1 << 4, // Align vertically to middle.
242         ALIGN_BOTTOM   = 1 << 5, // Align vertically to bottom.
243         ALIGN_BASELINE = 1 << 6  // Align vertically to baseline (default).
244     };
245 
246     enum LineCap {
247         BUTT,
248         ROUND,
249         SQUARE,
250         BEVEL,
251         MITER
252     };
253 
254     enum Solidity {
255         SOLID = 1, // CCW
256         HOLE  = 2  // CW
257     };
258 
259     enum Winding {
260         CCW = 1, // Winding for solid shapes
261         CW  = 2  // Winding for holes
262     };
263 
264     struct Paint {
265         float xform[6];
266         float extent[2];
267         float radius;
268         float feather;
269         Color innerColor;
270         Color outerColor;
271         int   imageId;
272 
273         Paint() noexcept;
274 
275        /**
276           @internal
277         */
278         Paint(const NVGpaint&) noexcept;
279         operator NVGpaint() const noexcept;
280     };
281 
282     struct GlyphPosition {
283         const char* str;  // Position of the glyph in the input string.
284         float x;          // The x-coordinate of the logical glyph position.
285         float minx, maxx; // The bounds of the glyph shape.
286     };
287 
288     struct TextRow {
289         const char* start; // Pointer to the input text where the row starts.
290         const char* end;   // Pointer to the input text where the row ends (one past the last character).
291         const char* next;  // Pointer to the beginning of the next row.
292         float width;       // Logical width of the row.
293         float minx, maxx;  // Actual bounds of the row. Logical with and bounds can differ because of kerning and some parts over extending.
294     };
295 
296     typedef int FontId;
297 
298    /**
299       Constructor.
300       @see CreateFlags
301     */
302     NanoVG(int flags = CREATE_ANTIALIAS);
303 
304    /**
305       Constructor reusing a NanoVG context, used for subwidgets.
306     */
307     NanoVG(NanoWidget* groupWidget);
308 
309    /**
310       Destructor.
311     */
312     virtual ~NanoVG();
313 
314    /**
315       Get the NanoVG context.
316       You should not need this under normal circumstances.
317     */
getContext() const318     NVGcontext* getContext() const noexcept
319     {
320         return fContext;
321     }
322 
323    /**
324       Begin drawing a new frame.
325     */
326     void beginFrame(const uint width, const uint height, const float scaleFactor = 1.0f);
327 
328    /**
329       Begin drawing a new frame inside a widget.
330     */
331     void beginFrame(Widget* const widget);
332 
333    /**
334       Cancels drawing the current frame.
335     */
336     void cancelFrame();
337 
338    /**
339       Ends drawing flushing remaining render state.
340     */
341     void endFrame();
342 
343    /* --------------------------------------------------------------------
344     * State Handling */
345 
346    /**
347       Pushes and saves the current render state into a state stack.
348       A matching restore() must be used to restore the state.
349     */
350     void save();
351 
352    /**
353       Pops and restores current render state.
354     */
355     void restore();
356 
357    /**
358       Resets current render state to default values. Does not affect the render state stack.
359     */
360     void reset();
361 
362    /* --------------------------------------------------------------------
363     * Render styles */
364 
365    /**
366       Sets current stroke style to a solid color.
367     */
368     void strokeColor(const Color& color);
369 
370    /**
371       Sets current stroke style to a solid color, made from red, green, blue and alpha numeric values.
372       Values must be in [0..255] range.
373     */
374     void strokeColor(const int red, const int green, const int blue, const int alpha = 255);
375 
376    /**
377       Sets current stroke style to a solid color, made from red, green, blue and alpha numeric values.
378       Values must in [0..1] range.
379     */
380     void strokeColor(const float red, const float green, const float blue, const float alpha = 1.0f);
381 
382    /**
383       Sets current stroke style to a paint, which can be a one of the gradients or a pattern.
384     */
385     void strokePaint(const Paint& paint);
386 
387    /**
388       Sets current fill style to a solid color.
389     */
390     void fillColor(const Color& color);
391 
392    /**
393       Sets current fill style to a solid color, made from red, green, blue and alpha numeric values.
394       Values must be in [0..255] range.
395     */
396     void fillColor(const int red, const int green, const int blue, const int alpha = 255);
397 
398    /**
399       Sets current fill style to a solid color, made from red, green, blue and alpha numeric values.
400       Values must in [0..1] range.
401     */
402     void fillColor(const float red, const float green, const float blue, const float alpha = 1.0f);
403 
404    /**
405       Sets current fill style to a paint, which can be a one of the gradients or a pattern.
406     */
407     void fillPaint(const Paint& paint);
408 
409    /**
410       Sets the miter limit of the stroke style.
411       Miter limit controls when a sharp corner is beveled.
412     */
413     void miterLimit(float limit);
414 
415    /**
416       Sets the stroke width of the stroke style.
417     */
418     void strokeWidth(float size);
419 
420    /**
421       Sets how the end of the line (cap) is drawn,
422       Can be one of: BUTT, ROUND, SQUARE.
423     */
424     void lineCap(LineCap cap = BUTT);
425 
426    /**
427       Sets how sharp path corners are drawn.
428       Can be one of MITER, ROUND, BEVEL.
429     */
430     void lineJoin(LineCap join = MITER);
431 
432    /**
433       Sets the transparency applied to all rendered shapes.
434       Already transparent paths will get proportionally more transparent as well.
435     */
436     void globalAlpha(float alpha);
437 
438    /* --------------------------------------------------------------------
439     * Transforms */
440 
441    /**
442       Resets current transform to a identity matrix.
443     */
444     void resetTransform();
445 
446    /**
447       Pre-multiplies current coordinate system by specified matrix.
448       The parameters are interpreted as matrix as follows:
449         [a c e]
450         [b d f]
451         [0 0 1]
452     */
453     void transform(float a, float b, float c, float d, float e, float f);
454 
455    /**
456       Translates current coordinate system.
457     */
458     void translate(float x, float y);
459 
460    /**
461       Rotates current coordinate system. Angle is specified in radians.
462     */
463     void rotate(float angle);
464 
465    /**
466       Skews the current coordinate system along X axis. Angle is specified in radians.
467     */
468     void skewX(float angle);
469 
470    /**
471       Skews the current coordinate system along Y axis. Angle is specified in radians.
472     */
473     void skewY(float angle);
474 
475    /**
476       Scales the current coordinate system.
477     */
478     void scale(float x, float y);
479 
480    /**
481       Stores the top part (a-f) of the current transformation matrix in to the specified buffer.
482         [a c e]
483         [b d f]
484         [0 0 1]
485     */
486     void currentTransform(float xform[6]);
487 
488    /**
489       The following functions can be used to make calculations on 2x3 transformation matrices.
490       A 2x3 matrix is represented as float[6]. */
491 
492    /**
493       Sets the transform to identity matrix.
494     */
495     static void transformIdentity(float dst[6]);
496 
497    /**
498       Sets the transform to translation matrix
499     */
500     static void transformTranslate(float dst[6], float tx, float ty);
501 
502    /**
503       Sets the transform to scale matrix.
504     */
505     static void transformScale(float dst[6], float sx, float sy);
506 
507    /**
508       Sets the transform to rotate matrix. Angle is specified in radians.
509     */
510     static void transformRotate(float dst[6], float a);
511 
512    /**
513       Sets the transform to skew-x matrix. Angle is specified in radians.
514     */
515     static void transformSkewX(float dst[6], float a);
516 
517    /**
518       Sets the transform to skew-y matrix. Angle is specified in radians.
519     */
520     static void transformSkewY(float dst[6], float a);
521 
522    /**
523       Sets the transform to the result of multiplication of two transforms, of A = A*B.
524     */
525     static void transformMultiply(float dst[6], const float src[6]);
526 
527    /**
528       Sets the transform to the result of multiplication of two transforms, of A = B*A.
529     */
530     static void transformPremultiply(float dst[6], const float src[6]);
531 
532    /**
533       Sets the destination to inverse of specified transform.
534       Returns 1 if the inverse could be calculated, else 0.
535     */
536     static int transformInverse(float dst[6], const float src[6]);
537 
538    /**
539       Transform a point by given transform.
540     */
541     static void transformPoint(float& dstx, float& dsty, const float xform[6], float srcx, float srcy);
542 
543    /**
544       Convert degrees to radians.
545     */
546     static float degToRad(float deg);
547 
548    /**
549       Convert radians to degrees.
550     */
551     static float radToDeg(float rad);
552 
553    /* --------------------------------------------------------------------
554     * Images */
555 
556    /**
557       Creates image by loading it from the disk from specified file name.
558     */
559     NanoImage::Handle createImageFromFile(const char* filename, ImageFlags imageFlags);
560 
561    /**
562       Creates image by loading it from the disk from specified file name.
563       Overloaded function for convenience.
564       @see ImageFlags
565     */
566     NanoImage::Handle createImageFromFile(const char* filename, int imageFlags);
567 
568    /**
569       Creates image by loading it from the specified chunk of memory.
570     */
571     NanoImage::Handle createImageFromMemory(uchar* data, uint dataSize, ImageFlags imageFlags);
572 
573    /**
574       Creates image by loading it from the specified chunk of memory.
575       Overloaded function for convenience.
576       @see ImageFlags
577     */
578     NanoImage::Handle createImageFromMemory(uchar* data, uint dataSize, int imageFlags);
579 
580    /**
581       Creates image from specified image data.
582     */
583     NanoImage::Handle createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags);
584 
585    /**
586       Creates image from specified image data.
587       Overloaded function for convenience.
588       @see ImageFlags
589     */
590     NanoImage::Handle createImageFromRGBA(uint w, uint h, const uchar* data, int imageFlags);
591 
592    /**
593       Creates image from an OpenGL texture handle.
594     */
595     NanoImage::Handle createImageFromTextureHandle(GLuint textureId, uint w, uint h, ImageFlags imageFlags, bool deleteTexture = false);
596 
597    /**
598       Creates image from an OpenGL texture handle.
599       Overloaded function for convenience.
600       @see ImageFlags
601     */
602     NanoImage::Handle createImageFromTextureHandle(GLuint textureId, uint w, uint h, int imageFlags, bool deleteTexture = false);
603 
604    /* --------------------------------------------------------------------
605     * Paints */
606 
607    /**
608       Creates and returns a linear gradient. Parameters (sx,sy)-(ex,ey) specify the start and end coordinates
609       of the linear gradient, icol specifies the start color and ocol the end color.
610       The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint().
611     */
612     Paint linearGradient(float sx, float sy, float ex, float ey, const Color& icol, const Color& ocol);
613 
614    /**
615       Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
616       drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
617       (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry
618       the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient.
619       The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint().
620     */
621     Paint boxGradient(float x, float y, float w, float h, float r, float f, const Color& icol, const Color& ocol);
622 
623    /**
624       Creates and returns a radial gradient. Parameters (cx,cy) specify the center, inr and outr specify
625       the inner and outer radius of the gradient, icol specifies the start color and ocol the end color.
626       The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint().
627     */
628     Paint radialGradient(float cx, float cy, float inr, float outr, const Color& icol, const Color& ocol);
629 
630    /**
631       Creates and returns an image pattern. Parameters (ox,oy) specify the left-top location of the image pattern,
632       (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render.
633       The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint().
634     */
635     Paint imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage& image, float alpha);
636 
637    /* --------------------------------------------------------------------
638     * Scissoring */
639 
640    /**
641       Sets the current scissor rectangle.
642       The scissor rectangle is transformed by the current transform.
643     */
644     void scissor(float x, float y, float w, float h);
645 
646    /**
647       Intersects current scissor rectangle with the specified rectangle.
648       The scissor rectangle is transformed by the current transform.
649       Note: in case the rotation of previous scissor rect differs from
650       the current one, the intersection will be done between the specified
651       rectangle and the previous scissor rectangle transformed in the current
652       transform space. The resulting shape is always rectangle.
653     */
654     void intersectScissor(float x, float y, float w, float h);
655 
656    /**
657       Reset and disables scissoring.
658     */
659     void resetScissor();
660 
661    /* --------------------------------------------------------------------
662     * Paths */
663 
664    /**
665       Clears the current path and sub-paths.
666     */
667     void beginPath();
668 
669    /**
670       Starts new sub-path with specified point as first point.
671     */
672     void moveTo(float x, float y);
673 
674    /**
675       Adds line segment from the last point in the path to the specified point.
676     */
677     void lineTo(float x, float y);
678 
679    /**
680       Adds cubic bezier segment from last point in the path via two control points to the specified point.
681     */
682     void bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y);
683 
684    /**
685       Adds quadratic bezier segment from last point in the path via a control point to the specified point.
686     */
687     void quadTo(float cx, float cy, float x, float y);
688 
689    /**
690       Adds an arc segment at the corner defined by the last path point, and two specified points.
691     */
692     void arcTo(float x1, float y1, float x2, float y2, float radius);
693 
694    /**
695       Closes current sub-path with a line segment.
696     */
697     void closePath();
698 
699    /**
700       Sets the current sub-path winding.
701     */
702     void pathWinding(Winding dir);
703 
704    /**
705       Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r,
706       and the arc is drawn from angle a0 to a1, and swept in direction dir (NVG_CCW or NVG_CW).
707       Angles are specified in radians.
708     */
709     void arc(float cx, float cy, float r, float a0, float a1, Winding dir);
710 
711    /**
712       Creates new rectangle shaped sub-path.
713     */
714     void rect(float x, float y, float w, float h);
715 
716    /**
717       Creates new rounded rectangle shaped sub-path.
718     */
719     void roundedRect(float x, float y, float w, float h, float r);
720 
721    /**
722       Creates new ellipse shaped sub-path.
723     */
724     void ellipse(float cx, float cy, float rx, float ry);
725 
726    /**
727       Creates new circle shaped sub-path.
728     */
729     void circle(float cx, float cy, float r);
730 
731    /**
732       Fills the current path with current fill style.
733     */
734     void fill();
735 
736    /**
737       Fills the current path with current stroke style.
738     */
739     void stroke();
740 
741    /* --------------------------------------------------------------------
742     * Text */
743 
744    /**
745       Creates font by loading it from the disk from specified file name.
746       Returns handle to the font.
747     */
748     FontId createFontFromFile(const char* name, const char* filename);
749 
750    /**
751       Creates font by loading it from the specified memory chunk.
752       Returns handle to the font.
753     */
754     FontId createFontFromMemory(const char* name, const uchar* data, uint dataSize, bool freeData);
755 
756    /**
757       Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found.
758     */
759     FontId findFont(const char* name);
760 
761    /**
762       Sets the font size of current text style.
763     */
764     void fontSize(float size);
765 
766    /**
767       Sets the blur of current text style.
768     */
769     void fontBlur(float blur);
770 
771    /**
772       Sets the letter spacing of current text style.
773     */
774     void textLetterSpacing(float spacing);
775 
776    /**
777       Sets the proportional line height of current text style. The line height is specified as multiple of font size.
778     */
779     void textLineHeight(float lineHeight);
780 
781    /**
782       Sets the text align of current text style.
783     */
784     void textAlign(Align align);
785 
786    /**
787       Sets the text align of current text style.
788       Overloaded function for convenience.
789       @see Align
790     */
791     void textAlign(int align);
792 
793    /**
794       Sets the font face based on specified id of current text style.
795     */
796     void fontFaceId(FontId font);
797 
798    /**
799       Sets the font face based on specified name of current text style.
800     */
801     void fontFace(const char* font);
802 
803    /**
804       Draws text string at specified location. If end is specified only the sub-string up to the end is drawn.
805     */
806     float text(float x, float y, const char* string, const char* end);
807 
808    /**
809       Draws multi-line text string at specified location wrapped at the specified width.
810       If end is specified only the sub-string up to the end is drawn.
811       White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
812       Words longer than the max width are slit at nearest character (i.e. no hyphenation).
813     */
814     void textBox(float x, float y, float breakRowWidth, const char* string, const char* end = nullptr);
815 
816    /**
817       Measures the specified text string. The bounds value are [xmin,ymin, xmax,ymax].
818       Returns the horizontal advance of the measured text (i.e. where the next character should drawn).
819       Measured values are returned in local coordinate space.
820     */
821     float textBounds(float x, float y, const char* string, const char* end, Rectangle<float>& bounds);
822 
823    /**
824       Measures the specified multi-text string. Parameter bounds should be a pointer to float[4],
825       if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
826       Measured values are returned in local coordinate space.
827     */
828     void textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float bounds[4]);
829 
830    /**
831       Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used.
832       Measured values are returned in local coordinate space.
833     */
834     int textGlyphPositions(float x, float y, const char* string, const char* end, GlyphPosition& positions, int maxPositions);
835 
836    /**
837       Returns the vertical metrics based on the current text style.
838       Measured values are returned in local coordinate space.
839     */
840     void textMetrics(float* ascender, float* descender, float* lineh);
841 
842    /**
843       Breaks the specified text into lines. If end is specified only the sub-string will be used.
844       White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
845       Words longer than the max width are slit at nearest character (i.e. no hyphenation).
846     */
847     int textBreakLines(const char* string, const char* end, float breakRowWidth, TextRow& rows, int maxRows);
848 
849 #ifndef DGL_NO_SHARED_RESOURCES
850    /**
851       Load DPF's internal shared resources for this NanoVG class.
852     */
853     virtual void loadSharedResources();
854 #endif
855 
856 private:
857     NVGcontext* const fContext;
858     bool fInFrame;
859     bool fIsSubWidget;
860     friend class BlendishWidget;
861 
862     DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoVG)
863 };
864 
865 // -----------------------------------------------------------------------
866 // NanoWidget
867 
868 /**
869    NanoVG Widget class.
870 
871    This class implements the NanoVG drawing API inside a DGL Widget.
872    The drawing function onDisplay() is implemented internally but a
873    new onNanoDisplay() needs to be overridden instead.
874  */
875 class NanoWidget : public Widget,
876                    public NanoVG
877 {
878 public:
879    /**
880       Constructor.
881       @see CreateFlags
882     */
883     explicit NanoWidget(Window& parent, int flags = CREATE_ANTIALIAS);
884 
885    /**
886       Constructor for a subwidget.
887     */
888     explicit NanoWidget(Widget* groupWidget, int flags = CREATE_ANTIALIAS);
889 
890    /**
891       Constructor for a subwidget, reusing a NanoVG context.
892     */
893     explicit NanoWidget(NanoWidget* groupWidget);
894 
895    /**
896       Destructor.
897     */
898     virtual ~NanoWidget();
899 
900 protected:
901    /**
902       New virtual onDisplay function.
903       @see onDisplay
904     */
905     virtual void onNanoDisplay() = 0;
906 
907 private:
908     struct PrivateData;
909     PrivateData* const nData;
910 
911    /**
912       Widget display function.
913       Implemented internally to wrap begin/endFrame() automatically.
914     */
915     void onDisplay() override;
916 
917     // these should not be used
beginFrame(uint,uint)918     void beginFrame(uint,uint) {}
beginFrame(uint,uint,float)919     void beginFrame(uint,uint,float) {}
beginFrame(Widget *)920     void beginFrame(Widget*) {}
cancelFrame()921     void cancelFrame() {}
endFrame()922     void endFrame() {}
923 
924     DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoWidget)
925 };
926 
927 // -----------------------------------------------------------------------
928 
929 END_NAMESPACE_DGL
930 
931 #endif // DGL_NANO_WIDGET_HPP_INCLUDED
932