packages feed

nanovg 0.5.2.0 → 0.6.0.0

raw patch · 14 files changed

+358/−94 lines, 14 filesdep ~basedep ~containers

Dependency ranges changed: base, containers

Files

CHANGELOG.md view
@@ -1,3 +1,10 @@+0.6.0.0+---++* GL2 support+* openGLES3 support+* Drop support for GHC 7.10+ 0.5.2.0 --- * MacOS support
README.md view
@@ -1,6 +1,7 @@ # NanoVG Haskell bindings -[![Build Status](https://travis-ci.org/cocreature/nanovg-hs.svg?branch=master)](https://travis-ci.org/cocreature/nanovg-hs)+[![Build Status](https://img.shields.io/travis/cocreature/nanovg-hs.svg)](https://travis-ci.org/cocreature/nanovg-hs)+[![Hackage](https://img.shields.io/hackage/v/nanovg.svg)](https://hackage.haskell.org/package/nanovg)  Currently only the GL3 backend is supported. 
cbits/nanovg_gl.c view
@@ -1,7 +1,17 @@+#if defined(GLES_3)+#define NANOVG_GLES3_IMPLEMENTATION+#elif defined(GL_2)+#define NANOVG_GL2_IMPLEMENTATION+#else #define NANOVG_GL3_IMPLEMENTATION+#endif // This is used to link the implementation #if defined(darwin_HOST_OS)+#if defined(GL_2)+#include <OpenGL/gl.h>+#else #include <OpenGL/gl3.h>+#endif #else #include "GL/glew.h" #endif
nanovg.cabal view
@@ -1,5 +1,5 @@ name:                nanovg-version:             0.5.2.0+version:             0.6.0.0 synopsis:            Haskell bindings for nanovg description:         Raw bindings to the OpenGL vector graphics library NanoVG homepage:            https://github.com/cocreature/nanovg-hs@@ -14,7 +14,7 @@   README.md   CHANGELOG.md cabal-version:       >=1.10-tested-with:         GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1+tested-with:         GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.2  source-repository head   type:     git@@ -25,14 +25,27 @@   default:     False   manual:      True +flag gles3+  description: Build for GLES3. This deactivates GL3 support.+  default:     False+  manual:      True++flag gl2+  description: Build for GL2. This deactivates GL3 support.+  default:     False+  manual:      True+ library   exposed-modules:     NanoVG                        NanoVG.Internal                        NanoVG.Internal.Color+                       NanoVG.Internal.CreateContext                        NanoVG.Internal.Context                        NanoVG.Internal.FFIHelpers                        NanoVG.Internal.FixedVector                        NanoVG.Internal.GL3+                       NanoVG.Internal.GL2+                       NanoVG.Internal.GLES3                        NanoVG.Internal.Image                        NanoVG.Internal.Paint                        NanoVG.Internal.Path@@ -42,11 +55,11 @@                        NanoVG.Internal.Text                        NanoVG.Internal.Transformation                        NanoVG.Internal.Types-  build-depends:       base >= 4.7 && <5.0+  build-depends:       base >= 4.8 && <5.0                      , bytestring >= 0.10 && < 0.11                      , containers >= 0.5 && < 0.6                      , text >= 1.2 && < 1.3-                     , vector >= 0.11 && < 0.12+                     , vector >= 0.11 && < 0.13   hs-source-dirs:      src   default-language:    Haskell2010   include-dirs:        nanovg/src@@ -67,7 +80,13 @@     cc-options:          -Ddarwin_HOST_OS   else     extra-libraries:     GLU, GL, m, GLEW-    ghc-options:         -pgml gcc "-optl-Wl,--whole-archive" "-optl-Wl,-lGLEW" "-optl-Wl,--no-whole-archive"+    pkgconfig-depends: glew+  if flag(gles3)+    cpp-options:       -DGLES_3+    cc-options:        -DGLES_3+  if flag(gl2)+    cpp-options:       -DGL_2+    cc-options:        -DGL_2   build-tools:         c2hs  executable example00
nanovg/src/fontstash.h view
@@ -38,6 +38,11 @@ 	FONS_ALIGN_BASELINE	= 1<<6, // Default }; +enum FONSglyphBitmap {+	FONS_GLYPH_BITMAP_OPTIONAL = 1,+	FONS_GLYPH_BITMAP_REQUIRED = 2,+};+ enum FONSerrorCode { 	// Font atlas is full. 	FONS_ATLAS_FULL = 1,@@ -78,6 +83,7 @@ 	const char* next; 	const char* end; 	unsigned int utf8state;+	int bitmapOption; }; typedef struct FONStextIter FONStextIter; @@ -122,7 +128,7 @@ void fonsVertMetrics(FONScontext* s, float* ascender, float* descender, float* lineh);  // Text iterator-int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, float x, float y, const char* str, const char* end);+int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, float x, float y, const char* str, const char* end, int bitmapOption); int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, struct FONSquad* quad);  // Pull texture changes@@ -873,7 +879,8 @@ int fonsAddFont(FONScontext* stash, const char* name, const char* path) { 	FILE* fp = 0;-	int dataSize = 0, readed;+	int dataSize = 0;+	size_t readed; 	unsigned char* data = NULL;  	// Read in the font data.@@ -1029,7 +1036,7 @@ }  static FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned int codepoint,-								 short isize, short iblur)+								 short isize, short iblur, int bitmapOption) { 	int i, g, advance, lsb, x0, y0, x1, y1, gw, gh, gx, gy, x, y; 	float scale;@@ -1052,12 +1059,18 @@ 	h = fons__hashint(codepoint) & (FONS_HASH_LUT_SIZE-1); 	i = font->lut[h]; 	while (i != -1) {-		if (font->glyphs[i].codepoint == codepoint && font->glyphs[i].size == isize && font->glyphs[i].blur == iblur)-			return &font->glyphs[i];+		if (font->glyphs[i].codepoint == codepoint && font->glyphs[i].size == isize && font->glyphs[i].blur == iblur) {+			glyph = &font->glyphs[i];+			if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL || (glyph->x0 >= 0 && glyph->y0 >= 0)) {+			  return glyph;+			}+			// At this point, glyph exists but the bitmap data is not yet created.+			break;+		} 		i = font->glyphs[i].next; 	} -	// Could not find glyph, create it.+	// Create a new glyph or rasterize bitmap data for a cached glyph. 	g = fons__tt_getGlyphIndex(&font->font, codepoint); 	// Try to find the glyph in fallback fonts. 	if (g == 0) {@@ -1078,20 +1091,34 @@ 	gw = x1-x0 + pad*2; 	gh = y1-y0 + pad*2; -	// Find free spot for the rect in the atlas-	added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy);-	if (added == 0 && stash->handleError != NULL) {-		// Atlas is full, let the user to resize the atlas (or not), and try again.-		stash->handleError(stash->errorUptr, FONS_ATLAS_FULL, 0);+	// Determines the spot to draw glyph in the atlas.+	if (bitmapOption == FONS_GLYPH_BITMAP_REQUIRED) {+		// Find free spot for the rect in the atlas 		added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy);+		if (added == 0 && stash->handleError != NULL) {+			// Atlas is full, let the user to resize the atlas (or not), and try again.+			stash->handleError(stash->errorUptr, FONS_ATLAS_FULL, 0);+			added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy);+		}+		if (added == 0) return NULL;+	} else {+		// Negative coordinate indicates there is no bitmap data created.+		gx = -1;+		gy = -1; 	}-	if (added == 0) return NULL;  	// Init glyph.-	glyph = fons__allocGlyph(font);-	glyph->codepoint = codepoint;-	glyph->size = isize;-	glyph->blur = iblur;+	if (glyph == NULL) {+		glyph = fons__allocGlyph(font);+		glyph->codepoint = codepoint;+		glyph->size = isize;+		glyph->blur = iblur;+		glyph->next = 0;++		// Insert char to hash lookup.+		glyph->next = font->lut[h];+		font->lut[h] = font->nglyphs-1;+	} 	glyph->index = g; 	glyph->x0 = (short)gx; 	glyph->y0 = (short)gy;@@ -1100,15 +1127,14 @@ 	glyph->xadv = (short)(scale * advance * 10.0f); 	glyph->xoff = (short)(x0 - pad); 	glyph->yoff = (short)(y0 - pad);-	glyph->next = 0; -	// Insert char to hash lookup.-	glyph->next = font->lut[h];-	font->lut[h] = font->nglyphs-1;+	if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL) {+		return glyph;+	}  	// Rasterize 	dst = &stash->texData[(glyph->x0+pad) + (glyph->y0+pad) * stash->params.width];-	fons__tt_renderGlyphBitmap(&renderFont->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale,scale, g);+	fons__tt_renderGlyphBitmap(&renderFont->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale, scale, g);  	// Make sure there is one pixel empty border. 	dst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width];@@ -1135,7 +1161,7 @@ 	if (iblur > 0) { 		stash->nscratch = 0; 		bdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width];-		fons__blur(stash, bdst, gw,gh, stash->params.width, iblur);+		fons__blur(stash, bdst, gw, gh, stash->params.width, iblur); 	}  	stash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], glyph->x0);@@ -1297,7 +1323,7 @@ 	for (; str != end; ++str) { 		if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) 			continue;-		glyph = fons__getGlyph(stash, font, codepoint, isize, iblur);+		glyph = fons__getGlyph(stash, font, codepoint, isize, iblur, FONS_GLYPH_BITMAP_REQUIRED); 		if (glyph != NULL) { 			fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); @@ -1320,7 +1346,7 @@ }  int fonsTextIterInit(FONScontext* stash, FONStextIter* iter,-					 float x, float y, const char* str, const char* end)+					 float x, float y, const char* str, const char* end, int bitmapOption) { 	FONSstate* state = fons__getState(stash); 	float width;@@ -1360,6 +1386,7 @@ 	iter->end = end; 	iter->codepoint = 0; 	iter->prevGlyphIndex = -1;+	iter->bitmapOption = bitmapOption;  	return 1; }@@ -1380,7 +1407,8 @@ 		// Get glyph and quad 		iter->x = iter->nextx; 		iter->y = iter->nexty;-		glyph = fons__getGlyph(stash, iter->font, iter->codepoint, iter->isize, iter->iblur);+		glyph = fons__getGlyph(stash, iter->font, iter->codepoint, iter->isize, iter->iblur, iter->bitmapOption);+		// If the iterator was initialized with FONS_GLYPH_BITMAP_OPTIONAL, then the UV coordinates of the quad will be invalid. 		if (glyph != NULL) 			fons__getQuad(stash, iter->font, iter->prevGlyphIndex, glyph, iter->scale, iter->spacing, &iter->nextx, &iter->nexty, quad); 		iter->prevGlyphIndex = glyph != NULL ? glyph->index : -1;@@ -1477,7 +1505,7 @@ 	for (; str != end; ++str) { 		if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) 			continue;-		glyph = fons__getGlyph(stash, font, codepoint, isize, iblur);+		glyph = fons__getGlyph(stash, font, codepoint, isize, iblur, FONS_GLYPH_BITMAP_OPTIONAL); 		if (glyph != NULL) { 			fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); 			if (q.x0 < minx) minx = q.x0;
nanovg/src/nanovg.c view
@@ -67,6 +67,7 @@  struct NVGstate { 	NVGcompositeOperationState compositeOperation;+	int shapeAntiAlias; 	NVGpaint fill; 	NVGpaint stroke; 	float strokeWidth;@@ -389,8 +390,7 @@  void nvgEndFrame(NVGcontext* ctx) {-	NVGstate* state = nvg__getState(ctx);-	ctx->params.renderFlush(ctx->params.userPtr, state->compositeOperation);+	ctx->params.renderFlush(ctx->params.userPtr); 	if (ctx->fontImageIdx != 0) { 		int fontImage = ctx->fontImages[ctx->fontImageIdx]; 		int i, j, iw, ih;@@ -646,6 +646,7 @@ 	nvg__setPaintColor(&state->fill, nvgRGBA(255,255,255,255)); 	nvg__setPaintColor(&state->stroke, nvgRGBA(0,0,0,255)); 	state->compositeOperation = nvg__compositeOperationState(NVG_SOURCE_OVER);+	state->shapeAntiAlias = 1; 	state->strokeWidth = 1.0f; 	state->miterLimit = 10.0f; 	state->lineCap = NVG_BUTT;@@ -665,6 +666,12 @@ }  // State setting+void nvgShapeAntiAlias(NVGcontext* ctx, int enabled)+{+	NVGstate* state = nvg__getState(ctx);+	state->shapeAntiAlias = enabled;+}+ void nvgStrokeWidth(NVGcontext* ctx, float width) { 	NVGstate* state = nvg__getState(ctx);@@ -2203,7 +2210,7 @@ 	int i;  	nvg__flattenPaths(ctx);-	if (ctx->params.edgeAntiAlias)+	if (ctx->params.edgeAntiAlias && state->shapeAntiAlias) 		nvg__expandFill(ctx, ctx->fringeWidth, NVG_MITER, 2.4f); 	else 		nvg__expandFill(ctx, 0.0f, NVG_MITER, 2.4f);@@ -2212,7 +2219,7 @@ 	fillPaint.innerColor.a *= state->alpha; 	fillPaint.outerColor.a *= state->alpha; -	ctx->params.renderFill(ctx->params.userPtr, &fillPaint, &state->scissor, ctx->fringeWidth,+	ctx->params.renderFill(ctx->params.userPtr, &fillPaint, state->compositeOperation, &state->scissor, ctx->fringeWidth, 						   ctx->cache->bounds, ctx->cache->paths, ctx->cache->npaths);  	// Count triangles@@ -2248,12 +2255,12 @@  	nvg__flattenPaths(ctx); -	if (ctx->params.edgeAntiAlias)+	if (ctx->params.edgeAntiAlias && state->shapeAntiAlias) 		nvg__expandStroke(ctx, strokeWidth*0.5f + ctx->fringeWidth*0.5f, state->lineCap, state->lineJoin, state->miterLimit); 	else 		nvg__expandStroke(ctx, strokeWidth*0.5f, state->lineCap, state->lineJoin, state->miterLimit); -	ctx->params.renderStroke(ctx->params.userPtr, &strokePaint, &state->scissor, ctx->fringeWidth,+	ctx->params.renderStroke(ctx->params.userPtr, &strokePaint, state->compositeOperation, &state->scissor, ctx->fringeWidth, 							 strokeWidth, ctx->cache->paths, ctx->cache->npaths);  	// Count triangles@@ -2401,7 +2408,7 @@ 	paint.innerColor.a *= state->alpha; 	paint.outerColor.a *= state->alpha; -	ctx->params.renderTriangles(ctx->params.userPtr, &paint, &state->scissor, verts, nverts);+	ctx->params.renderTriangles(ctx->params.userPtr, &paint, state->compositeOperation, &state->scissor, verts, nverts);  	ctx->drawCallCount++; 	ctx->textTriCount += nverts/3;@@ -2433,7 +2440,7 @@ 	verts = nvg__allocTempVerts(ctx, cverts); 	if (verts == NULL) return x; -	fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end);+	fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_REQUIRED); 	prevIter = iter; 	while (fonsTextIterNext(ctx->fs, &iter, &q)) { 		float c[4*2];@@ -2471,7 +2478,7 @@  	nvg__renderText(ctx, verts, nverts); -	return iter.x;+	return iter.nextx / scale; }  void nvgTextBox(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end)@@ -2530,7 +2537,7 @@ 	fonsSetAlign(ctx->fs, state->textAlign); 	fonsSetFont(ctx->fs, state->fontId); -	fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end);+	fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_OPTIONAL); 	prevIter = iter; 	while (fonsTextIterNext(ctx->fs, &iter, &q)) { 		if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph?@@ -2596,7 +2603,7 @@  	breakRowWidth *= scale; -	fonsTextIterInit(ctx->fs, &iter, 0, 0, string, end);+	fonsTextIterInit(ctx->fs, &iter, 0, 0, string, end, FONS_GLYPH_BITMAP_OPTIONAL); 	prevIter = iter; 	while (fonsTextIterNext(ctx->fs, &iter, &q)) { 		if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph?
nanovg/src/nanovg.h view
@@ -141,6 +141,7 @@ 	NVG_IMAGE_REPEATY			= 1<<2,		// Repeat image in Y direction. 	NVG_IMAGE_FLIPY				= 1<<3,		// Flips (inverses) image in Y direction when rendered. 	NVG_IMAGE_PREMULTIPLIED		= 1<<4,		// Image data has premultiplied alpha.+	NVG_IMAGE_NEAREST			= 1<<5,		// Image interpolation is Nearest instead Linear };  // Begin drawing a new frame@@ -237,6 +238,9 @@ // // Current render style can be saved and restored using nvgSave() and nvgRestore(). +// Sets whether to draw antialias for nvgStroke() and nvgFill(). It's enabled by default.+void nvgShapeAntiAlias(NVGcontext* ctx, int enabled);+ // Sets current stroke style to a solid color. void nvgStrokeColor(NVGcontext* ctx, NVGcolor color); @@ -651,10 +655,10 @@ 	int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h); 	void (*renderViewport)(void* uptr, int width, int height, float devicePixelRatio); 	void (*renderCancel)(void* uptr);-	void (*renderFlush)(void* uptr, NVGcompositeOperationState compositeOperation);-	void (*renderFill)(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);-	void (*renderStroke)(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);-	void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGscissor* scissor, const NVGvertex* verts, int nverts);+	void (*renderFlush)(void* uptr);+	void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);+	void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);+	void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts); 	void (*renderDelete)(void* uptr); }; typedef struct NVGparams NVGparams;
nanovg/src/nanovg_gl.h view
@@ -150,6 +150,15 @@ }; typedef struct GLNVGtexture GLNVGtexture; +struct GLNVGblend+{+	GLenum srcRGB;+	GLenum dstRGB;+	GLenum srcAlpha;+	GLenum dstAlpha;+};+typedef struct GLNVGblend GLNVGblend;+ enum GLNVGcallType { 	GLNVG_NONE = 0, 	GLNVG_FILL,@@ -166,6 +175,7 @@ 	int triangleOffset; 	int triangleCount; 	int uniformOffset;+	GLNVGblend blendFunc; }; typedef struct GLNVGcall GLNVGcall; @@ -256,6 +266,7 @@ 	GLenum stencilFunc; 	GLint stencilFuncRef; 	GLuint stencilFuncMask;+	GLNVGblend blendFunc; 	#endif }; typedef struct GLNVGcontext GLNVGcontext;@@ -316,7 +327,22 @@ 	glStencilFunc(func, ref, mask); #endif }+static void glnvg__blendFuncSeparate(GLNVGcontext* gl, const GLNVGblend* blend)+{+#if NANOVG_GL_USE_STATE_FILTER+	if ((gl->blendFunc.srcRGB != blend->srcRGB) ||+		(gl->blendFunc.dstRGB != blend->dstRGB) ||+		(gl->blendFunc.srcAlpha != blend->srcAlpha) ||+		(gl->blendFunc.dstAlpha != blend->dstAlpha)) { +		gl->blendFunc = *blend;+		glBlendFuncSeparate(blend->srcRGB, blend->dstRGB, blend->srcAlpha,blend->dstAlpha);+	}+#else+	glBlendFuncSeparate(blend->srcRGB, blend->dstRGB, blend->srcAlpha,blend->dstAlpha);+#endif+}+ static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl) { 	GLNVGtexture* tex = NULL;@@ -600,6 +626,7 @@ 		"	float scissor = scissorMask(fpos);\n" 		"#ifdef EDGE_AA\n" 		"	float strokeAlpha = strokeMask();\n"+		"	if (strokeAlpha < strokeThr) discard;\n" 		"#else\n" 		"	float strokeAlpha = 1.0;\n" 		"#endif\n"@@ -639,9 +666,6 @@ 		"		color *= scissor;\n" 		"		result = color * innerCol;\n" 		"	}\n"-		"#ifdef EDGE_AA\n"-		"	if (strokeAlpha < strokeThr) discard;\n"-		"#endif\n" 		"#ifdef NANOVG_GL3\n" 		"	outColor = result;\n" 		"#else\n"@@ -739,12 +763,25 @@ #endif  	if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) {-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);+		if (imageFlags & NVG_IMAGE_NEAREST) {+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);+		} else {+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);+		} 	} else {-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);+		if (imageFlags & NVG_IMAGE_NEAREST) {+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);+		} else {+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);+		} 	}-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +	if (imageFlags & NVG_IMAGE_NEAREST) {+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);+	} else {+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);+	}+ 	if (imageFlags & NVG_IMAGE_REPEATX) 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 	else@@ -908,10 +945,17 @@ 		} 		frag->type = NSVG_SHADER_FILLIMG; +		#if NANOVG_GL_USE_UNIFORMBUFFER 		if (tex->type == NVG_TEXTURE_RGBA) 			frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1; 		else 			frag->texType = 2;+		#else+		if (tex->type == NVG_TEXTURE_RGBA)+			frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0.0f : 1.0f;+		else+			frag->texType = 2.0f;+		#endif //		printf("frag->texType = %d\n", frag->texType); 	} else { 		frag->type = NSVG_SHADER_FILLGRAD;@@ -947,6 +991,7 @@  static void glnvg__renderViewport(void* uptr, int width, int height, float devicePixelRatio) {+	NVG_NOTUSED(devicePixelRatio); 	GLNVGcontext* gl = (GLNVGcontext*)uptr; 	gl->view[0] = (float)width; 	gl->view[1] = (float)height;@@ -991,7 +1036,7 @@ 	// Draw fill 	glnvg__stencilFunc(gl, GL_NOTEQUAL, 0x0, 0xff); 	glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);-	glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount);+	glDrawArrays(GL_TRIANGLE_STRIP, call->triangleOffset, call->triangleCount);  	glDisable(GL_STENCIL_TEST); }@@ -1103,19 +1148,24 @@ 	return GL_INVALID_ENUM; } -static void glnvg__blendCompositeOperation(NVGcompositeOperationState op)+static GLNVGblend glnvg__blendCompositeOperation(NVGcompositeOperationState op) {-	GLenum srcRGB = glnvg_convertBlendFuncFactor(op.srcRGB);-	GLenum dstRGB = glnvg_convertBlendFuncFactor(op.dstRGB);-	GLenum srcAlpha = glnvg_convertBlendFuncFactor(op.srcAlpha);-	GLenum dstAlpha = glnvg_convertBlendFuncFactor(op.dstAlpha);-	if (srcRGB == GL_INVALID_ENUM || dstRGB == GL_INVALID_ENUM || srcAlpha == GL_INVALID_ENUM || dstAlpha == GL_INVALID_ENUM)-		glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);-	else-		glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);+	GLNVGblend blend;+	blend.srcRGB = glnvg_convertBlendFuncFactor(op.srcRGB);+	blend.dstRGB = glnvg_convertBlendFuncFactor(op.dstRGB);+	blend.srcAlpha = glnvg_convertBlendFuncFactor(op.srcAlpha);+	blend.dstAlpha = glnvg_convertBlendFuncFactor(op.dstAlpha);+	if (blend.srcRGB == GL_INVALID_ENUM || blend.dstRGB == GL_INVALID_ENUM || blend.srcAlpha == GL_INVALID_ENUM || blend.dstAlpha == GL_INVALID_ENUM)+	{+		blend.srcRGB = GL_ONE;+		blend.dstRGB = GL_ONE_MINUS_SRC_ALPHA;+		blend.srcAlpha = GL_ONE;+		blend.dstAlpha = GL_ONE_MINUS_SRC_ALPHA;+	}+	return blend; } -static void glnvg__renderFlush(void* uptr, NVGcompositeOperationState compositeOperation)+static void glnvg__renderFlush(void* uptr) { 	GLNVGcontext* gl = (GLNVGcontext*)uptr; 	int i;@@ -1125,7 +1175,6 @@ 		// Setup require GL state. 		glUseProgram(gl->shader.prog); -		glnvg__blendCompositeOperation(compositeOperation); 		glEnable(GL_CULL_FACE); 		glCullFace(GL_BACK); 		glFrontFace(GL_CCW);@@ -1144,6 +1193,10 @@ 		gl->stencilFunc = GL_ALWAYS; 		gl->stencilFuncRef = 0; 		gl->stencilFuncMask = 0xffffffff;+		gl->blendFunc.srcRGB = GL_INVALID_ENUM;+		gl->blendFunc.srcAlpha = GL_INVALID_ENUM;+		gl->blendFunc.dstRGB = GL_INVALID_ENUM;+		gl->blendFunc.dstAlpha = GL_INVALID_ENUM; 		#endif  #if NANOVG_GL_USE_UNIFORMBUFFER@@ -1173,6 +1226,7 @@  		for (i = 0; i < gl->ncalls; i++) { 			GLNVGcall* call = &gl->calls[i];+			glnvg__blendFuncSeparate(gl,&call->blendFunc); 			if (call->type == GLNVG_FILL) 				glnvg__fill(gl, call); 			else if (call->type == GLNVG_CONVEXFILL)@@ -1288,7 +1342,7 @@ 	vtx->v = v; } -static void glnvg__renderFill(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe,+static void glnvg__renderFill(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, 							  const float* bounds, const NVGpath* paths, int npaths) { 	GLNVGcontext* gl = (GLNVGcontext*)uptr;@@ -1300,16 +1354,21 @@ 	if (call == NULL) return;  	call->type = GLNVG_FILL;+	call->triangleCount = 4; 	call->pathOffset = glnvg__allocPaths(gl, npaths); 	if (call->pathOffset == -1) goto error; 	call->pathCount = npaths; 	call->image = paint->image;+	call->blendFunc = glnvg__blendCompositeOperation(compositeOperation);  	if (npaths == 1 && paths[0].convex)+	{ 		call->type = GLNVG_CONVEXFILL;+		call->triangleCount = 0;	// Bounding box fill quad not needed for convex fill+	}  	// Allocate vertices for all the paths.-	maxverts = glnvg__maxVertCount(paths, npaths) + 6;+	maxverts = glnvg__maxVertCount(paths, npaths) + call->triangleCount; 	offset = glnvg__allocVerts(gl, maxverts); 	if (offset == -1) goto error; @@ -1331,20 +1390,16 @@ 		} 	} -	// Quad-	call->triangleOffset = offset;-	call->triangleCount = 6;-	quad = &gl->verts[call->triangleOffset];-	glnvg__vset(&quad[0], bounds[0], bounds[3], 0.5f, 1.0f);-	glnvg__vset(&quad[1], bounds[2], bounds[3], 0.5f, 1.0f);-	glnvg__vset(&quad[2], bounds[2], bounds[1], 0.5f, 1.0f);--	glnvg__vset(&quad[3], bounds[0], bounds[3], 0.5f, 1.0f);-	glnvg__vset(&quad[4], bounds[2], bounds[1], 0.5f, 1.0f);-	glnvg__vset(&quad[5], bounds[0], bounds[1], 0.5f, 1.0f);- 	// Setup uniforms for draw calls 	if (call->type == GLNVG_FILL) {+		// Quad+		call->triangleOffset = offset;+		quad = &gl->verts[call->triangleOffset];+		glnvg__vset(&quad[0], bounds[2], bounds[3], 0.5f, 1.0f);+		glnvg__vset(&quad[1], bounds[2], bounds[1], 0.5f, 1.0f);+		glnvg__vset(&quad[2], bounds[0], bounds[3], 0.5f, 1.0f);+		glnvg__vset(&quad[3], bounds[0], bounds[1], 0.5f, 1.0f);+ 		call->uniformOffset = glnvg__allocFragUniforms(gl, 2); 		if (call->uniformOffset == -1) goto error; 		// Simple shader for stencil@@ -1369,7 +1424,7 @@ 	if (gl->ncalls > 0) gl->ncalls--; } -static void glnvg__renderStroke(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe,+static void glnvg__renderStroke(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, 								float strokeWidth, const NVGpath* paths, int npaths) { 	GLNVGcontext* gl = (GLNVGcontext*)uptr;@@ -1383,6 +1438,7 @@ 	if (call->pathOffset == -1) goto error; 	call->pathCount = npaths; 	call->image = paint->image;+	call->blendFunc = glnvg__blendCompositeOperation(compositeOperation);  	// Allocate vertices for all the paths. 	maxverts = glnvg__maxVertCount(paths, npaths);@@ -1424,7 +1480,7 @@ 	if (gl->ncalls > 0) gl->ncalls--; } -static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGscissor* scissor,+static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, 								   const NVGvertex* verts, int nverts) { 	GLNVGcontext* gl = (GLNVGcontext*)uptr;@@ -1435,6 +1491,7 @@  	call->type = GLNVG_TRIANGLES; 	call->image = paint->image;+	call->blendFunc = glnvg__blendCompositeOperation(compositeOperation);  	// Allocate vertices for all the paths. 	call->triangleOffset = glnvg__allocVerts(gl, nverts);
src/NanoVG.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} module NanoVG   ( FileName(..)   , Context(..)@@ -116,10 +117,22 @@   , textBreakLines   -- * GL   , CreateFlags(..)+#if defined(GLES_3)+  , createGLES3+  , deleteGLES3+  , createImageFromHandleGLES3+  , imageHandleGLES3+#elif defined(GL_2)+  , createGL2+  , deleteGL2+  , createImageFromHandleGL2+  , imageHandleGL2+#else   , createGL3   , deleteGL3   , createImageFromHandleGL3   , imageHandleGL3+#endif   -- * Vector types   , V2(..)   , V3(..)@@ -137,7 +150,14 @@ import           Foreign.Ptr import           Foreign.Storable import           NanoVG.Internal+import           NanoVG.Internal.CreateContext+#if defined(GLES_3)+import           NanoVG.Internal.GLES3+#elif defined(GL_2)+import           NanoVG.Internal.GL2+#else import           NanoVG.Internal.GL3+#endif import qualified NanoVG.Internal.Text as Internal import           NanoVG.Internal.Text hiding (textBreakLines,textGlyphPositions,text) 
src/NanoVG/Internal/Context.hs view
@@ -1,8 +1,18 @@ module NanoVG.Internal.Context   (Context(..)+  , toPointer+  , fromPointer   ) where  import Foreign.Ptr  -- | Opaque context that needs to be passed around newtype Context = Context (Ptr Context)++-- | In marshaller for c2hs+toPointer :: Context -> Ptr ()+toPointer (Context p) = castPtr p++-- | out marshaller for c2hs+fromPointer :: Ptr () -> Context+fromPointer p = Context (castPtr p)
+ src/NanoVG/Internal/CreateContext.chs view
@@ -0,0 +1,21 @@+module NanoVG.Internal.CreateContext where++import Foreign.C.Types+import Data.Word (Word32(..))++#include "nanovg.h"+#include "nanovg_gl.h"++{#pointer *NVGcontext as Context newtype nocode#}++{#enum NVGcreateFlags as CreateFlags+         {underscoreToCase} with prefix = "NVG_"+         deriving (Show,Read,Eq,Ord)#}++type GLuint = Word32++toCInt :: CreateFlags -> CInt+toCInt = fromIntegral . fromEnum++fromCInt :: CInt -> CreateFlags+fromCInt = toEnum . fromIntegral
+ src/NanoVG/Internal/GL2.chs view
@@ -0,0 +1,40 @@+module NanoVG.Internal.GL2 where++import qualified Data.Set as S+import           Data.Word+import           Foreign.C.Types++import           NanoVG.Internal.CreateContext+import           NanoVG.Internal.Types+import           NanoVG.Internal.Context+import           NanoVG.Internal.FFIHelpers++-- For now only the GL2 backends are supported+#define NANOVG_GL2++-- We need to include this to define GLuint+#if defined(darwin_HOST_OS)+#include <OpenGL/gl.h>+#else+#include "GL/glew.h"+#endif+#include "nanovg.h"+#include "nanovg_gl.h"++{#fun unsafe nvgCreateGL2 as createGL2+        {bitMask`S.Set CreateFlags'} -> `Context' fromPointer#}+{#fun unsafe nvgDeleteGL2 as deleteGL2+        { toPointer `Context' fromPointer} -> `()'#}++{#fun unsafe nvglCreateImageFromHandleGL2 as createImageFromHandleGL2+        { toPointer `Context' fromPointer+        , fromIntegral`GLuint'+        , `CInt'+        , `CInt'+        , toCInt `CreateFlags' fromCInt+        } -> `Image'Image#}++{#fun unsafe nvglImageHandleGL2 as imageHandleGL2+        { toPointer `Context' fromPointer+        , imageHandle`Image'+        } -> `GLuint'fromIntegral#}
src/NanoVG/Internal/GL3.chs view
@@ -4,12 +4,14 @@ import           Data.Word import           Foreign.C.Types +import           NanoVG.Internal.CreateContext import           NanoVG.Internal.Types import           NanoVG.Internal.Context import           NanoVG.Internal.FFIHelpers --- For now only the GL3 backend is supported+-- For now only the GL3 and the GLES3 backends are supported #define NANOVG_GL3+ -- We need to include this to define GLuint #if defined(darwin_HOST_OS) #include <OpenGL/gl3.h>@@ -19,21 +21,20 @@ #include "nanovg.h" #include "nanovg_gl.h" -{#pointer *NVGcontext as Context newtype nocode#}--{#enum NVGcreateFlags as CreateFlags-         {underscoreToCase} with prefix = "NVG_"-         deriving (Show,Read,Eq,Ord)#}- {#fun unsafe nvgCreateGL3 as createGL3-        {bitMask`S.Set CreateFlags'} -> `Context'#}+        {bitMask`S.Set CreateFlags'} -> `Context' fromPointer#} {#fun unsafe nvgDeleteGL3 as deleteGL3-        {`Context'} -> `()'#}--type GLuint = Word32+        { toPointer `Context' fromPointer} -> `()'#}  {#fun unsafe nvglCreateImageFromHandleGL3 as createImageFromHandleGL3-        {`Context',fromIntegral`GLuint',`CInt',`CInt',`CreateFlags'} -> `Image'Image#}+        { toPointer `Context' fromPointer+        , fromIntegral`GLuint'+        , `CInt'+        , `CInt'+        , toCInt `CreateFlags' fromCInt+        } -> `Image'Image#}  {#fun unsafe nvglImageHandleGL3 as imageHandleGL3-        {`Context',imageHandle`Image'} -> `GLuint'fromIntegral#}+        { toPointer `Context' fromPointer+        , imageHandle`Image'+        } -> `GLuint'fromIntegral#}
+ src/NanoVG/Internal/GLES3.chs view
@@ -0,0 +1,39 @@+module NanoVG.Internal.GLES3 where++import qualified Data.Set as S+import           Data.Word+import           Foreign.C.Types++import           NanoVG.Internal.CreateContext+import           NanoVG.Internal.Types+import           NanoVG.Internal.Context+import           NanoVG.Internal.FFIHelpers++-- For now only the GL3 and GLES3 backends are supported+#define NANOVG_GLES3+-- We need to include this to define GLuint+#if defined(darwin_HOST_OS)+#include <OpenGL/gl3.h>+#else+#include "GL/glew.h"+#endif+#include "nanovg.h"+#include "nanovg_gl.h"++{#fun unsafe nvgCreateGLES3 as createGLES3+        {bitMask`S.Set CreateFlags'} -> `Context' fromPointer#}+{#fun unsafe nvgDeleteGLES3 as deleteGLES3+        {toPointer `Context' fromPointer} -> `()'#}++{#fun unsafe nvglCreateImageFromHandleGLES3 as createImageFromHandleGLES3+        { toPointer `Context' fromPointer+        , fromIntegral`GLuint'+        , `CInt'+        , `CInt'+        , toCInt `CreateFlags' fromCInt+        } -> `Image'Image#}++{#fun unsafe nvglImageHandleGLES3 as imageHandleGLES3+        { toPointer `Context' fromPointer+        , imageHandle`Image'+        } -> `GLuint'fromIntegral#}