mirror of https://github.com/adamdruppe/arsd.git
NanoVega: fixed kerning bug in stb_ttf backend; implemented glyph outline retrieval for stb.ttf; experimental API to get tesselated paths
This commit is contained in:
parent
848130ea98
commit
c0db16a13d
382
nanovega.d
382
nanovega.d
|
@ -531,6 +531,8 @@ import core.stdc.stdlib : malloc, realloc, free;
|
||||||
import core.stdc.string : memset, memcpy, strlen;
|
import core.stdc.string : memset, memcpy, strlen;
|
||||||
import std.math : PI;
|
import std.math : PI;
|
||||||
|
|
||||||
|
//version = nanovg_force_stb_ttf;
|
||||||
|
|
||||||
version(Posix) {
|
version(Posix) {
|
||||||
version = nanovg_use_freetype;
|
version = nanovg_use_freetype;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1307,7 +1309,8 @@ struct NVGscissor {
|
||||||
float[2] extent = -1.0f;
|
float[2] extent = -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NVGvertex {
|
/// General NanoVega vertex struct. Contains geometry coordinates, and (sometimes unused) texture coordinates.
|
||||||
|
public struct NVGVertex {
|
||||||
float x, y, u, v;
|
float x, y, u, v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1316,12 +1319,12 @@ struct NVGpath {
|
||||||
int count;
|
int count;
|
||||||
bool closed;
|
bool closed;
|
||||||
int nbevel;
|
int nbevel;
|
||||||
NVGvertex* fill;
|
NVGVertex* fill;
|
||||||
int nfill;
|
int nfill;
|
||||||
NVGvertex* stroke;
|
NVGVertex* stroke;
|
||||||
int nstroke;
|
int nstroke;
|
||||||
NVGWinding winding;
|
NVGWinding mWinding;
|
||||||
int convex;
|
bool convex;
|
||||||
bool cloned;
|
bool cloned;
|
||||||
|
|
||||||
@disable this (this); // no copies
|
@disable this (this); // no copies
|
||||||
|
@ -1348,6 +1351,19 @@ struct NVGpath {
|
||||||
}
|
}
|
||||||
this.cloned = true;
|
this.cloned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @property const(NVGVertex)[] fillVertices () const pure nothrow @trusted @nogc {
|
||||||
|
pragma(inline, true);
|
||||||
|
return (nfill > 0 ? fill[0..nfill] : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @property const(NVGVertex)[] strokeVertices () const pure nothrow @trusted @nogc {
|
||||||
|
pragma(inline, true);
|
||||||
|
return (nstroke > 0 ? stroke[0..nstroke] : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @property NVGWinding winding () const pure nothrow @trusted @nogc { pragma(inline, true); return mWinding; }
|
||||||
|
public @property bool complex () const pure nothrow @trusted @nogc { pragma(inline, true); return !convex; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1369,7 +1385,7 @@ struct NVGparams {
|
||||||
void function (void* uptr) nothrow @trusted @nogc renderResetClip; // reset current clip region to `non-clipped`
|
void function (void* uptr) nothrow @trusted @nogc renderResetClip; // reset current clip region to `non-clipped`
|
||||||
void function (void* uptr, NVGCompositeOperationState compositeOperation, NVGClipMode clipmode, NVGPaint* paint, NVGscissor* scissor, float fringe, const(float)* bounds, const(NVGpath)* paths, int npaths, bool evenOdd) nothrow @trusted @nogc renderFill;
|
void function (void* uptr, NVGCompositeOperationState compositeOperation, NVGClipMode clipmode, NVGPaint* paint, NVGscissor* scissor, float fringe, const(float)* bounds, const(NVGpath)* paths, int npaths, bool evenOdd) nothrow @trusted @nogc renderFill;
|
||||||
void function (void* uptr, NVGCompositeOperationState compositeOperation, NVGClipMode clipmode, NVGPaint* paint, NVGscissor* scissor, float fringe, float strokeWidth, const(NVGpath)* paths, int npaths) nothrow @trusted @nogc renderStroke;
|
void function (void* uptr, NVGCompositeOperationState compositeOperation, NVGClipMode clipmode, NVGPaint* paint, NVGscissor* scissor, float fringe, float strokeWidth, const(NVGpath)* paths, int npaths) nothrow @trusted @nogc renderStroke;
|
||||||
void function (void* uptr, NVGCompositeOperationState compositeOperation, NVGClipMode clipmode, NVGPaint* paint, NVGscissor* scissor, const(NVGvertex)* verts, int nverts) nothrow @trusted @nogc renderTriangles;
|
void function (void* uptr, NVGCompositeOperationState compositeOperation, NVGClipMode clipmode, NVGPaint* paint, NVGscissor* scissor, const(NVGVertex)* verts, int nverts) nothrow @trusted @nogc renderTriangles;
|
||||||
void function (void* uptr, in ref NVGMatrix mat) nothrow @trusted @nogc renderSetAffine;
|
void function (void* uptr, in ref NVGMatrix mat) nothrow @trusted @nogc renderSetAffine;
|
||||||
void function (void* uptr) nothrow @trusted @nogc renderDelete;
|
void function (void* uptr) nothrow @trusted @nogc renderDelete;
|
||||||
}
|
}
|
||||||
|
@ -1446,7 +1462,7 @@ struct NVGpathCache {
|
||||||
NVGpath* paths;
|
NVGpath* paths;
|
||||||
int npaths;
|
int npaths;
|
||||||
int cpaths;
|
int cpaths;
|
||||||
NVGvertex* verts;
|
NVGVertex* verts;
|
||||||
int nverts;
|
int nverts;
|
||||||
int cverts;
|
int cverts;
|
||||||
float[4] bounds;
|
float[4] bounds;
|
||||||
|
@ -1479,6 +1495,7 @@ struct NVGpathCache {
|
||||||
this.paths = cast(NVGpath*)malloc(src.npaths*NVGpath.sizeof);
|
this.paths = cast(NVGpath*)malloc(src.npaths*NVGpath.sizeof);
|
||||||
memset(this.paths, 0, npaths*NVGpath.sizeof);
|
memset(this.paths, 0, npaths*NVGpath.sizeof);
|
||||||
foreach (immutable pidx; 0..npaths) this.paths[pidx].copyFrom(&src.paths[pidx]);
|
foreach (immutable pidx; 0..npaths) this.paths[pidx].copyFrom(&src.paths[pidx]);
|
||||||
|
this.cpaths = src.npaths;
|
||||||
} else {
|
} else {
|
||||||
this.npaths = this.cpaths = 0;
|
this.npaths = this.cpaths = 0;
|
||||||
}
|
}
|
||||||
|
@ -1615,6 +1632,59 @@ private:
|
||||||
@disable this (this); // no copies
|
@disable this (this); // no copies
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns number of tesselated pathes in context.
|
||||||
|
*
|
||||||
|
* Tesselated pathes are either triangle strips (for strokes), or
|
||||||
|
* triangle fans (for fills). Note that NanoVega can generate some
|
||||||
|
* surprising pathes (like fringe stroke for antialiasing, for example).
|
||||||
|
*
|
||||||
|
* One render path can contain vertices both for fill, and for stroke triangles.
|
||||||
|
*/
|
||||||
|
public int renderPathCount (NVGContext ctx) pure nothrow @trusted @nogc {
|
||||||
|
pragma(inline, true);
|
||||||
|
return (ctx !is null && ctx.contextAlive ? ctx.cache.npaths : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get vertices of "fill" triangle fan for the given render path. Can return empty slice.
|
||||||
|
*
|
||||||
|
* $(WARNING Returned slice can be invalidated by any other NanoVega API call
|
||||||
|
* (except the calls to render path accessors), and using it in such
|
||||||
|
* case is UB. So copy vertices to freshly allocated array if you want
|
||||||
|
* to keep them for further processing.)
|
||||||
|
*/
|
||||||
|
public const(NVGVertex)[] renderPathFillVertices (NVGContext ctx, int pathidx) pure nothrow @trusted @nogc {
|
||||||
|
pragma(inline, true);
|
||||||
|
return (ctx !is null && ctx.contextAlive && pathidx >= 0 && pathidx < ctx.cache.npaths ? ctx.cache.paths[pathidx].fillVertices : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get vertices of "stroke" triangle strip for the given render path. Can return empty slice.
|
||||||
|
*
|
||||||
|
* $(WARNING Returned slice can be invalidated by any other NanoVega API call
|
||||||
|
* (except the calls to render path accessors), and using it in such
|
||||||
|
* case is UB. So copy vertices to freshly allocated array if you want
|
||||||
|
* to keep them for further processing.)
|
||||||
|
*/
|
||||||
|
public const(NVGVertex)[] renderPathStrokeVertices (NVGContext ctx, int pathidx) pure nothrow @trusted @nogc {
|
||||||
|
pragma(inline, true);
|
||||||
|
return (ctx !is null && ctx.contextAlive && pathidx >= 0 && pathidx < ctx.cache.npaths ? ctx.cache.paths[pathidx].strokeVertices : null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns winding for the given render path.
|
||||||
|
public NVGWinding renderPathWinding (NVGContext ctx, int pathidx) pure nothrow @trusted @nogc {
|
||||||
|
pragma(inline, true);
|
||||||
|
return (ctx !is null && ctx.contextAlive && pathidx >= 0 && pathidx < ctx.cache.npaths ? ctx.cache.paths[pathidx].winding : NVGWinding.CCW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns "complex path" flag for the given render path.
|
||||||
|
public bool renderPathComplex (NVGContext ctx, int pathidx) pure nothrow @trusted @nogc {
|
||||||
|
pragma(inline, true);
|
||||||
|
return (ctx !is null && ctx.contextAlive && pathidx >= 0 && pathidx < ctx.cache.npaths ? ctx.cache.paths[pathidx].complex : false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void nvg__imageIncRef (NVGContext ctx, int imgid) nothrow @trusted @nogc {
|
void nvg__imageIncRef (NVGContext ctx, int imgid) nothrow @trusted @nogc {
|
||||||
if (ctx !is null && imgid > 0) {
|
if (ctx !is null && imgid > 0) {
|
||||||
++ctx.imageCount;
|
++ctx.imageCount;
|
||||||
|
@ -1698,7 +1768,7 @@ NVGpathCache* nvg__allocPathCache () nothrow @trusted @nogc {
|
||||||
assert(c.npaths == 0);
|
assert(c.npaths == 0);
|
||||||
c.cpaths = NVG_INIT_PATHS_SIZE;
|
c.cpaths = NVG_INIT_PATHS_SIZE;
|
||||||
|
|
||||||
c.verts = cast(NVGvertex*)malloc(NVGvertex.sizeof*NVG_INIT_VERTS_SIZE);
|
c.verts = cast(NVGVertex*)malloc(NVGVertex.sizeof*NVG_INIT_VERTS_SIZE);
|
||||||
if (c.verts is null) goto error;
|
if (c.verts is null) goto error;
|
||||||
assert(c.nverts == 0);
|
assert(c.nverts == 0);
|
||||||
c.cverts = NVG_INIT_VERTS_SIZE;
|
c.cverts = NVG_INIT_VERTS_SIZE;
|
||||||
|
@ -1933,6 +2003,9 @@ public void cancelFrame (NVGContext ctx) nothrow @trusted @nogc {
|
||||||
ctx.mDeviceRatio = 0;
|
ctx.mDeviceRatio = 0;
|
||||||
// cancel render queue
|
// cancel render queue
|
||||||
ctx.params.renderCancel(ctx.params.userPtr);
|
ctx.params.renderCancel(ctx.params.userPtr);
|
||||||
|
// clear saved states (this may free some textures)
|
||||||
|
foreach (ref NVGstate st; ctx.states[0..ctx.nstates]) st.clearPaint();
|
||||||
|
ctx.nstates = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ends drawing the current frame (flushing remaining render state). Commits recorded paths.
|
/// Ends drawing the current frame (flushing remaining render state). Commits recorded paths.
|
||||||
|
@ -1970,6 +2043,9 @@ public void endFrame (NVGContext ctx) nothrow @trusted @nogc {
|
||||||
// clear all images after j
|
// clear all images after j
|
||||||
ctx.fontImages[j..NVG_MAX_FONTIMAGES] = NVGImage.init;
|
ctx.fontImages[j..NVG_MAX_FONTIMAGES] = NVGImage.init;
|
||||||
}
|
}
|
||||||
|
// clear saved states (this may free some textures)
|
||||||
|
foreach (ref NVGstate st; ctx.states[0..ctx.nstates]) st.clearPaint();
|
||||||
|
ctx.nstates = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2860,6 +2936,18 @@ public bool canSave (NVGContext ctx) pure nothrow @trusted @nogc { pragma(inline
|
||||||
*/
|
*/
|
||||||
public bool canRestore (NVGContext ctx) pure nothrow @trusted @nogc { pragma(inline, true); return (ctx.nstates > 1); }
|
public bool canRestore (NVGContext ctx) pure nothrow @trusted @nogc { pragma(inline, true); return (ctx.nstates > 1); }
|
||||||
|
|
||||||
|
/// Returns `true` if rendering is currently blocked.
|
||||||
|
/// Group: state_handling
|
||||||
|
public bool renderBlocked (NVGContext ctx) pure nothrow @trusted @nogc { pragma(inline, true); return (ctx !is null && ctx.contextAlive ? ctx.recblockdraw : false); }
|
||||||
|
|
||||||
|
/// Blocks/unblocks rendering
|
||||||
|
/// Group: state_handling
|
||||||
|
public void renderBlocked (NVGContext ctx, bool v) pure nothrow @trusted @nogc { pragma(inline, true); if (ctx !is null && ctx.contextAlive) ctx.recblockdraw = v; }
|
||||||
|
|
||||||
|
/// Blocks/unblocks rendering; returns previous state.
|
||||||
|
/// Group: state_handling
|
||||||
|
public bool setRenderBlocked (NVGContext ctx, bool v) pure nothrow @trusted @nogc { pragma(inline, true); if (ctx !is null && ctx.contextAlive) { bool res = ctx.recblockdraw; ctx.recblockdraw = v; return res; } else return false; }
|
||||||
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////// //
|
// ////////////////////////////////////////////////////////////////////////// //
|
||||||
// Render styles
|
// Render styles
|
||||||
|
@ -3849,7 +3937,7 @@ void nvg__addPath (NVGContext ctx) nothrow @trusted @nogc {
|
||||||
NVGpath* path = &ctx.cache.paths[ctx.cache.npaths++];
|
NVGpath* path = &ctx.cache.paths[ctx.cache.npaths++];
|
||||||
memset(path, 0, NVGpath.sizeof);
|
memset(path, 0, NVGpath.sizeof);
|
||||||
path.first = ctx.cache.npoints;
|
path.first = ctx.cache.npoints;
|
||||||
path.winding = NVGWinding.CCW;
|
path.mWinding = NVGWinding.CCW;
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGpoint* nvg__lastPoint (NVGContext ctx) nothrow @trusted @nogc {
|
NVGpoint* nvg__lastPoint (NVGContext ctx) nothrow @trusted @nogc {
|
||||||
|
@ -3895,7 +3983,7 @@ void nvg__closePath (NVGContext ctx) nothrow @trusted @nogc {
|
||||||
void nvg__pathWinding (NVGContext ctx, NVGWinding winding) nothrow @trusted @nogc {
|
void nvg__pathWinding (NVGContext ctx, NVGWinding winding) nothrow @trusted @nogc {
|
||||||
NVGpath* path = nvg__lastPath(ctx);
|
NVGpath* path = nvg__lastPath(ctx);
|
||||||
if (path is null) return;
|
if (path is null) return;
|
||||||
path.winding = winding;
|
path.mWinding = winding;
|
||||||
}
|
}
|
||||||
|
|
||||||
float nvg__getAverageScale() (in auto ref NVGMatrix t) nothrow @trusted @nogc {
|
float nvg__getAverageScale() (in auto ref NVGMatrix t) nothrow @trusted @nogc {
|
||||||
|
@ -3904,10 +3992,10 @@ float nvg__getAverageScale() (in auto ref NVGMatrix t) nothrow @trusted @nogc {
|
||||||
return (sx+sy)*0.5f;
|
return (sx+sy)*0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGvertex* nvg__allocTempVerts (NVGContext ctx, int nverts) nothrow @trusted @nogc {
|
NVGVertex* nvg__allocTempVerts (NVGContext ctx, int nverts) nothrow @trusted @nogc {
|
||||||
if (nverts > ctx.cache.cverts) {
|
if (nverts > ctx.cache.cverts) {
|
||||||
int cverts = (nverts+0xff)&~0xff; // Round up to prevent allocations when things change just slightly.
|
int cverts = (nverts+0xff)&~0xff; // Round up to prevent allocations when things change just slightly.
|
||||||
NVGvertex* verts = cast(NVGvertex*)realloc(ctx.cache.verts, NVGvertex.sizeof*cverts);
|
NVGVertex* verts = cast(NVGVertex*)realloc(ctx.cache.verts, NVGVertex.sizeof*cverts);
|
||||||
if (verts is null) return null;
|
if (verts is null) return null;
|
||||||
ctx.cache.verts = verts;
|
ctx.cache.verts = verts;
|
||||||
ctx.cache.cverts = cverts;
|
ctx.cache.cverts = cverts;
|
||||||
|
@ -3947,7 +4035,7 @@ void nvg__polyReverse (NVGpoint* pts, int npts) nothrow @trusted @nogc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvg__vset (NVGvertex* vtx, float x, float y, float u, float v) nothrow @trusted @nogc {
|
void nvg__vset (NVGVertex* vtx, float x, float y, float u, float v) nothrow @trusted @nogc {
|
||||||
vtx.x = x;
|
vtx.x = x;
|
||||||
vtx.y = y;
|
vtx.y = y;
|
||||||
vtx.u = u;
|
vtx.u = u;
|
||||||
|
@ -4365,8 +4453,8 @@ void nvg__flattenPaths (NVGContext ctx) nothrow @trusted @nogc {
|
||||||
// enforce winding
|
// enforce winding
|
||||||
if (path.count > 2) {
|
if (path.count > 2) {
|
||||||
immutable float area = nvg__polyArea(pts, path.count);
|
immutable float area = nvg__polyArea(pts, path.count);
|
||||||
if (path.winding == NVGWinding.CCW && area < 0.0f) nvg__polyReverse(pts, path.count);
|
if (path.mWinding == NVGWinding.CCW && area < 0.0f) nvg__polyReverse(pts, path.count);
|
||||||
if (path.winding == NVGWinding.CW && area > 0.0f) nvg__polyReverse(pts, path.count);
|
if (path.mWinding == NVGWinding.CW && area > 0.0f) nvg__polyReverse(pts, path.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (immutable _; 0..path.count) {
|
foreach (immutable _; 0..path.count) {
|
||||||
|
@ -4410,7 +4498,7 @@ void nvg__chooseBevel (int bevel, NVGpoint* p0, NVGpoint* p1, float w, float* x0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGvertex* nvg__roundJoin (NVGvertex* dst, NVGpoint* p0, NVGpoint* p1, float lw, float rw, float lu, float ru, int ncap, float fringe) nothrow @trusted @nogc {
|
NVGVertex* nvg__roundJoin (NVGVertex* dst, NVGpoint* p0, NVGpoint* p1, float lw, float rw, float lu, float ru, int ncap, float fringe) nothrow @trusted @nogc {
|
||||||
float dlx0 = p0.dy;
|
float dlx0 = p0.dy;
|
||||||
float dly0 = -p0.dx;
|
float dly0 = -p0.dx;
|
||||||
float dlx1 = p1.dy;
|
float dlx1 = p1.dy;
|
||||||
|
@ -4467,7 +4555,7 @@ NVGvertex* nvg__roundJoin (NVGvertex* dst, NVGpoint* p0, NVGpoint* p1, float lw,
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGvertex* nvg__bevelJoin (NVGvertex* dst, NVGpoint* p0, NVGpoint* p1, float lw, float rw, float lu, float ru, float fringe) nothrow @trusted @nogc {
|
NVGVertex* nvg__bevelJoin (NVGVertex* dst, NVGpoint* p0, NVGpoint* p1, float lw, float rw, float lu, float ru, float fringe) nothrow @trusted @nogc {
|
||||||
float rx0, ry0, rx1, ry1;
|
float rx0, ry0, rx1, ry1;
|
||||||
float lx0, ly0, lx1, ly1;
|
float lx0, ly0, lx1, ly1;
|
||||||
float dlx0 = p0.dy;
|
float dlx0 = p0.dy;
|
||||||
|
@ -4538,7 +4626,7 @@ NVGvertex* nvg__bevelJoin (NVGvertex* dst, NVGpoint* p0, NVGpoint* p1, float lw,
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGvertex* nvg__buttCapStart (NVGvertex* dst, NVGpoint* p, float dx, float dy, float w, float d, float aa) nothrow @trusted @nogc {
|
NVGVertex* nvg__buttCapStart (NVGVertex* dst, NVGpoint* p, float dx, float dy, float w, float d, float aa) nothrow @trusted @nogc {
|
||||||
immutable float px = p.x-dx*d;
|
immutable float px = p.x-dx*d;
|
||||||
immutable float py = p.y-dy*d;
|
immutable float py = p.y-dy*d;
|
||||||
immutable float dlx = dy;
|
immutable float dlx = dy;
|
||||||
|
@ -4550,7 +4638,7 @@ NVGvertex* nvg__buttCapStart (NVGvertex* dst, NVGpoint* p, float dx, float dy, f
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGvertex* nvg__buttCapEnd (NVGvertex* dst, NVGpoint* p, float dx, float dy, float w, float d, float aa) nothrow @trusted @nogc {
|
NVGVertex* nvg__buttCapEnd (NVGVertex* dst, NVGpoint* p, float dx, float dy, float w, float d, float aa) nothrow @trusted @nogc {
|
||||||
immutable float px = p.x+dx*d;
|
immutable float px = p.x+dx*d;
|
||||||
immutable float py = p.y+dy*d;
|
immutable float py = p.y+dy*d;
|
||||||
immutable float dlx = dy;
|
immutable float dlx = dy;
|
||||||
|
@ -4562,7 +4650,7 @@ NVGvertex* nvg__buttCapEnd (NVGvertex* dst, NVGpoint* p, float dx, float dy, flo
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGvertex* nvg__roundCapStart (NVGvertex* dst, NVGpoint* p, float dx, float dy, float w, int ncap, float aa) nothrow @trusted @nogc {
|
NVGVertex* nvg__roundCapStart (NVGVertex* dst, NVGpoint* p, float dx, float dy, float w, int ncap, float aa) nothrow @trusted @nogc {
|
||||||
immutable float px = p.x;
|
immutable float px = p.x;
|
||||||
immutable float py = p.y;
|
immutable float py = p.y;
|
||||||
immutable float dlx = dy;
|
immutable float dlx = dy;
|
||||||
|
@ -4580,7 +4668,7 @@ NVGvertex* nvg__roundCapStart (NVGvertex* dst, NVGpoint* p, float dx, float dy,
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGvertex* nvg__roundCapEnd (NVGvertex* dst, NVGpoint* p, float dx, float dy, float w, int ncap, float aa) nothrow @trusted @nogc {
|
NVGVertex* nvg__roundCapEnd (NVGVertex* dst, NVGpoint* p, float dx, float dy, float w, int ncap, float aa) nothrow @trusted @nogc {
|
||||||
immutable float px = p.x;
|
immutable float px = p.x;
|
||||||
immutable float py = p.y;
|
immutable float py = p.y;
|
||||||
immutable float dlx = dy;
|
immutable float dlx = dy;
|
||||||
|
@ -4657,7 +4745,7 @@ void nvg__calculateJoins (NVGContext ctx, float w, int lineJoin, float miterLimi
|
||||||
p0 = p1++;
|
p0 = p1++;
|
||||||
}
|
}
|
||||||
|
|
||||||
path.convex = (nleft == path.count) ? 1 : 0;
|
path.convex = (nleft == path.count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4688,7 +4776,7 @@ void nvg__expandStroke (NVGContext ctx, float w, int lineCap, int lineJoin, floa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGvertex* verts = nvg__allocTempVerts(ctx, cverts);
|
NVGVertex* verts = nvg__allocTempVerts(ctx, cverts);
|
||||||
if (verts is null) return;
|
if (verts is null) return;
|
||||||
|
|
||||||
foreach (int i; 0..cache.npaths) {
|
foreach (int i; 0..cache.npaths) {
|
||||||
|
@ -4703,7 +4791,7 @@ void nvg__expandStroke (NVGContext ctx, float w, int lineCap, int lineJoin, floa
|
||||||
|
|
||||||
// Calculate fringe or stroke
|
// Calculate fringe or stroke
|
||||||
immutable bool loop = path.closed;
|
immutable bool loop = path.closed;
|
||||||
NVGvertex* dst = verts;
|
NVGVertex* dst = verts;
|
||||||
path.stroke = dst;
|
path.stroke = dst;
|
||||||
|
|
||||||
if (loop) {
|
if (loop) {
|
||||||
|
@ -4779,7 +4867,7 @@ void nvg__expandFill (NVGContext ctx, float w, int lineJoin, float miterLimit) n
|
||||||
if (fringe) cverts += (path.count+path.nbevel*5+1)*2; // plus one for loop
|
if (fringe) cverts += (path.count+path.nbevel*5+1)*2; // plus one for loop
|
||||||
}
|
}
|
||||||
|
|
||||||
NVGvertex* verts = nvg__allocTempVerts(ctx, cverts);
|
NVGVertex* verts = nvg__allocTempVerts(ctx, cverts);
|
||||||
if (verts is null) return;
|
if (verts is null) return;
|
||||||
|
|
||||||
bool convex = (cache.npaths == 1 && cache.paths[0].convex);
|
bool convex = (cache.npaths == 1 && cache.paths[0].convex);
|
||||||
|
@ -4790,7 +4878,7 @@ void nvg__expandFill (NVGContext ctx, float w, int lineJoin, float miterLimit) n
|
||||||
|
|
||||||
// Calculate shape vertices.
|
// Calculate shape vertices.
|
||||||
immutable float woff = 0.5f*aa;
|
immutable float woff = 0.5f*aa;
|
||||||
NVGvertex* dst = verts;
|
NVGVertex* dst = verts;
|
||||||
path.fill = dst;
|
path.fill = dst;
|
||||||
|
|
||||||
if (fringe) {
|
if (fringe) {
|
||||||
|
@ -7523,9 +7611,9 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
float[4] bounds = 0;
|
float[4] bounds = 0; /// glyph outline bounds
|
||||||
|
|
||||||
@property int length () const pure { pragma(inline, true); return ccount; }
|
@property int length () const pure { pragma(inline, true); return ccount; } /// number of commands in outline
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Returns forward range with all glyph commands.
|
/// Returns forward range with all glyph commands.
|
||||||
|
@ -7674,7 +7762,7 @@ bool nvg__allocTextAtlas (NVGContext ctx) nothrow @trusted @nogc {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvg__renderText (NVGContext ctx, NVGvertex* verts, int nverts) nothrow @trusted @nogc {
|
void nvg__renderText (NVGContext ctx, NVGVertex* verts, int nverts) nothrow @trusted @nogc {
|
||||||
NVGstate* state = nvg__getState(ctx);
|
NVGstate* state = nvg__getState(ctx);
|
||||||
NVGPaint paint = state.fill;
|
NVGPaint paint = state.fill;
|
||||||
|
|
||||||
|
@ -7698,7 +7786,7 @@ public float text(T) (NVGContext ctx, float x, float y, const(T)[] str) nothrow
|
||||||
NVGstate* state = nvg__getState(ctx);
|
NVGstate* state = nvg__getState(ctx);
|
||||||
FONStextIter!T iter, prevIter;
|
FONStextIter!T iter, prevIter;
|
||||||
FONSquad q;
|
FONSquad q;
|
||||||
NVGvertex* verts;
|
NVGVertex* verts;
|
||||||
float scale = nvg__getFontScale(state)*ctx.devicePxRatio;
|
float scale = nvg__getFontScale(state)*ctx.devicePxRatio;
|
||||||
float invscale = 1.0f/scale;
|
float invscale = 1.0f/scale;
|
||||||
int cverts = 0;
|
int cverts = 0;
|
||||||
|
@ -8407,21 +8495,28 @@ import core.stdc.stdio : FILE, fopen, fclose, fseek, ftell, fread, SEEK_END, SEE
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// welcome to version hell!
|
// welcome to version hell!
|
||||||
version(nanovg_force_detect) {} else version(nanovg_use_freetype) { version = nanovg_use_freetype_ii; }
|
version(nanovg_force_stb_ttf) {
|
||||||
|
} else {
|
||||||
|
version(nanovg_force_detect) {} else version(nanovg_use_freetype) { version = nanovg_use_freetype_ii; }
|
||||||
|
}
|
||||||
version(nanovg_ignore_iv_stb_ttf) enum nanovg_ignore_iv_stb_ttf = true; else enum nanovg_ignore_iv_stb_ttf = false;
|
version(nanovg_ignore_iv_stb_ttf) enum nanovg_ignore_iv_stb_ttf = true; else enum nanovg_ignore_iv_stb_ttf = false;
|
||||||
//version(nanovg_ignore_mono);
|
//version(nanovg_ignore_mono);
|
||||||
|
|
||||||
version (nanovg_builtin_freetype_bindings) {
|
version(nanovg_force_stb_ttf) {
|
||||||
version(Posix) {
|
private enum NanoVegaForceFreeType = false;
|
||||||
private enum NanoVegaForceFreeType = true;
|
|
||||||
} else {
|
|
||||||
private enum NanoVegaForceFreeType = false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
version(Posix) {
|
version (nanovg_builtin_freetype_bindings) {
|
||||||
private enum NanoVegaForceFreeType = true;
|
version(Posix) {
|
||||||
|
private enum NanoVegaForceFreeType = true;
|
||||||
|
} else {
|
||||||
|
private enum NanoVegaForceFreeType = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
private enum NanoVegaForceFreeType = false;
|
version(Posix) {
|
||||||
|
private enum NanoVegaForceFreeType = true;
|
||||||
|
} else {
|
||||||
|
private enum NanoVegaForceFreeType = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8435,15 +8530,15 @@ version(nanovg_use_freetype_ii) {
|
||||||
static if (!nanovg_ignore_iv_stb_ttf && __traits(compiles, { import iv.stb.ttf; })) {
|
static if (!nanovg_ignore_iv_stb_ttf && __traits(compiles, { import iv.stb.ttf; })) {
|
||||||
import iv.stb.ttf;
|
import iv.stb.ttf;
|
||||||
enum NanoVegaIsUsingSTBTTF = true;
|
enum NanoVegaIsUsingSTBTTF = true;
|
||||||
//pragma(msg, "iv.stb.ttf");
|
version(nanovg_report_stb_ttf) pragma(msg, "iv.stb.ttf");
|
||||||
} else static if (__traits(compiles, { import arsd.ttf; })) {
|
} else static if (__traits(compiles, { import arsd.ttf; })) {
|
||||||
import arsd.ttf;
|
import arsd.ttf;
|
||||||
enum NanoVegaIsUsingSTBTTF = true;
|
enum NanoVegaIsUsingSTBTTF = true;
|
||||||
//pragma(msg, "arsd.ttf");
|
version(nanovg_report_stb_ttf) pragma(msg, "arsd.ttf");
|
||||||
} else static if (__traits(compiles, { import stb_truetype; })) {
|
} else static if (__traits(compiles, { import stb_truetype; })) {
|
||||||
import stb_truetype;
|
import stb_truetype;
|
||||||
enum NanoVegaIsUsingSTBTTF = true;
|
enum NanoVegaIsUsingSTBTTF = true;
|
||||||
//pragma(msg, "stb_truetype");
|
version(nanovg_report_stb_ttf) pragma(msg, "stb_truetype");
|
||||||
} else static if (__traits(compiles, { import iv.freetype; })) {
|
} else static if (__traits(compiles, { import iv.freetype; })) {
|
||||||
version (nanovg_builtin_freetype_bindings) {
|
version (nanovg_builtin_freetype_bindings) {
|
||||||
enum NanoVegaIsUsingSTBTTF = false;
|
enum NanoVegaIsUsingSTBTTF = false;
|
||||||
|
@ -8452,7 +8547,7 @@ version(nanovg_use_freetype_ii) {
|
||||||
import iv.freetype;
|
import iv.freetype;
|
||||||
enum NanoVegaIsUsingSTBTTF = false;
|
enum NanoVegaIsUsingSTBTTF = false;
|
||||||
}
|
}
|
||||||
//pragma(msg, "iv.freetype");
|
version(nanovg_report_stb_ttf) pragma(msg, "freetype");
|
||||||
} else {
|
} else {
|
||||||
static assert(0, "no stb_ttf/iv.freetype found!");
|
static assert(0, "no stb_ttf/iv.freetype found!");
|
||||||
}
|
}
|
||||||
|
@ -8973,8 +9068,8 @@ extern(C) nothrow @trusted @nogc {
|
||||||
NVGGlyphOutline* ol;
|
NVGGlyphOutline* ol;
|
||||||
FT_BBox outlineBBox;
|
FT_BBox outlineBBox;
|
||||||
nothrow @trusted @nogc:
|
nothrow @trusted @nogc:
|
||||||
T transx(T) (T v) const pure { pragma(inline, true); return v; }
|
static float transx(T) (T v) pure { pragma(inline, true); return cast(float)v; }
|
||||||
T transy(T) (T v) const pure { pragma(inline, true); return -v; }
|
static float transy(T) (T v) pure { pragma(inline, true); return -cast(float)v; }
|
||||||
void putBytes (const(void)[] b) {
|
void putBytes (const(void)[] b) {
|
||||||
assert(b.length <= 512);
|
assert(b.length <= 512);
|
||||||
if (b.length == 0) return;
|
if (b.length == 0) return;
|
||||||
|
@ -9187,11 +9282,178 @@ void fons__tt_renderGlyphBitmap (FONSttFontImpl* font, ubyte* output, int outWid
|
||||||
}
|
}
|
||||||
|
|
||||||
float fons__tt_getGlyphKernAdvance (FONSttFontImpl* font, float size, int glyph1, int glyph2) nothrow @trusted @nogc {
|
float fons__tt_getGlyphKernAdvance (FONSttFontImpl* font, float size, int glyph1, int glyph2) nothrow @trusted @nogc {
|
||||||
|
// FUnits -> pixels: pointSize * resolution / (72 points per inch * units_per_em)
|
||||||
|
// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM02/Chap2.html#converting
|
||||||
float res = void;
|
float res = void;
|
||||||
forceNoThrowNoGC({ res = stbtt_GetGlyphKernAdvance(&font.font, glyph1, glyph2); });
|
forceNoThrowNoGC({
|
||||||
|
res = stbtt_GetGlyphKernAdvance(&font.font, glyph1, glyph2);
|
||||||
|
res *= stbtt_ScaleForPixelHeight(&font.font, size);
|
||||||
|
});
|
||||||
|
/*
|
||||||
|
if (res != 0) {
|
||||||
|
{ import core.stdc.stdio; printf("fres=%g; size=%g; %g (%g); rv=%g\n", res, size, res*stbtt_ScaleForMappingEmToPixels(&font.font, size), stbtt_ScaleForPixelHeight(&font.font, size*100), res*stbtt_ScaleForPixelHeight(&font.font, size*100)); }
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//k8: dunno if this is right; i guess it isn't but...
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// old arsd.ttf sux! ;-)
|
||||||
|
static if (is(typeof(STBTT_vcubic))) {
|
||||||
|
|
||||||
|
static struct OutlinerData {
|
||||||
|
@disable this (this);
|
||||||
|
NVGGlyphOutline* ol;
|
||||||
|
nothrow @trusted @nogc:
|
||||||
|
static float transx(T) (T v) pure { pragma(inline, true); return cast(float)v; }
|
||||||
|
static float transy(T) (T v) pure { pragma(inline, true); return -cast(float)v; }
|
||||||
|
void putBytes (const(void)[] b) {
|
||||||
|
assert(b.length <= 512);
|
||||||
|
if (b.length == 0) return;
|
||||||
|
if (ol.used+cast(uint)b.length > ol.size) {
|
||||||
|
import core.stdc.stdlib : realloc;
|
||||||
|
uint newsz = (ol.size == 0 ? 2048 : ol.size < 32768 ? ol.size*2 : ol.size+8192);
|
||||||
|
assert(ol.used+cast(uint)b.length <= newsz);
|
||||||
|
auto nd = cast(ubyte*)realloc(ol.data, newsz);
|
||||||
|
if (nd is null) assert(0, "FONS: out of memory");
|
||||||
|
ol.size = newsz;
|
||||||
|
ol.data = nd;
|
||||||
|
}
|
||||||
|
import core.stdc.string : memcpy;
|
||||||
|
memcpy(ol.data+ol.used, b.ptr, b.length);
|
||||||
|
ol.used += cast(uint)b.length;
|
||||||
|
}
|
||||||
|
void newCommand (ubyte cmd) { pragma(inline, true); ++ol.ccount; putBytes((&cmd)[0..1]); }
|
||||||
|
void putArg (float f) { putBytes((&f)[0..1]); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool fons__nvg__toPath (NVGContext vg, FONSttFontImpl* font, uint glyphidx, float[] bounds=null) nothrow @trusted @nogc {
|
||||||
|
if (bounds.length > 4) bounds = bounds.ptr[0..4];
|
||||||
|
|
||||||
|
bool okflag = false;
|
||||||
|
|
||||||
|
forceNoThrowNoGC({
|
||||||
|
int x0, y0, x1, y1;
|
||||||
|
if (!stbtt_GetGlyphBox(&font.font, glyphidx, &x0, &y0, &x1, &y1)) {
|
||||||
|
bounds[] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bounds.length > 0) bounds.ptr[0] = x0;
|
||||||
|
if (bounds.length > 1) bounds.ptr[1] = -y1;
|
||||||
|
if (bounds.length > 2) bounds.ptr[2] = x1;
|
||||||
|
if (bounds.length > 3) bounds.ptr[3] = -y0;
|
||||||
|
|
||||||
|
static float transy(T) (T v) pure { pragma(inline, true); return -cast(float)v; }
|
||||||
|
|
||||||
|
stbtt_vertex* verts = null;
|
||||||
|
scope(exit) { import core.stdc.stdlib : free; if (verts !is null) free(verts); }
|
||||||
|
int vcount = stbtt_GetGlyphShape(&font.font, glyphidx, &verts);
|
||||||
|
if (vcount < 1) return;
|
||||||
|
|
||||||
|
foreach (const ref vt; verts[0..vcount]) {
|
||||||
|
switch (vt.type) {
|
||||||
|
case STBTT_vmove: vg.moveTo(vt.x, transy(vt.y)); break;
|
||||||
|
case STBTT_vline: vg.lineTo(vt.x, transy(vt.y)); break;
|
||||||
|
case STBTT_vcurve: vg.quadTo(vt.x, transy(vt.y), vt.cx, transy(vt.cy)); break;
|
||||||
|
case STBTT_vcubic: vg.bezierTo(vt.x, transy(vt.y), vt.cx, transy(vt.cy), vt.cx1, transy(vt.cy1)); break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
okflag = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return okflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fons__nvg__toOutline (FONSttFontImpl* font, uint glyphidx, NVGGlyphOutline* ol) nothrow @trusted @nogc {
|
||||||
|
bool okflag = false;
|
||||||
|
|
||||||
|
forceNoThrowNoGC({
|
||||||
|
int x0, y0, x1, y1;
|
||||||
|
|
||||||
|
if (!stbtt_GetGlyphBox(&font.font, glyphidx, &x0, &y0, &x1, &y1)) {
|
||||||
|
ol.bounds[] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.bounds.ptr[0] = x0;
|
||||||
|
ol.bounds.ptr[1] = -y1;
|
||||||
|
ol.bounds.ptr[2] = x1;
|
||||||
|
ol.bounds.ptr[3] = -y0;
|
||||||
|
|
||||||
|
stbtt_vertex* verts = null;
|
||||||
|
scope(exit) { import core.stdc.stdlib : free; if (verts !is null) free(verts); }
|
||||||
|
int vcount = stbtt_GetGlyphShape(&font.font, glyphidx, &verts);
|
||||||
|
if (vcount < 1) return;
|
||||||
|
|
||||||
|
OutlinerData odata;
|
||||||
|
odata.ol = ol;
|
||||||
|
|
||||||
|
foreach (const ref vt; verts[0..vcount]) {
|
||||||
|
switch (vt.type) {
|
||||||
|
case STBTT_vmove:
|
||||||
|
odata.newCommand(odata.ol.Command.Kind.MoveTo);
|
||||||
|
odata.putArg(odata.transx(vt.x));
|
||||||
|
odata.putArg(odata.transy(vt.y));
|
||||||
|
break;
|
||||||
|
case STBTT_vline:
|
||||||
|
odata.newCommand(odata.ol.Command.Kind.LineTo);
|
||||||
|
odata.putArg(odata.transx(vt.x));
|
||||||
|
odata.putArg(odata.transy(vt.y));
|
||||||
|
break;
|
||||||
|
case STBTT_vcurve:
|
||||||
|
odata.newCommand(odata.ol.Command.Kind.QuadTo);
|
||||||
|
odata.putArg(odata.transx(vt.x));
|
||||||
|
odata.putArg(odata.transy(vt.y));
|
||||||
|
odata.putArg(odata.transx(vt.cx));
|
||||||
|
odata.putArg(odata.transy(vt.cy));
|
||||||
|
break;
|
||||||
|
case STBTT_vcubic:
|
||||||
|
odata.newCommand(odata.ol.Command.Kind.BezierTo);
|
||||||
|
odata.putArg(odata.transx(vt.x));
|
||||||
|
odata.putArg(odata.transy(vt.y));
|
||||||
|
odata.putArg(odata.transx(vt.cx));
|
||||||
|
odata.putArg(odata.transy(vt.cy));
|
||||||
|
odata.putArg(odata.transx(vt.cx1));
|
||||||
|
odata.putArg(odata.transy(vt.cy1));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
okflag = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return okflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fons__nvg__bounds (FONSttFontImpl* font, uint glyphidx, float[] bounds) nothrow @trusted @nogc {
|
||||||
|
if (bounds.length > 4) bounds = bounds.ptr[0..4];
|
||||||
|
|
||||||
|
bool okflag = false;
|
||||||
|
|
||||||
|
forceNoThrowNoGC({
|
||||||
|
int x0, y0, x1, y1;
|
||||||
|
if (stbtt_GetGlyphBox(&font.font, glyphidx, &x0, &y0, &x1, &y1)) {
|
||||||
|
if (bounds.length > 0) bounds.ptr[0] = x0;
|
||||||
|
if (bounds.length > 1) bounds.ptr[1] = -y1;
|
||||||
|
if (bounds.length > 2) bounds.ptr[2] = x1;
|
||||||
|
if (bounds.length > 3) bounds.ptr[3] = -y0;
|
||||||
|
okflag = true;
|
||||||
|
} else {
|
||||||
|
bounds[] = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return okflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // check for old stb_ttf
|
||||||
|
|
||||||
|
|
||||||
} // version
|
} // version
|
||||||
|
|
||||||
|
|
||||||
|
@ -11645,7 +11907,7 @@ struct GLNVGcontext {
|
||||||
GLNVGpath* paths;
|
GLNVGpath* paths;
|
||||||
int cpaths;
|
int cpaths;
|
||||||
int npaths;
|
int npaths;
|
||||||
NVGvertex* verts;
|
NVGVertex* verts;
|
||||||
int cverts;
|
int cverts;
|
||||||
int nverts;
|
int nverts;
|
||||||
ubyte* uniforms;
|
ubyte* uniforms;
|
||||||
|
@ -12999,11 +13261,11 @@ void glnvg__renderFlush (void* uptr) nothrow @trusted @nogc {
|
||||||
|
|
||||||
// Upload vertex data
|
// Upload vertex data
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, gl.vertBuf);
|
glBindBuffer(GL_ARRAY_BUFFER, gl.vertBuf);
|
||||||
glBufferData(GL_ARRAY_BUFFER, gl.nverts*NVGvertex.sizeof, gl.verts, GL_STREAM_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, gl.nverts*NVGVertex.sizeof, gl.verts, GL_STREAM_DRAW);
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, NVGvertex.sizeof, cast(const(GLvoid)*)cast(usize)0);
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, NVGVertex.sizeof, cast(const(GLvoid)*)cast(usize)0);
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, NVGvertex.sizeof, cast(const(GLvoid)*)(0+2*float.sizeof));
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, NVGVertex.sizeof, cast(const(GLvoid)*)(0+2*float.sizeof));
|
||||||
glnvg__checkError(gl, "vertex data uploading");
|
glnvg__checkError(gl, "vertex data uploading");
|
||||||
|
|
||||||
// Set view and texture just once per frame.
|
// Set view and texture just once per frame.
|
||||||
|
@ -13169,9 +13431,9 @@ int glnvg__allocPaths (GLNVGcontext* gl, int n) nothrow @trusted @nogc {
|
||||||
int glnvg__allocVerts (GLNVGcontext* gl, int n) nothrow @trusted @nogc {
|
int glnvg__allocVerts (GLNVGcontext* gl, int n) nothrow @trusted @nogc {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (gl.nverts+n > gl.cverts) {
|
if (gl.nverts+n > gl.cverts) {
|
||||||
NVGvertex* verts;
|
NVGVertex* verts;
|
||||||
int cverts = glnvg__maxi(gl.nverts+n, 4096)+gl.cverts/2; // 1.5x Overallocate
|
int cverts = glnvg__maxi(gl.nverts+n, 4096)+gl.cverts/2; // 1.5x Overallocate
|
||||||
verts = cast(NVGvertex*)realloc(gl.verts, NVGvertex.sizeof*cverts);
|
verts = cast(NVGVertex*)realloc(gl.verts, NVGVertex.sizeof*cverts);
|
||||||
if (verts is null) return -1;
|
if (verts is null) return -1;
|
||||||
gl.verts = verts;
|
gl.verts = verts;
|
||||||
gl.cverts = cverts;
|
gl.cverts = cverts;
|
||||||
|
@ -13200,7 +13462,7 @@ GLNVGfragUniforms* nvg__fragUniformPtr (GLNVGcontext* gl, int i) nothrow @truste
|
||||||
return cast(GLNVGfragUniforms*)&gl.uniforms[i];
|
return cast(GLNVGfragUniforms*)&gl.uniforms[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void glnvg__vset (NVGvertex* vtx, float x, float y, float u, float v) nothrow @trusted @nogc {
|
void glnvg__vset (NVGVertex* vtx, float x, float y, float u, float v) nothrow @trusted @nogc {
|
||||||
vtx.x = x;
|
vtx.x = x;
|
||||||
vtx.y = y;
|
vtx.y = y;
|
||||||
vtx.u = u;
|
vtx.u = u;
|
||||||
|
@ -13212,7 +13474,7 @@ void glnvg__renderFill (void* uptr, NVGCompositeOperationState compositeOperatio
|
||||||
|
|
||||||
GLNVGcontext* gl = cast(GLNVGcontext*)uptr;
|
GLNVGcontext* gl = cast(GLNVGcontext*)uptr;
|
||||||
GLNVGcall* call = glnvg__allocCall(gl);
|
GLNVGcall* call = glnvg__allocCall(gl);
|
||||||
NVGvertex* quad;
|
NVGVertex* quad;
|
||||||
GLNVGfragUniforms* frag;
|
GLNVGfragUniforms* frag;
|
||||||
int maxverts, offset;
|
int maxverts, offset;
|
||||||
|
|
||||||
|
@ -13247,13 +13509,13 @@ void glnvg__renderFill (void* uptr, NVGCompositeOperationState compositeOperatio
|
||||||
if (path.nfill > 0) {
|
if (path.nfill > 0) {
|
||||||
copy.fillOffset = offset;
|
copy.fillOffset = offset;
|
||||||
copy.fillCount = path.nfill;
|
copy.fillCount = path.nfill;
|
||||||
memcpy(&gl.verts[offset], path.fill, NVGvertex.sizeof*path.nfill);
|
memcpy(&gl.verts[offset], path.fill, NVGVertex.sizeof*path.nfill);
|
||||||
offset += path.nfill;
|
offset += path.nfill;
|
||||||
}
|
}
|
||||||
if (path.nstroke > 0) {
|
if (path.nstroke > 0) {
|
||||||
copy.strokeOffset = offset;
|
copy.strokeOffset = offset;
|
||||||
copy.strokeCount = path.nstroke;
|
copy.strokeCount = path.nstroke;
|
||||||
memcpy(&gl.verts[offset], path.stroke, NVGvertex.sizeof*path.nstroke);
|
memcpy(&gl.verts[offset], path.stroke, NVGVertex.sizeof*path.nstroke);
|
||||||
offset += path.nstroke;
|
offset += path.nstroke;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13325,7 +13587,7 @@ void glnvg__renderStroke (void* uptr, NVGCompositeOperationState compositeOperat
|
||||||
if (path.nstroke) {
|
if (path.nstroke) {
|
||||||
copy.strokeOffset = offset;
|
copy.strokeOffset = offset;
|
||||||
copy.strokeCount = path.nstroke;
|
copy.strokeCount = path.nstroke;
|
||||||
memcpy(&gl.verts[offset], path.stroke, NVGvertex.sizeof*path.nstroke);
|
memcpy(&gl.verts[offset], path.stroke, NVGVertex.sizeof*path.nstroke);
|
||||||
offset += path.nstroke;
|
offset += path.nstroke;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13351,7 +13613,7 @@ error:
|
||||||
if (gl.ncalls > 0) --gl.ncalls;
|
if (gl.ncalls > 0) --gl.ncalls;
|
||||||
}
|
}
|
||||||
|
|
||||||
void glnvg__renderTriangles (void* uptr, NVGCompositeOperationState compositeOperation, NVGClipMode clipmode, NVGPaint* paint, NVGscissor* scissor, const(NVGvertex)* verts, int nverts) nothrow @trusted @nogc {
|
void glnvg__renderTriangles (void* uptr, NVGCompositeOperationState compositeOperation, NVGClipMode clipmode, NVGPaint* paint, NVGscissor* scissor, const(NVGVertex)* verts, int nverts) nothrow @trusted @nogc {
|
||||||
if (nverts < 1) return;
|
if (nverts < 1) return;
|
||||||
|
|
||||||
GLNVGcontext* gl = cast(GLNVGcontext*)uptr;
|
GLNVGcontext* gl = cast(GLNVGcontext*)uptr;
|
||||||
|
@ -13371,7 +13633,7 @@ void glnvg__renderTriangles (void* uptr, NVGCompositeOperationState compositeOpe
|
||||||
if (call.triangleOffset == -1) goto error;
|
if (call.triangleOffset == -1) goto error;
|
||||||
call.triangleCount = nverts;
|
call.triangleCount = nverts;
|
||||||
|
|
||||||
memcpy(&gl.verts[call.triangleOffset], verts, NVGvertex.sizeof*nverts);
|
memcpy(&gl.verts[call.triangleOffset], verts, NVGVertex.sizeof*nverts);
|
||||||
|
|
||||||
// Fill shader
|
// Fill shader
|
||||||
call.uniformOffset = glnvg__allocFragUniforms(gl, 1);
|
call.uniformOffset = glnvg__allocFragUniforms(gl, 1);
|
||||||
|
|
Loading…
Reference in New Issue