memononen / nanovg Goto Github PK
View Code? Open in Web Editor NEWAntialiased 2D vector drawing library on top of OpenGL for UI and visualizations.
License: zlib License
Antialiased 2D vector drawing library on top of OpenGL for UI and visualizations.
License: zlib License
I think the second-to-last nvg__vset() call in nvg__bevelJoin() has a copy/paste mistake:
nvg__vset(dst, p1->x + dlx1*rw, p1->y + dly1*rw, lu,1); dst++;
should be:
nvg__vset(dst, p1->x + dlx1*lw, p1->y + dly1*lw, lu,1); dst++;
I could see a difference in the 3rd text line in the example (the one with like the 1 pixel wide vertical gray box).
Is there a way with the current API to do inverse scissoring? As in defining an area where you DON'T want to draw?
I'm doing some really basic line rendering tests with edge AA turned on and I got the following result. I'm rendering a 4 pixel horizontal line with a stroke width of 1 using the code below.
nvgStrokeColor(vg, nvgRGBA(255,255,255,255));
nvgLineCap(vg, NVG_BUTT);
nvgStrokeWidth(vg, 1.0f);
nvgBeginPath(vg);
nvgMoveTo(vg, 10.5f, 100.5f);
nvgLineTo(vg, 14.5f, 100.5f);
What I'm getting however, is a full 5 pixel line. That's not what I expected from a line segment capped by NVG_BUTT. It would be the result I'd expect when using NVG_SQUARE, but if I do that the line becomes 7 fully white pixels.
Here's a close-up view of what I mean:
Cyan outline is the expected stroked line segment using NVG_BUTT.
Is this intended behavior?
Cheers,
Guido
Xcode keeps giving me a warning for line https://github.com/memononen/nanovg/blob/master/src/stb_image.c#L1736
in_far = in_far;
Does this line actually do anything?
When I run my laptop with Intel Mesa drivers, I can get a GLES3 context, and that helps exercise the new GLES2 support. A few things:
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
GL_UNPACK_ROW_LENGTH
GL_UNPACK_SKIP_ROWS
GL_UNPACK_SKIP_PIXELS
"#version 100\n"
"precision mediump float;\n"
It appears NanoVG doesn't set all states required for it to render correctly, which increases the amount of boilerplate needed on the client side, and also causes all kinds of hard to diagnose side effects if the user is making use of other blackbox GL components.
I'm not sure why this was done, perhaps to make multiple subsequent draw calls more efficient, but in practice, this should not make any noticeable differences in performance.
Among the states mentioned in the docs, which are
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_BLEND)
glDisable(GL_DEPTH_TEST)
I also had to take care that these states are initialized as follows (still probably not a complete list):
glDisable(GL_SCISSOR_TEST)
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE)
glStencilMask(0xffffffff)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP)
glStencilFunc(GL_ALWAYS, 0, 0xffffffff)
And then there are other obvious ones, which are
glViewport(0,0,frame_width,frame_height)
glClearColor(0,0,0,0)
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
I would like to propose that the alpha_blend argument in beginFrame is converted to a general flags field, NVG_PREMULTIPLIED_ALPHA and NVG_STRAIGHT_ALPHA control bit 0, and a new NVG_NAKED_FRAME field is introduced, which, when set, does not make any of the above calls; so the default would be that all states are set correctly and the framebuffer is cleared for drawing.
For more granular control, if desired, NVG_NAKED_FRAME could also be a composite of three bits, which is at most NVG_KEEP_STATES (no state changes), NVG_KEEP_VIEWPORT (no viewport change) and NVG_KEEP_FRAMEBUFFER (no clear).
If none or not all of the proposed changes find their way into the codebase, I'd appreciate if the docs would be expanded by the additionally required boilerplate so others don't run into the same problems.
I was trying to write a simple utility for converting SVG files into nanovg source code. Unfortunately, the result looks a bit weird. To stroke the path, it looks exactly what I want. But to fill the path, nanovg simply draws a rectangle. This picture shows the expected and rendered results by nanovg:
The code for drawing the path is as follow:
nvgBeginPath(context);
nvgMoveTo(context, 43.438, 11.27);
nvgLineTo(context, 38.485, 11.27);
nvgBezierTo(context, 37.279, 8.237, 34.315, 6.079, 30.865, 6.079);
nvgLineTo(context, 19.135, 6.079);
nvgBezierTo(context, 15.687, 6.079, 12.723, 8.237, 11.518, 11.27);
nvgLineTo(context, 6.561, 11.27);
nvgBezierTo(context, 2.951, 11.27, 0, 14.22, 0, 17.829);
nvgLineTo(context, 0, 39.154);
nvgBezierTo(context, 0.0, 42.759, 2.951, 45.715, 6.561, 45.715);
nvgLineTo(context, 43.438, 45.715);
nvgBezierTo(context, 47.044, 45.715, 50.0, 42.76, 50.0, 39.154);
nvgLineTo(context, 50.0, 17.829);
nvgBezierTo(context, 50, 14.22, 47.044, 11.27, 43.438, 11.27);
nvgClosePath(context);
Hi And kudos for your great work on this lib.I have been expecting the source code of GL 3 core module to see if I can use it for text rendering.I found that the vertex shader doesn't use projection matrices,so I can assume the text is always in screen space.I wonder if I should expect any kind of problems if I transform the text with a perspective matrix?
Thanks.
I was a bit curious as to how people were performing layout calculations with NanoVG? Say for something as simple as a Button control that calculates its width based on its text? Or for more complex Row/Column/Table based layout?
The main issue I seem to have is with having to setup the state on a NVGcontext in order to properly calculate a text bounds based on the current font, font-size, font-blur, etc. Normally I'd have an UpdateLayout pass that sizes and positions everything, and then have the Draw come through and render using the context with everything ready to go (possibly even drawing in a background thread).
It seems like one way would be to have a separate context for the update to use that avoids any actual draw calls. Another way would be to use the font directly to compute a bounds for text, but I believe this would not perform the pixel alignment that the actual drawing code performs (though I'm not sure that nvgTextBounds performs this either).
I'm currently using cairo to do dynamic/procedural textures for our game, and I am looking for a more performant, lightweight replacement. NanoVG would qualify (as soon as miter joins / round caps work), but I'm also unhappy with cairo's current limitation to support only 8-bit per channel (http://cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t) and so it would be nice if (as NanoVG runs on GL backend) NanoVG would support rendering to 16F/32F textures that I can then use in my deferred rendering engine.
Is there any known issue between NanoVG and SDL2? Or, is there any particular OpenGL state that NanoVG needs in order for path winding (creating holes within shapes) to work, that SDL2 might be messing up?
I've recently switched my project from GLFW to SDL2, and this change has caused NanoVG output to be wrong due to missing shape holes. I've got it narrowed down to a sample program where I can toggle between using GLFW to create the window and context, and having SDL2 do it, and only the GLFW version draws correct holes.
The test program draws a red rectangle, then another green one over top with a hole. Under GLFW, you can see the red showing through, as expected. With SDL2, you just see a solid green rectangle.
This is on Linux, if it matters, using the GL3 version of NanoVG.
Here is the (heavily butchered) test program: https://gist.github.com/Nairou/ffddad31a847ccf4572b
The GLNVG_LOC_TEX binding should always be cached and set, also when compiling with NANOVG_GL_USE_UNIFORMBUFFER as the sampler is not part of the uniform buffer (it's ok in the shader though).
Hi all,
this is a patch for MinGW, a Windows version of gcc, produced native executable file for WIndows. after a little modify, I have successfully bootstrap NanoVG with MinGW, this is the patch:
diff --git a/example/demo.c b/example/demo.c
index d3d6620..3f93a43 100644
--- a/example/demo.c
+++ b/example/demo.c
@@ -13,7 +13,7 @@
#ifdef _MSC_VER
#define snprintf _snprintf
-#else
+#elif !defined(__MINGW32__)
#include <iconv.h>
#endif
diff --git a/example/perf.c b/example/perf.c
index bf36a61..94113b7 100644
--- a/example/perf.c
+++ b/example/perf.c
@@ -10,7 +10,7 @@
#ifdef _MSC_VER
#define snprintf _snprintf
-#else
+#elif !defined(__MINGW32__)
#include <iconv.h>
#endif
diff --git a/premake4.lua b/premake4.lua
index 123482d..4d320f1 100644
--- a/premake4.lua
+++ b/premake4.lua
@@ -34,7 +34,7 @@ solution "nanovg"
defines { "NANOVG_GLEW" }
configuration { "windows" }
- links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+ links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
defines { "NANOVG_GLEW" }
configuration { "macosx" }
@@ -62,7 +62,7 @@ solution "nanovg"
defines { "NANOVG_GLEW" }
configuration { "windows" }
- links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+ links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
defines { "NANOVG_GLEW" }
configuration { "macosx" }
@@ -91,7 +91,7 @@ solution "nanovg"
defines { "NANOVG_GLEW" }
configuration { "windows" }
- links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+ links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
defines { "NANOVG_GLEW" }
configuration { "macosx" }
@@ -120,7 +120,7 @@ solution "nanovg"
defines { "NANOVG_GLEW" }
configuration { "windows" }
- links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+ links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
defines { "NANOVG_GLEW" }
configuration { "macosx" }
@@ -147,7 +147,7 @@ solution "nanovg"
links { "X11","Xrandr", "rt", "GL", "GLU", "pthread", "m", "glfw3" }
configuration { "windows" }
- links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+ links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
defines { "NANOVG_GLEW" }
configuration { "macosx" }
@@ -174,7 +174,7 @@ solution "nanovg"
links { "X11","Xrandr", "rt", "GL", "GLU", "pthread", "m", "glfw3" }
configuration { "windows" }
- links { "glu32","opengl32", "gdi32", "winmm", "user32", "glfw3", "GLEW" }
+ links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" }
defines { "NANOVG_GLEW" }
configuration { "macosx" }
In the example code I added a simple rotation over time:
rotate += 0.01f;
nvgRotate(vg, rotate/180.0f*NVG_PI);
... to see how the dialog would look with a rotation-based animation. Some of the text looks fine, but on several widgets (and the title bar) the text shakes back and forth as the dialog slowly rotates. Not sure if this is an easy fix. I can't quite tell why some of it works and some doesn't.
(very cool library btw!)
This snippet tries to stroke and fill a rectangle with the same color. The result should still look like a rectangle without stroke, but it isn't.
struct NVGcontext* context = nvgCreateGLES2(GetWidth(), GetHeight(), NVG_ANTIALIAS);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
// Fill and stroke for the same rectangle with the same color.
nvgBeginFrame(context, GetWidth(), GetHeight(), GetContentScaleFactor());
nvgBeginPath(context);
nvgRect(context, 0, 0, width(), height());
nvgFillColor(context, nvgRGBA(110, 201, 235, 255));
nvgStrokeColor(context, nvgRGBA(110, 201, 235, 255));
nvgStrokeWidth(context, 10.0f);
nvgFill(context);
nvgStroke(context);
nvgEndFrame(context);
I'm using pixel ratios to have a fixed-size coordinate space to draw in which causes lines of thickness 1.0 to be several physical pixels in size, which is fine.
I do however expect a thickness < 1.0 to differ in size from a thickness of 1.0, but it seems like widths are clamped to 1.0.
For flair, it would be nice to be able to express detail finer than pxRatio.
Is this intended or unintended behaviour?
Hi,
I'm writing a Lua language binding for NanoVG, I'm trying to implement context.strokeText
, so I wondering how to stroke a text. currently NanoVG can only fill text. Is that right? then how can I implement stroke?
Hi Mikko :-)
I have tried to write a same thing like nanovg, So you know how happy I found this project! it IS great!
I just want a light-weight graphics library can be used in small game with Lua. So I will write a binding to Lua of nanovg. So there are some features I want ask.
There is a game-engine in Lua, [Love2D][love2d.org], it has custom shader support, It allows user to give two shader functions: effect
and position
, at [this][http://www.love2d.org/wiki/love.graphics.newShader].
It looks good and allow users to modify effects on screen, So may nanovg support custom shader linking/loading?
we can offer two default shader function, and if user do not specified custom shader, we use the default one, what I wonder is how to design a good interface for specify shader uniform/attribute array in a clean way.
Thx for this great work again :)
In glnvg__xformInverse():
if (det > -1e-6 && det < -1e-6) {
I think the second check should be positive 1e-6 to provide the approximately-zero check.
While I have compiled and ran nanovg successfully on my mac, I was recently trying to run the example code on my Ubuntu 13.10 laptop, which uses either an Intel or NVIDIA GPU (proprietary, binary driver) that I can select in the BIOS.
Running with either GPU, the example code doesn't render correctly, and only text appears,
Not being familiar with the underlying rendering technique, there wasn't much I could do to fix it, but I tried to narrow down the issue slightly, by modifying the shader alpha component calculation from "color.w *= strokeAlpha * scissor;", to just "color.w *= scissor;", in which case the rest of the scene appears, but the blending appears off:
Hi,
I hope NanoVG could add compositing support. it means, you can set how pixel composition with destination pixel. In HTML5 canvas, these compositing mode are used:
source-over
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
source-in
glBlendFunc(GL_DST_ALPHA, GL_ZERO);
source-out
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);
source-atop
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
destination-over
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
destination-in
glBlendFunc(GL_ZERO, GL_SRC_ALPHA)
destination-out
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
destination-atop
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA);
lighter
glBlendFunc(GL_ONE, GL_ONE);
darker
deprecated
copy
glBlendFunc(GL_ONE, GL_ZERO);
xor
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
see here
A function:
void nvgBlendMode(NVGcontext *ctx, int mode);
can be added, and add a field to NVGparams
, backend can set correct mode before any drawing.
I would like to have a way to query the upper 6 values of the current transform matrix, using a function like e.g.
void nvgQueryTransform(struct NVGcontext* ctx, float *mtx);
I'm currently implementing a UI drawing library that makes use of NanoVG's internal stack to do hierarchical transformations; An element of the lib is supposed to layout its children before drawing them, for which it needs to know its current transformation. Without this function, I'd have to do all transformations in my own code, and would not be able to use the stack at all.
The problem is the last term here, the shifting by 24.
unsigned int nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
return (r) | (g << 8) | (b << 16) | (a << 24);
}
Suppose int was at least 32 bit (which is not guaranteed, so better use uint32_t at least). Even though integral promotion is performed only shifting by at most 23 is allowed.
Shifting UCHAR_MAX by 24 yields a negative number, which is undefined behavior, too.
Need to add -framework CoreVideo to the gl2 and gl3 examples. Otherwise the linker won't find the CVDisplayLink symbols in glfw
nanovg looks incredibly useful. Do you have already plans to add support for rendering in an OpenGL Core profile, or with GLES (2/3)?
Hi,
I have updated to latest commit, and found out opengl buffered backed is great! we have amost 100+ fps at full speed. Thanks for this great feature!
We use buffered backed now is because now it support GL2, so a name nanovg_gl3buf.h is not suitable for this backend, what about only nanovg_glbuf.h ?
I have interesting to write a pure software backend (for some old device that have not OpenGL support or OpenGL support is software and very slow, e.g. the old Nokia cellphones). Is pull requests welcome?
regards,
Xavier.
On Windows I am trying to specify a larger atlas size to the glnvgCreate() call in the example.c file. Setting it to 1024x1024 (or anything other than 512x512) causes a problem with font rendering. The output is corrupt, possibly from bad uv coordinates being used to draw.
Is there some other value that I need to adjust to get this to work?
It would be great if I could get precise hit testing for paths, in a similar way that Cairo supports it.
An user could draw a path, and, instead of filling/stroking it, query whether a certain point is within the shape, using following two new proposed functions
bool nvgInFill(struct NVGcontext* ctx, float x, float y);
bool nvgInStroke(struct NVGcontext* ctx, float x, float y);
These functions would not commit their fill/stroke, only execute the test. The user would still be able to call fill/stroke afterwards, or merely clear the path.
I reckon these tests wouldn't cover text, but that's probably OK.
So as a test, I commented out the code in nvg__flattenPaths() to "Enforce winding."
// Enforce winding.
if (path->count > 2) {
area = nvg__polyArea(pts, path->count);
if (path->winding == NVG_CCW && area < 0.0f)
nvg__polyReverse(pts, path->count);
if (path->winding == NVG_CW && area > 0.0f)
nvg__polyReverse(pts, path->count);
}
as it did not seem necessary given a simple rectangle shape -- the points should have been properly generated from the start.
If this is removed, the shape will then fail the left-turn check inside nvg__expandStrokeAndFill() and presumably go through the slower non-convex fill drawing method.
With the enforce winding removed, nvg__expandStrokeAndFill()'s cross product result needs to be flipped (or the vectors need to be flipped).
So I'm assuming there's a bug then with the comparison in the "Enforce winding" check or the nvg__polyArea function that's causing the cross result to need to be checked differently?
I'm still looking over this, but as the code is now, it seems like every basic shape is going through the nvg_polyReverse() call.
Most glnvg__alloc...() functions are not respecting the requested allocation size 'n' on reallocation. The capacity is doubled in size when the buffer doesn't fit anymore, but just doubling it may not be sufficient to hold 'n' extra elements.
E.g. I had (hard to reproduce) memory corruption because glnvg__allocVerts(gl, n=314) was expanding its gl->cverts from 256 to 512 while gl->nverts was at 220.
As discussed, this is a request for newline (text wrapping) support in NanoVG's text rendering function, either as a modification to the existing nvgText(), or as a new multi-line text function.
I cant compile in vs2010, windows 8. I recieve numerous errors.
I have integrated your library into my engine:
Now i have something like this:
nvgFontSize(vg, 20.0f);
nvgFontFace(vg, "sans");
nvgFillColor(vg, nvgRGBA(255, 255, 255, 32));
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
nvgText(vg, viewport.width - 300, viewport.height - 300, "HELLO WORLD", NULL);
But text is not shown, is there any prerequesities or define i need to add?
Thanks
Since 0ec2be7 things look like for all backends:
Would it make sense for there to be a google group or mailing list?
I have lots of questions regarding using NanoVG that probably are not appropriate as Github issues.
I'm not sure if this is intentional or not, but the included examples do not seem to distinguish between framebuffer and window size correctly, and therefore the demo doesn't appear as advertised when running with a Retina display:
The framebuffer size should be indeed be used to set glViewport, but the window size should be used elsewhere. A simple fix is
glfwGetWindowSize(window, &width, &height);
nvgBeginFrame(vg, width, height);
Once this is done, the NanoVG demo appears as advertised when running with a Retina display:
I was trying to render circles on iPhone 5S. But the circle doesn't look smooth as a circle even in Retina display. I tried to change the mediump to highp but the result was not improved.
This picture shows the result I got, and I enlarged it 2x in Photoshop so it's more clear to see the result is not smooth.
The code I was using to render the circle is as follow.
const int kCenterX = (GetWidth() + 1) / 2;
const int kCenterY = (GetHeight() + 1) / 2;
nvgBeginPath(context);
nvgCircle(context, kCenterX, kCenterY, (GetWidth() - 1) / 2 - 2);
nvgFillColor(context, nvgRGBA(110, 201, 235, 180));
nvgFill(context);
nvgBeginPath(context);
nvgCircle(context, kCenterX, kCenterY, (GetWidth() - 1) / 2 - 1);
nvgStrokeColor(context, nvgRGBA(255, 255, 255, 255));
nvgStrokeWidth(context, 3);
nvgStroke(context);
nvgBeginPath(context);
nvgCircle(context, kCenterX, kCenterY, (GetWidth() - 1) / 2 - 7);
nvgFillColor(context, nvgRGBA(255, 255, 255, 255));
nvgFill(context);
The environment for setting OpenGL and nanovg context up is also very intuitive like this: https://github.com/ollix/moui/blob/master/moui/widgets/widget_view.cc
You currently use stb_truetype.h for handling fonts, which can't load .otf font files. Any opposition to using freetype instead, other than adding a dependency?
At the moment, drawing is done via Fill/Stroke, which both preserve state; The user is expected to call BeginPath to clear the current path. This becomes a perpetual nuisance, as calling BeginPath is easy to forget, so paths may be redundantly redrawn, and the mistake is very hard to detect if the paint doesn't change; Additionally, calling BeginPath turns out to be quite annoying if the path needs to be cleared after each operation, which is the usual case.
Additionally, one would expect that BeginPath has a matching EndPath, much like BeginFrame/EndFrame, but it's missing; this is confusing/surprising.
Therefore I would like to suggest following changes in the API, in the same way the Cairo API solves this, which has worked very well for me over the past years:
It would optionally be possible to rename nvgBeginPath to nvgClearPath and still keep it around, for situations where paths are started but then need not be drawn (for whatever reason), and for cases where existing users just want to do an 1:1 update of their code with a simple rename job.
At this point I should say that I'm totally fine with my proposals being shot down. It's just been things on my mind while I wrote the bindings, and I am also thinking about people (like me) who consider porting code over from cairo. The library is young and I figured this would still be a good time for basic API improvements.
In my setup, using glDebugMessageCallback(), I'm getting a debug callback when drawing a non-convex, filled shape which appears to be due to the GL_BLEND being disabled at the top of glnvg__fill(). The message is:
Program/shader state performance warning: Fragment Shader is going to be recompiled because the shader key based on GL state mismatches.
This is on a nVidia Quadro 4000. Just wondering if there is a need to disable blending there? I commented it out and it seems to render the demo fine and at the same frame-rate, but I don't think it's fill-bound right now or even drawing that many non-convex shapes.
Hi Mikko, I tried out the library but ran into some link problems from C++ ... it might be related to the main header missing the C++ guards for extern "C", as well as trying to return a value to a forward declared struct when in C++ mode.
Forgive my weak git fu, here is a patch inline in the comment.
diff --git a/src/nanovg.h b/src/nanovg.h
index fabe79c..fd8904e 100644
--- a/src/nanovg.h
+++ b/src/nanovg.h
@@ -19,10 +19,25 @@
#ifndef NANOVG_H
#define NANOVG_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define NVG_PI 3.14159265358979323846264338327f
struct NVGcontext;
-struct NVGpaint;
+struct NVGpaint
+{
enum NVGwinding {
NVG_CCW = 1, // Winding for solid shapes
@@ -355,18 +370,6 @@ enum NVGtexture {
NVG_TEXTURE_RGBA = 0x02,
};
-struct NVGpaint
-{
struct NVGscissor
{
float xform[6];
@@ -410,5 +413,8 @@ struct NVGcontext* nvgCreateInternal(struct NVGparams* params);
void nvgDeleteInternal(struct NVGcontext* ctx);
+#ifdef __cplusplus
+}
+#endif
#endif // NANOVG_H
NVG_NOTUSED should be:
It's tested with bunch of compilers and it does the right thing everywhere. Reference:
https://github.com/bkaradzic/bx/blob/master/include/bx/macros.h#L83
I would like to propose yet another backend for NanoVG based on the NV_path_rendering extension [1]. For my own code, I run primarily on NVIDIA hardware and want to take advantage of anything it has to offer, while still maintaining the portability of NanoVG. Once I have NanoVG integrated into my code, I will give this a shot, but meanwhile, just wanted to throw this idea out there.
Compiling and running the gl3 sample produces a GL_INVALID_ENUM
error on glnvg__checkError("init");
. It's not limited to the sample however, as I encounter the same error in my own GL application.
So far I've been unable to track down the source. Everything seems to be working just fine even with the error.
I use NANOVG_GL3_IMPLEMENTATION. I get "error 501 after convex fill" when i use glTexSubImage2D. And I don't see other 3d model-mesh in background.
Looks like armv7 requires that pointers be 32bit-aligned, and will throw an EXC_ARM_DA_ALIGN exception otherwise.
I was getting unaligned values from nvg__fragUniformPtr
due to gl->fragSize
being 173. Changing align
to 4 here seems to fix things:
https://github.com/memononen/nanovg/blob/master/src/nanovg_gl.h#L370
I think the real issue is that we need a special case for when align
is 1 here:
https://github.com/memononen/nanovg/blob/master/src/nanovg_gl.h#L565
I can submit a pull req if you like.
More info on the armv7 alignment issue: https://brewx.qualcomm.com/bws/content/gi/common/appseng/en/knowledgebase/docs/kb95.html
At the moment there are four different functions to configure draw paint, two for high level, two for low level, two for each stroke / fill, so a 2x2 matrix:
void nvgStrokeColor(struct NVGcontext* ctx, struct NVGcolor color);
void nvgStrokePaint(struct NVGcontext* ctx, struct NVGpaint paint);
void nvgFillColor(struct NVGcontext* ctx, struct NVGcolor color);
void nvgFillPaint(struct NVGcontext* ctx, struct NVGpaint paint);
This complicates the interface somewhat; I can't set the same color/paint for both strokes and fills at the same time - I even feel stupid writing a wrapper that does this for me, as I'm most of the time only using 50% of the setting; The API level also suffers: More paint config functions have become cumbersome as each one would have to be doubled, which is why the implementation details NVGcolor and NVGpaint are exposed, and the rest of the configuration is done through these multi-functional structs.
If both stroke and fill would happen at the same time, the above interface would make sense, but they're never seen at the same time, which lets me conclude that they are both the SAME dude, but with a different beard ;-) Therefore, I would like to propose to merge the separate states into a single one (as it works in Cairo), so that the declarations become:
void nvgColor(struct NVGcontext* ctx, struct NVGcolor color);
void nvgPaint(struct NVGcontext* ctx, struct NVGpaint paint);
Both stroke and fill operation would then source the same paint.
It would be optionally possible to hide NVGcolor/NVGpaint from the interface completely, clearing the header of structs (solving any future alignment or packing problems), and allowing to use only internal structures for context.
nvgColor would then become nvgSourceRGB, nvgSourceRGBA, nvgSourceRGB8, etc., and the old nvgRGB* functions would disappear.
All NVGpaint functions would return void, adapt the same scheme e.g. nvgSourceLinearGradient and set the internal paint directly.
Then the API would work pretty much like the cairo API does.
Of course that means the user can no longer prepare and cache source paints, but it doesn't look like being able to do so would be a big optimization. Users should arrange their calls to group similar batches anyway.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.