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