Antialiased 2D vector drawing library on top of OpenGL for UI and visualizations.

Related tags

Graphics nanovg
Overview

This project is not actively maintained.

NanoVG

NanoVG is small antialiased vector graphics rendering library for OpenGL. It has lean API modeled after HTML5 canvas API. It is aimed to be a practical and fun toolset for building scalable user interfaces and visualizations.

Screenshot

screenshot of some text rendered witht the sample program

Usage

The NanoVG API is modeled loosely on HTML5 canvas API. If you know canvas, you're up to speed with NanoVG in no time.

Creating drawing context

The drawing context is created using platform specific constructor function. If you're using the OpenGL 2.0 back-end the context is created as follows:

#define NANOVG_GL2_IMPLEMENTATION	// Use GL2 implementation.
#include "nanovg_gl.h"
...
struct NVGcontext* vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES);

The first parameter defines flags for creating the renderer.

  • NVG_ANTIALIAS means that the renderer adjusts the geometry to include anti-aliasing. If you're using MSAA, you can omit this flags.
  • NVG_STENCIL_STROKES means that the render uses better quality rendering for (overlapping) strokes. The quality is mostly visible on wider strokes. If you want speed, you can omit this flag.

Currently there is an OpenGL back-end for NanoVG: nanovg_gl.h for OpenGL 2.0, OpenGL ES 2.0, OpenGL 3.2 core profile and OpenGL ES 3. The implementation can be chosen using a define as in above example. See the header file and examples for further info.

NOTE: The render target you're rendering to must have stencil buffer.

Drawing shapes with NanoVG

Drawing a simple shape using NanoVG consists of four steps: 1) begin a new shape, 2) define the path to draw, 3) set fill or stroke, 4) and finally fill or stroke the path.

nvgBeginPath(vg);
nvgRect(vg, 100,100, 120,30);
nvgFillColor(vg, nvgRGBA(255,192,0,255));
nvgFill(vg);

Calling nvgBeginPath() will clear any existing paths and start drawing from blank slate. There are number of number of functions to define the path to draw, such as rectangle, rounded rectangle and ellipse, or you can use the common moveTo, lineTo, bezierTo and arcTo API to compose the paths step by step.

Understanding Composite Paths

Because of the way the rendering backend is build in NanoVG, drawing a composite path, that is path consisting from multiple paths defining holes and fills, is a bit more involved. NanoVG uses even-odd filling rule and by default the paths are wound in counter clockwise order. Keep that in mind when drawing using the low level draw API. In order to wind one of the predefined shapes as a hole, you should call nvgPathWinding(vg, NVG_HOLE), or nvgPathWinding(vg, NVG_CW) after defining the path.

nvgBeginPath(vg);
nvgRect(vg, 100,100, 120,30);
nvgCircle(vg, 120,120, 5);
nvgPathWinding(vg, NVG_HOLE);	// Mark circle as a hole.
nvgFillColor(vg, nvgRGBA(255,192,0,255));
nvgFill(vg);

Rendering is wrong, what to do?

  • make sure you have created NanoVG context using one of the nvgCreatexxx() calls
  • make sure you have initialised OpenGL with stencil buffer
  • make sure you have cleared stencil buffer
  • make sure all rendering calls happen between nvgBeginFrame() and nvgEndFrame()
  • to enable more checks for OpenGL errors, add NVG_DEBUG flag to nvgCreatexxx()
  • if the problem still persists, please report an issue!

OpenGL state touched by the backend

The OpenGL back-end touches following states:

When textures are uploaded or updated, the following pixel store is set to defaults: GL_UNPACK_ALIGNMENT, GL_UNPACK_ROW_LENGTH, GL_UNPACK_SKIP_PIXELS, GL_UNPACK_SKIP_ROWS. Texture binding is also affected. Texture updates can happen when the user loads images, or when new font glyphs are added. Glyphs are added as needed between calls to nvgBeginFrame() and nvgEndFrame().

