From 8b6835218deb8169f64a08e08e4056f6e2ebdeb6 Mon Sep 17 00:00:00 2001 From: "Adam D. Ruppe" Date: Tue, 27 Feb 2018 11:25:45 -0500 Subject: [PATCH] from ketmar: more small fixes: slightly better image API, some documentation clarifications --- nanovega.d | 55 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/nanovega.d b/nanovega.d index 90ed200..0d3a7c6 100644 --- a/nanovega.d +++ b/nanovega.d @@ -210,7 +210,10 @@ The following code illustrates the OpenGL state touched by the rendering code: NanoVega allows you to load image files in various formats (if arsd loaders are in place) to be used for rendering. In addition you can upload your own image. - The parameter imageFlags is combination of flags defined in NVGImageFlags. + The parameter imageFlags is combination of flags defined in [NVGImageFlag]. + + If you will use your image as fill pattern, it will be scaled by default. To make it repeat, pass + [NVGImageFlag.RepeatX] and [NVGImageFlag.RepeatY] flags to image creation function respectively. paints = ## Paints @@ -265,6 +268,10 @@ The following code illustrates the OpenGL state touched by the rendering code: ## Text NanoVega allows you to load .ttf files and use the font to render text. + You have to load some font, and set proper font size before doing anything + with text, as there is no "default" font provided by NanoVega. Also, don't + forget to check return value of `createFont()`, 'cause NanoVega won't fail + if it cannot load font, it will silently try to render nothing. The appearance of the text can be defined by setting the current text style and by specifying the fill color. Common text and font settings such as @@ -290,7 +297,7 @@ The following code illustrates the OpenGL state touched by the rendering code: string txt = "Text me up."; vg.textBounds(x, y, txt, bounds); vg.beginPath(); - vg.roundedRect(bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]); + vg.roundedRect(bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1], 6); vg.fill(); ---------------------- @@ -997,7 +1004,7 @@ public struct NVGTextRow(CT) if (isAnyCharType!CT) { /// Image creation flags. /// Group: images -public enum NVGImageFlags : uint { +public enum NVGImageFlag : uint { None = 0, /// Nothing special. GenerateMipmaps = 1<<0, /// Generate mipmaps during creation of the image. RepeatX = 1<<1, /// Repeat image in X direction. @@ -1008,6 +1015,8 @@ public enum NVGImageFlags : uint { Nearest = NoFiltering, /// compatibility with original NanoVG } +alias NVGImageFlags = NVGImageFlag; /// Backwards compatibility for [NVGImageFlag]. + // ////////////////////////////////////////////////////////////////////////// // package/*(arsd)*/: @@ -1464,7 +1473,7 @@ package/*(arsd)*/ NVGContext createInternal (NVGparams* params) nothrow @trusted if (ctx.fs is null) goto error; // create font texture - ctx.fontImages[0] = ctx.params.renderCreateTexture(ctx.params.userPtr, NVGtexture.Alpha, fontParams.width, fontParams.height, (ctx.params.fontAA ? 0 : NVGImageFlags.NoFiltering), null); + ctx.fontImages[0] = ctx.params.renderCreateTexture(ctx.params.userPtr, NVGtexture.Alpha, fontParams.width, fontParams.height, (ctx.params.fontAA ? 0 : NVGImageFlag.NoFiltering), null); if (ctx.fontImages[0] == 0) goto error; ctx.fontImageIdx = 0; @@ -2684,7 +2693,9 @@ public void scale (NVGContext ctx, in float x, in float y) nothrow @trusted @nog /// Creates image by loading it from the disk from specified file name. /// Returns handle to the image or 0 on error. /// Group: images -public int createImage() (NVGContext ctx, const(char)[] filename, int imageFlags=NVGImageFlags.None) { +public int createImage() (NVGContext ctx, const(char)[] filename, const(/*NVGImageFlag*/uint)[] imageFlagsList...) { + uint imageFlags = 0; + foreach (immutable uint flag; imageFlagsList) imageFlags |= flag; static if (NanoVegaHasArsdImage) { import arsd.image; // do we have new arsd API to load images? @@ -2725,8 +2736,10 @@ static if (NanoVegaHasArsdImage) { /// Creates image by loading it from the specified memory image. /// Returns handle to the image or 0 on error. /// Group: images - public int createImageFromMemoryImage() (NVGContext ctx, MemoryImage img, int imageFlags=NVGImageFlags.None) { + public int createImageFromMemoryImage() (NVGContext ctx, MemoryImage img, const(/*NVGImageFlag*/uint)[] imageFlagsList...) { if (img is null) return 0; + uint imageFlags = 0; + foreach (immutable uint flag; imageFlagsList) imageFlags |= flag; if (auto tc = cast(TrueColorImage)img) { return ctx.createImageRGBA(tc.width, tc.height, tc.imageData.bytes[], imageFlags); } else { @@ -2739,13 +2752,15 @@ static if (NanoVegaHasArsdImage) { /// Creates image by loading it from the specified chunk of memory. /// Returns handle to the image or 0 on error. /// Group: images - public int createImageMem() (NVGContext ctx, const(ubyte)* data, int ndata, int imageFlags=NVGImageFlags.None) { + public int createImageMem() (NVGContext ctx, const(ubyte)* data, int ndata, const(/*NVGImageFlag*/uint)[] imageFlagsList...) { int w, h, n, image; ubyte* img = stbi_load_from_memory(data, ndata, &w, &h, &n, 4); if (img is null) { //printf("Failed to load %s - %s\n", filename, stbi_failure_reason()); return 0; } + uint imageFlags = 0; + foreach (immutable uint flag; imageFlagsList) imageFlags |= flag; image = ctx.createImageRGBA(w, h, img[0..w*h*4], imageFlags); stbi_image_free(img); return image; @@ -2755,8 +2770,10 @@ static if (NanoVegaHasArsdImage) { /// Creates image from specified image data. /// Returns handle to the image or 0 on error. /// Group: images -public int createImageRGBA (NVGContext ctx, int w, int h, const(void)[] data, int imageFlags=NVGImageFlags.None) nothrow @trusted @nogc { +public int createImageRGBA (NVGContext ctx, int w, int h, const(void)[] data, const(/*NVGImageFlag*/uint)[] imageFlagsList...) nothrow @trusted @nogc { if (w < 1 || h < 1 || data.length < w*h*4) return 0; + uint imageFlags = 0; + foreach (immutable uint flag; imageFlagsList) imageFlags |= flag; return ctx.params.renderCreateTexture(ctx.params.userPtr, NVGtexture.RGBA, w, h, imageFlags, cast(const(ubyte)*)data.ptr); } @@ -3050,7 +3067,7 @@ public NVGLGS createLinearGradientWithStops (NVGContext ctx, float sx, float sy, foreach (immutable i; 0..stops.length-1) gradientSpan(data.ptr, stops.ptr+i, stops.ptr+i+1); } gradientSpan(data.ptr, (stops.length ? stops.ptr+stops.length-1 : &s0), &s1); - img = ctx.createImageRGBA(NVG_GRADIENT_SAMPLES, 1, data[], NVGImageFlags.RepeatX|NVGImageFlags.RepeatY); + img = ctx.createImageRGBA(NVG_GRADIENT_SAMPLES, 1, data[], NVGImageFlag.RepeatX, NVGImageFlag.RepeatY); if (img <= 0) return null; // allocate data NVGLGS res = cast(NVGLGS)malloc((*NVGLGS).sizeof); @@ -6845,7 +6862,7 @@ bool nvg__allocTextAtlas (NVGContext ctx) nothrow @trusted @nogc { ctx.imageSize(ctx.fontImages[ctx.fontImageIdx], iw, ih); if (iw > ih) ih *= 2; else iw *= 2; if (iw > NVG_MAX_FONTIMAGE_SIZE || ih > NVG_MAX_FONTIMAGE_SIZE) iw = ih = NVG_MAX_FONTIMAGE_SIZE; - ctx.fontImages[ctx.fontImageIdx+1] = ctx.params.renderCreateTexture(ctx.params.userPtr, NVGtexture.Alpha, iw, ih, (ctx.params.fontAA ? 0 : NVGImageFlags.NoFiltering), null); + ctx.fontImages[ctx.fontImageIdx+1] = ctx.params.renderCreateTexture(ctx.params.userPtr, NVGtexture.Alpha, iw, ih, (ctx.params.fontAA ? 0 : NVGImageFlag.NoFiltering), null); } ++ctx.fontImageIdx; fonsResetAtlas(ctx.fs, iw, ih); @@ -10607,7 +10624,7 @@ public enum NVGContextFlag : int { public enum NANOVG_GL_USE_STATE_FILTER = true; -/// These are additional flags on top of NVGImageFlags. +/// These are additional flags on top of [NVGImageFlag]. /// Group: images public enum NVGImageFlagsGL : int { NoDelete = 1<<16, // Do not delete GL texture handle. @@ -11097,7 +11114,7 @@ int glnvg__renderCreateTexture (void* uptr, NVGtexture type, int w, int h, int i glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); // GL 1.4 and later has support for generating mipmaps using a tex parameter. - if ((imageFlags&(NVGImageFlags.GenerateMipmaps|NVGImageFlags.NoFiltering)) == NVGImageFlags.GenerateMipmaps) glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + if ((imageFlags&(NVGImageFlag.GenerateMipmaps|NVGImageFlag.NoFiltering)) == NVGImageFlag.GenerateMipmaps) glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); if (type == NVGtexture.RGBA) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); @@ -11105,20 +11122,20 @@ int glnvg__renderCreateTexture (void* uptr, NVGtexture type, int w, int h, int i glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data); } - if ((imageFlags&(NVGImageFlags.GenerateMipmaps|NVGImageFlags.NoFiltering)) == NVGImageFlags.GenerateMipmaps) { + if ((imageFlags&(NVGImageFlag.GenerateMipmaps|NVGImageFlag.NoFiltering)) == NVGImageFlag.GenerateMipmaps) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (imageFlags&NVGImageFlags.NoFiltering ? GL_NEAREST : GL_LINEAR)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (imageFlags&NVGImageFlag.NoFiltering ? GL_NEAREST : GL_LINEAR)); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (imageFlags&NVGImageFlags.NoFiltering ? GL_NEAREST : GL_LINEAR)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (imageFlags&NVGImageFlag.NoFiltering ? GL_NEAREST : GL_LINEAR)); - if (imageFlags&NVGImageFlags.RepeatX) { + if (imageFlags&NVGImageFlag.RepeatX) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); } - if (imageFlags&NVGImageFlags.RepeatY) { + if (imageFlags&NVGImageFlag.RepeatY) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -11258,7 +11275,7 @@ bool glnvg__convertPaint (GLNVGcontext* gl, GLNVGfragUniforms* frag, NVGPaint* p if (paint.image != 0) { tex = glnvg__findTexture(gl, paint.image); if (tex is null) return false; - if ((tex.flags&NVGImageFlags.FlipY) != 0) { + if ((tex.flags&NVGImageFlag.FlipY) != 0) { /* NVGMatrix flipped; nvgTransformScale(flipped[], 1.0f, -1.0f); @@ -11289,7 +11306,7 @@ bool glnvg__convertPaint (GLNVGcontext* gl, GLNVGfragUniforms* frag, NVGPaint* p frag.type = NSVG_SHADER_FILLIMG; if (tex.type == NVGtexture.RGBA) { - frag.texType = (tex.flags&NVGImageFlags.Premultiplied ? 0 : 1); + frag.texType = (tex.flags&NVGImageFlag.Premultiplied ? 0 : 1); } else { frag.texType = 2; }