The data for the whole frame is buffered and flushed in nvgEndFrame(). The following code illustrates the OpenGL state touched by the rendering code:

	glUseProgram(prog);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
	glFrontFace(GL_CCW);
	glEnable(GL_BLEND);
	glDisable(GL_DEPTH_TEST);
	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);
	glActiveTexture(GL_TEXTURE0);
	glBindBuffer(GL_UNIFORM_BUFFER, buf);
	glBindVertexArray(arr);
	glBindBuffer(GL_ARRAY_BUFFER, buf);
	glBindTexture(GL_TEXTURE_2D, tex);
	glUniformBlockBinding(... , GLNVG_FRAG_BINDING);

API Reference

See the header file nanovg.h for API reference.

Ports

Projects using NanoVG

License

The library is licensed under zlib license Fonts used in examples:

Discussions

NanoVG mailing list

Links

Uses stb_truetype (or, optionally, freetype) for font rendering. Uses stb_image for image loading.

Comments
  • The rendered result doesn't look nice

    The rendered result doesn't look nice

    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. nanovg_circle

    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

    opened by olliwang 29
  • Weird line on shape boundary

    Weird line on shape boundary

    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);
    

    The result picture looks like this, pretty weird. nanovg

    opened by olliwang 27
  • Two framebuffers conflict with each other

    Two framebuffers conflict with each other

    I'm trying to make two dynamic framebuffer brushes and draw with them, but I have problem with color rendering - colors change and blink randomly.

    The exact code:

        // Creating framebuffer 1
    
        if (fb == NULL) fb = nvgluCreateFramebuffer(vg, 100, 100, NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
        if (fb == NULL) {
            printf("Could not create FBO.\n");
            return;
        }
    
        nvgluBindFramebuffer(fb);
        glViewport(0, 0, 100, 100);
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
        nvgBeginFrame(vg, 100, 100, 1);
    
        nvgBeginPath(vg);
        nvgRoundedRect(vg, 0, 0, 50.0f, 50.0f, 10.0f);      // Round rect
        nvgFillColor(vg, nvgRGB(255, 128, 128));            // Red color
        nvgFill(vg);
    
        nvgEndFrame(vg);
    
        // Creating framebuffer 2
    
        if (fb2 == NULL) fb2 = nvgluCreateFramebuffer(vg, 100, 100, NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
        if (fb2 == NULL) {
            printf("Could not create FBO.\n");
            return;
        }
        nvgluBindFramebuffer(fb2);
        glViewport(0, 0, 100, 100);
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
        nvgBeginFrame(vg, 100, 100, 1);
    
        nvgBeginPath(vg);
        nvgRect(vg, 0, 0, 50.0f, 50.0f);                // Rectangle
        nvgFillColor(vg, nvgRGB(128, 255, 128));        // Green color
        nvgFill(vg);
    
        nvgEndFrame(vg);
    
        // Rendering the main screen
    
        nvgluBindFramebuffer(0);
    
        NVGpaint fbPaint = nvgImagePattern(vg, 0, 0, 50, 50, 0, fb->image, 1.0f);
        NVGpaint fbPaint2 = nvgImagePattern(vg, 0, 0, 200, 200, 0, fb2->image, 0.5f);
    
        glfwGetWindowSize(window, &winWidth, &winHeight);
        glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
    
        // Calculate pixel ration for hi-dpi devices.
        pxRatio = (float)fbWidth / (float)winWidth;
    
        // Update and render
        glViewport(0, 0, fbWidth, fbHeight);
        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    
        nvgBeginFrame(vg, fbWidth, fbHeight, pxRatio);
    
        nvgBeginPath(vg);
        nvgRect(vg, 0.0f, 0.0f, winWidth, winHeight);
        nvgFillPaint(vg, fbPaint);
        nvgFill(vg);
    
        nvgBeginPath(vg);
        nvgRect(vg, 0.0f, 0.0f, winWidth, winHeight);
        nvgFillPaint(vg, fbPaint2);
        nvgFill(vg);
    
        nvgEndFrame(vg);
    

    Result: ss1 ss2

    The correct result (as I expect it) should be big green semi-transparent squares over little pink round-rect squares. The actual result has correct shape, but colors blink and change randomly each frame between green, pink and black. Colors of both layers change independently.

    What am I doing wrong?

    opened by bigfatbrowncat 19
  • android example?

    android example?

    Hello, in the issues, several people seem to talk about using nanovg on android like it was nothing. However, the examples all use glfw, which is not available on android. Someone was making SDL port (judging from the issues), but didn't share it anywhere. And the bgfx port is plagued with c++, and their 'c99 api' doesn't extend to nanovg, that they felt the need to c++-ize as well. What is it that I am missing? Why can't I just make a simple app for android without using java? Can someone please help me understand how to use nanovg on android? Just drawing, touch and ideally keyboard, but I guess I would rather make my own keyboard then use c++ just because bgfx author does. Sorry to bother you, but it seems like making C apps shouldn't be as difficult as it seems to me right now. Thanks for help :)

    opened by Mis012 18
  • Can't get font-rendering to work at all

    Can't get font-rendering to work at all

    For technical reasons I can't use glfw, so I had to roll my own window and context creation. After some fidgeting, I got NanoVG to work, so I can draw lines etc. now.

    But no text will ever render.

    I've reduced my render function to

    nvgBeginFrame(vg, width, height, 1.f);
    renderGraph(vg, 10, 10, &fps);
    nvgEndFrame(vg); 
    

    I've loaded a font etc. and in renderGraph the cursor position changes (nvgText returns a higher X coordinate than I feed in), but still I can't see any text.

    I've made sure the font is loaded correctly etc. It seems to be some sort of culling is going on, but no amount of glEnable/glDisable calls has been able to fix it.

    The weirdest thing is that I can't run a debug-version. It crashes during the first memset() in fonsCreateInternal(). No crashes in release...

    Please help if you can.

    opened by reFX-Mike 18
  • Image color is wrong in OpenGL ES 2

    Image color is wrong in OpenGL ES 2

    I was trying to draw an image with white background and 0.5 alpha value as this one: screen shot 2014-06-26 at 21 41 15

    It works fine when running on Mac (OpenGL 2).. screen shot 2014-06-26 at 21 57 00

    And works fine for iPhone simulator.. screen shot 2014-06-26 at 21 48 45

    But shows weird color when running on a real iPhone device (OpenGL ES 2) img_2552

    The drawing code is as follow:

    nvgBeginPath(context);
    nvgRect(context, 0, 0, GetWidth(), GetHeight());
    nvgFillColor(context, nvgRGBA(255, 0, 0, 255));
    nvgFill(context);
    
    struct NVGpaint paint = nvgImagePattern(context, 0, 0, 256, 256, 0, image_handle, NVG_NOREPEAT, 1);
    nvgBeginPath(context);
    nvgRect(context, 30, 30, 256, 256);
    nvgFillPaint(context, paint);
    nvgFill(context);
    

    So I guess something is wrong in the latest update?

    opened by olliwang 18
  • Incorrect width of

    Incorrect width of " " (space) character

    It looks like if I measure a single white space character with nvgTextBounds(..., bounds), I every time get bounds[0] = -1 and bounds[2] = 1, no matter which font size is selected. That leads to different behavior if I render "Some text" by a single string and "Some" + " " + "text" word by word with spaces between.

    What's the cause of this? Is this a bug?

    opened by bigfatbrowncat 17
  • nanovg is super slow on iPad 2/iPad 3/iPhone 4s

    nanovg is super slow on iPad 2/iPad 3/iPhone 4s

    Hi, is it possible to improve the performance on OpenGL ES further? I am developing an app for iOS 8 and usually I can get over 50 FPS for iPhone 6/5s without problem. But, it's pretty hard to get over 10 FPS on iPad 2/iPad 3/iPhone 4s and unfortunately all of these devices are still supported by iOS 8.

    I was trying to run the Instruments with the OpenGL ES Analyzer module for iPad 2/3, and it seems the reason all pointing to the glDrawArrays(GL_TRIANGLE_XXXXX, XX, XX) command.

    screen shot 2014-11-20 at 23 30 12

    Here are some suggestions from the Instruments for the top four situations that happened mostly. Does this help? Thanks.

    1. Dependent Texture Sampling

    The fragment shader performed dependent texture reads, which are slower than non-dependent texture reads. Dependent texture reads happen when the texture coordinates are modified in the fragment shader, or when the Project or Bias variants of the texture sampling functions are called. Use dependent texture samples sparingly. If you modify texture coordinates in the fragment shader, try to move the calculations of the texture coordinates to the vertex shader so that they occur once per vertex instead of once per fragment. This can help improve performance.

    screen shot 2014-11-20 at 23 46 52

    1. Fragment Shader Dynamic Branching + Memory Access

    Your fragment shader contains dynamic branch instructions and accesses main memory (either because of data spilling or a dependent texture sampling operation), which is an expensive combination for the GPU. To improve performance, rework the shader to eliminate one or more of these characteristics.

    screen shot 2014-11-20 at 23 47 14

    1. Loss Of Depth Test Hardware Optimizations

    Depth test hardware optimizations allow the GPU to skip calculations for pixels that would be discarded by the depth test.

    Your application used the following feature: discard fragment in a fragment shader. If possible, rework your rendering pipeline to avoid using this feature. If you must draw using this feature, attempt to do so at the end of each frame while covering the fewest number of pixels possible.

    screen shot 2014-11-20 at 23 47 23

    1. Uninitialized Texture Data

    Your application made a drawing call using a texture that contains uninitialized data. If a draw call uses uninitialized data, the rendering results are incorrect and unpredictable. One way to fix this issue is to provide image data to any TexImage2D calls instead of a NULL pointer.

    screen shot 2014-11-20 at 23 47 38

    opened by olliwang 15
  • How to Get Feature Pull Requests Accepted

    How to Get Feature Pull Requests Accepted

    I am currently working on a project that is using NanoVG. It's called Wima, and NanoVG is what does all of the drawing.

    However, I have a problem: in order for Wima to be feature complete, I need a certain feature, specifically Picking/Hit Regions (#401). I have already created the pull request and I keep merging changes from this repo into mine to keep it merge-ready. Despite all of that, nothing has been said about it, even though bug fix pull requests have been accepted.

    How can I get this pull request accepted?

    opened by gavinhoward 14
  • Proposal: Ensure all required GL states are correct in beginFrame

    Proposal: Ensure all required GL states are correct in beginFrame

    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.

    opened by paniq 14
  • Bug ? The glyphs rendered are not on the same line

    Bug ? The glyphs rendered are not on the same line

    Strange text rendering results when I render English and Chinese characters at the same time

    Here is the rendering results of nanovg and sdl_ttf Screenshot_20220210_182822

    Compared to SDL_ TTF,The Chinese glyphs and English glyphs seem to be not in the same line It was much lower than English glyphs

    It looks doesnot very good

    Here is the code

    
    //text and the fontsize
    const char *text = "啊AB啊C啊D啊E啊F界 Hello哈哈哈World";
    float fontsize = 12;
    
    //Setup nanovg ctxt
    ...
    //Load ttf
    //Microsoft Ya Hei
    int f = nvgCreateFont(ctxt,"font","./msyh.ttc");
    TTF_Font *ttf = TTF_OpenFont("./msyh.ttc",fontsize);
    
    //SDL_TTF Render text 
    SDL_Color color;
    color.r = 0;
    color.g = 0;
    color.b = 0;
    color.a = 255;
    
    SDL_Surface *surf = TTF_RenderUTF8_Blended(ttf,text,color);
    
    TTF_CloseFont(font);
    
    int image = nvgCreateImageRGBA(
            ctxt,
            surf->w,
            surf->h,
            NVG_IMAGE_NEAREST,
            (Uint8*)surf->pixels
    );
    ...
    
    //Clear background
    //nvgBeginFrame ...
    
    //nanovg draw text
    nvgBeginPath(ctxt);
    nvgFillColor(ctxt,nvgRGB(0,0,0));
    nvgFontFaceId(ctxt,f);
    nvgFontSize(ctxt,fontsize);
    nvgTextAlign(ctxt,NVG_ALIGN_TOP |  NVG_ALIGN_LEFT);
    nvgText(ctxt,100,300,text,nullptr);
    nvgFill(ctxt);
    //SDL_ttf draw text
    nvgBeginPath(ctxt);
    nvgRect(ctxt,100,100,surf->w,surf->h);
    nvgFillPaint(ctxt,nvgImagePattern(ctxt,
          100,
          100,
          surf->w,
          surf->h,
          0.0f/180.0f*NVG_PI,
          image,
          1.0f
     ));
    nvgFill(ctxt);
    
    
    //EndFrame ...
    //SwapBuffer ...
    

    Here is the font msyh.zip

    Can anyone help me?

    opened by BusyStudent 13
  • Edges of the curve are drawn at an angle

    Edges of the curve are drawn at an angle

    I entered the data from the svg file for the bezier curve, but the edges of the curve are drawn at an angle, uneven. But in the browser the svg file is drawn with straight ends. And the cairo library also draws straight. But gdi/gdi+ also draws unevenly. Is everything smooth in adobe illustrator too. What could be the problem? `

        nvgBeginPath(vg);
        float x = 168.f;
        float y = 37.f;
        nvgMoveTo(vg, 168.f, 37.f);
        nvgBezierTo(vg, 0 + x, 35.4f + y, 39.4f + x, 64 + y, 88 + x, 64 + y);
        nvgStrokeColor(vg, nvgRGBA(0, 0, 0, 255));
        nvgStrokeWidth(vg, 32); 
        nvgStroke(vg);`
    

    svg code: <?xml version="1.0" encoding="utf-8"?> <svg version="1.2" baseProfile="tiny" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 510 512" overflow="visible" xml:space="preserve"> <path fill="none" stroke="#000000" stroke-width="32" stroke-miterlimit="10" d="M168,37c0,35.4,39.4,64,88,64"/> </svg> 2022-10-27_19-29-24

    And this is what the curve looks like in the browser: 2022-09-12_23-35-32

    opened by Andr91ew 8
  • Layer based drawing

    Layer based drawing

    Hi, The current implementation draws everything sequentially on top of last drawing shape. Is it possible to create a layer based approach? It's like you will store all the drawing call to a layer and draw it later. For example:

    1. Draw Rectangle
    2. Store Circle
    3. Draw Rectangle
    4. Draw stored circle

    Cheers

    opened by prashant-saxena 1
  • Fix text jitter for animated (moving) text

    Fix text jitter for animated (moving) text

    Font stash returns glyph positions in integer pixels. When rendering text at floating point positions, glyph positions get rounded to the nearest pixel. This is particularly noticeable with animated moving text, giving the appearance of jitter relative to other animated graphics. To circumvent this problem, this PR renders text at the origin (0,0) and then translates it afterwards to the proper floating point pixel location. This is possible because text rendering is shift invariant. In addition to updating the draw text call, all the methods for getting text bounds and positions have been updated as well.

    dump

    opened by rgb2hsv 2
  • Forward bitmapOption to fons__tt_buildGlyphBitmap

    Forward bitmapOption to fons__tt_buildGlyphBitmap

    This can avoid unneccessary rasterization. (see #643) In one demo, where I am using glyph measurements quite a lot, I could get 360fps instead of 330fps with this change.

    I also added two functions fons__tt_getGlyphRenderFlags and fons__tt_setGlyphRenderFlags so that flags like FT_LOAD_TARGET_LIGHT for rasterization can be set or unset and don't have to be compiled in.

    opened by mulle-nat 0
  • Fundamental text layout problem in nanovg

    Fundamental text layout problem in nanovg

    The layout and drawing code of nanovg uses fonsTextIterInit and fonsTextIterNext to step through the glyphs. fonsTextIterInit needs to adjust the coordinates for the given origin and alignment (like NVG_ALIGN_CENTER). For that fonsTextIterInit needs to know the width of the text line, to adjust the origin, as the string is always drawn left to right.

    fonsTextIterInit calls fonsTextBounds to calculate the width. fonsTextBounds is basically another simpler rover over the glyphs, that calculates the width. But it's calculation is unfortunately not compatible with that of nvgText or nvgTextGlyphPositions:

    fontstash

    fonsTextBounds:

    if (q.x0 < minx) minx = q.x0;
    if (q.x1 > maxx) maxx = q.x1;
    

    nanovg

    nvgTextGlyphPositions uses iter.x and iter.nextx:

    positions[npos].minx = nvg__minf(iter.x, q.x0) * invscale;
    positions[npos].maxx = nvg__maxf(iter.nextx, q.x1) * invscale;
    

    So that's where I think the differences in nvgTextBounds happen, as nvgTextBounds relies solely on fonsTextBounds. From a software engineering perspective though, the situation is unfortunate. The decision to use iter.x and iter.nextx is made in nanovg, so it's not transparent to fontstash. But the alignment values are defined and calculated in fontstash, which would need that information for accuracy.

    I am currently of the opinion, that using the alignment implementation of fontstash is a mistake and alignment should be done in nanovg. But hacking fonsTextBounds to also use the whatever the values of iter.x and iter.nextx are, could work too...

    opened by mulle-nat 0
  • FONS_GLYPH_BITMAP_OPTIONAL doesn't inhibit FT_LOAD in fons__tt_buildGlyphBitmap

    FONS_GLYPH_BITMAP_OPTIONAL doesn't inhibit FT_LOAD in fons__tt_buildGlyphBitmap

    nanovg uses the FONS_GLYPH_BITMAP_OPTIONAL flag in various places to avoid the creation of superflous font atlas entries for glyphs. The actual glyph information is queried by fons__tt_buildGlyphBitmap, which always uses FT_LOAD_RENDER to render a (then unneeded) bitmap though. This is probably expensive and could be avoided, by passing an extra parameter to fons__tt_buildGlyphBitmap, telling FreeType not to.

    fontstash.h:

    	ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT);
    	if (ftError) return 0;
    

    The same should be done for stb_truetype (or could be harmlessly ignored, if not supported there).

    opened by mulle-nat 0
Owner
Mikko Mononen
Mikko Mononen
OpenGL®-Starter is a template for your upcoming OpenGL Projects which has been compiled to run the most basic Hello World OpenGL Program from LearnOpenGL.com.

OpenGL®-Starter OpenGL®-Starter is a template for your upcoming OpenGL Projects which has been compiled to run the most basic Hello World OpenGL Progr

Kushagra 9 Sep 7, 2022
Orbit is a multiplatform-focus graphical engine build on top of OpenGl, ImGui

Orbit Engine Orbit is a multiplatform-focus graphical engine build on top of OpenGl, ImGui and more... The development of the engine is documented via

Madsycode 11 Jul 3, 2021
A very simple and light-weight drawing app made with qt and C++.

Blackboard A very simple and light-weight drawing app made with qt and C++. It supports tablet and pen pressure with the help of QTabletEvents. So you

null 1 Nov 15, 2021
Pencil2D is an animation/drawing software for Windows, macOS, Linux, and FreeBSD.

Pencil2D is an animation/drawing software for Windows, macOS, Linux, and FreeBSD. It lets you create traditional hand-drawn animation (cartoon) using both bitmap and vector graphics. Pencil2D is free and open source.

Pencil2D 1.2k Nov 21, 2022
An immediate-mode, renderer agnostic, lightweight debug drawing API for C++

Debug Draw An immediate-mode, renderer agnostic, lightweight debug drawing API for C++. License This software is in the public domain. Where that dedi

Guilherme Lampert 452 Nov 26, 2022
A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input

GLFW Introduction GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan application development. It provides a simple, platf

GLFW 9.8k Nov 19, 2022
A legacy OpenGL simulator for OpenGL 4.4, written in C++.

the-ancient-tri A legacy OpenGL simulator for OpenGL 4.4, written in C++. Why? My Uni forces us to use legacy OpenGL (eww!), and I didn't want to lear

Mohammad Issawi 4 Feb 10, 2022
rlottie is a platform independent standalone c++ library for rendering vector based animations and art in realtime

rlottie rlottie is a platform independent standalone c++ library for rendering vector based animations and art in realtime. Lottie loads and renders a

Samsung 759 Nov 27, 2022
2D Vector Graphics Engine Powered by a JIT Compiler

Blend2D 2D Vector Graphics Powered by a JIT Compiler. Official Home Page (blend2d.com) Official Repository (blend2d/blend2d) Public Chat Channel Zlib

Blend2D 1.1k Nov 23, 2022
Utility on top of the Flutter Driver API that facilitates measuring the performance of your app in an automated way created by Very Good Ventures 🦄

Very Good Performance Developed with ?? by Very Good Ventures ?? Utility on top of the Flutter Driver API that facilitates measuring the performance o

Very Good Open Source 80 Nov 22, 2022
Low Level Graphics Library (LLGL) is a thin abstraction layer for the modern graphics APIs OpenGL, Direct3D, Vulkan, and Metal

Low Level Graphics Library (LLGL) Documentation NOTE: This repository receives bug fixes only, but no major updates. Pull requests may still be accept

Lukas Hermanns 1.5k Nov 28, 2022
Yet another Chip-8 interpreter, this time written in C++ using GLFW and OpenGL as its graphics library 💻

Yet another Chip-8 interpreter, but this time with a beautiful interface ??

Akshit Garg 32 Nov 21, 2022
Epoxy is a library for handling OpenGL function pointer management for you

Epoxy is a library for handling OpenGL function pointer management for you. It hides the complexity of dlopen(), dlsym(), glXGetProcAddress(), eglGetP

Eric Anholt 574 Nov 24, 2022
3D engine from scratch (without OpenGL or any other 3D graphics library)

Simple 3d engine based on SFML library. I tried to make this engine powerful and easy to understand.

Vectozavr 62 Nov 16, 2022
OpenGL Object Loading can load virtually every 3d.obj file you can find on the internet, without using another object loading library

OpenGL Object Loading can load virtually every 3d.obj file you can find on the internet, without using another object loading library (assimp for example). The program can load Object with 12M+ triangles and more

Phan Sang 12 Oct 13, 2022
NodeEditor basiced on Qt and OpenGL/CV

Vapour 基于Qt的轻量级的节点式几何建模工具与shader材质生成工具 可能加入图像处理(合成)的功能 日志: 2021-5-17: 完成背景绘制,右键菜单,节点连线,节点删除,初步拓扑排序 (细节)连线位于节点层级之下,使用lambda处理右键菜单slot,节点创建生成在鼠标位置处 2021

Cuimi 15 Aug 11, 2022
Tetris written with C++ and OpenGL.

Tetrec This is yet another Tetris game, which is in 3D, written using C++ and OpenGL 2.1, aiming at being lightweight towards not-so-beefy computers (

Lê Duy Quang 14 Jan 17, 2022
A simple single point light shadow mapping with OpenGL 3.3 and C++

omni-directional-light-example Using OpenGL 3.3 with C++ Basically a single light map, no lighting model was used Usage Build the executable outside A

Mohammad Issawi 4 Feb 10, 2022
A simple mirror simulator made with OpenGL 3.3 and C++

Mirror-Example A simple mirror example using OpenGL 3.3 with C++. Theory It basically constructs a camera at the mirror location, by determining its v

Mohammad Issawi 4 Feb 10, 2022