mirror of https://github.com/adamdruppe/arsd.git
nanovega: changed outline API a little (it is just an ordinary struct with refcounted payload now)
This commit is contained in:
parent
b56d59f208
commit
88ca1e2556
307
nanovega.d
307
nanovega.d
|
|
@ -7563,7 +7563,7 @@ public bool charPathBounds (NVGContext ctx, dchar dch, float[] bounds) nothrow @
|
||||||
return fonsPathBounds(ctx.fs, dch, bounds);
|
return fonsPathBounds(ctx.fs, dch, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** [charOutline] will return malloced [NVGGlyphOutline].
|
/** [charOutline] will return [NVGPathOutline].
|
||||||
|
|
||||||
some usage samples:
|
some usage samples:
|
||||||
|
|
||||||
|
|
@ -7627,29 +7627,102 @@ public bool charPathBounds (NVGContext ctx, dchar dch, float[] bounds) nothrow @
|
||||||
|
|
||||||
Group: text_api
|
Group: text_api
|
||||||
*/
|
*/
|
||||||
public struct NVGGlyphOutline {
|
public struct NVGPathOutline {
|
||||||
|
private nothrow @trusted @nogc:
|
||||||
|
struct DataStore {
|
||||||
|
uint rc; // refcount
|
||||||
|
ubyte* data;
|
||||||
|
uint used;
|
||||||
|
uint size;
|
||||||
|
uint ccount; // number of commands
|
||||||
|
float[4] bounds = 0; /// outline bounds
|
||||||
|
nothrow @trusted @nogc:
|
||||||
|
void putBytes (const(void)[] b) {
|
||||||
|
if (b.length == 0) return;
|
||||||
|
if (b.length >= int.max/8) assert(0, "NanoVega: out of memory");
|
||||||
|
if (int.max/8-used < b.length) assert(0, "NanoVega: out of memory");
|
||||||
|
if (used+cast(uint)b.length > size) {
|
||||||
|
import core.stdc.stdlib : realloc;
|
||||||
|
uint newsz = size;
|
||||||
|
while (newsz < used+cast(uint)b.length) newsz = (newsz == 0 ? 2048 : newsz < 32768 ? newsz*2 : newsz+8192);
|
||||||
|
assert(used+cast(uint)b.length <= newsz);
|
||||||
|
data = cast(ubyte*)realloc(data, newsz);
|
||||||
|
if (data is null) assert(0, "NanoVega: out of memory");
|
||||||
|
size = newsz;
|
||||||
|
}
|
||||||
|
import core.stdc.string : memcpy;
|
||||||
|
memcpy(data+used, b.ptr, b.length);
|
||||||
|
used += cast(uint)b.length;
|
||||||
|
}
|
||||||
|
void putCommand (ubyte cmd) { pragma(inline, true); ++ccount; putBytes((&cmd)[0..1]); }
|
||||||
|
void putArgs (const(float)[] f...) { pragma(inline, true); putBytes(f[]); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void incRef (DataStore* ds) {
|
||||||
|
pragma(inline, true);
|
||||||
|
if (ds !is null) {
|
||||||
|
++ds.rc;
|
||||||
|
//{ import core.stdc.stdio; printf("ods(%p): incref: newrc=%u\n", ds, ds.rc); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decRef (DataStore* ds) {
|
||||||
|
version(aliced) pragma(inline, true);
|
||||||
|
if (ds !is null) {
|
||||||
|
//{ import core.stdc.stdio; printf("ods(%p): decref: newrc=%u\n", ds, ds.rc-1); }
|
||||||
|
if (--ds.rc == 0) {
|
||||||
|
import core.stdc.stdlib : free;
|
||||||
|
import core.stdc.string : memset;
|
||||||
|
if (ds.data !is null) free(ds.data);
|
||||||
|
memset(ds, 0, DataStore.sizeof); // just in case
|
||||||
|
free(ds);
|
||||||
|
//{ import core.stdc.stdio; printf(" ods(%p): killed.\n"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static NVGPathOutline createNew () {
|
||||||
|
import core.stdc.stdlib : malloc;
|
||||||
|
import core.stdc.string : memset;
|
||||||
|
auto ds = cast(DataStore*)malloc(DataStore.sizeof);
|
||||||
|
if (ds is null) assert(0, "NanoVega: out of memory");
|
||||||
|
memset(ds, 0, DataStore.sizeof);
|
||||||
|
ds.rc = 1;
|
||||||
|
NVGPathOutline res;
|
||||||
|
res.dsaddr = cast(usize)ds;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
usize dsaddr; // fool GC
|
||||||
|
|
||||||
|
@property inout(DataStore)* ds () inout pure { pragma(inline, true); return cast(DataStore*)dsaddr; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// commands
|
/// commands
|
||||||
static struct Command {
|
static struct Command {
|
||||||
|
///
|
||||||
enum Kind : ubyte {
|
enum Kind : ubyte {
|
||||||
MoveTo, ///
|
MoveTo, ///
|
||||||
LineTo, ///
|
LineTo, ///
|
||||||
QuadTo, ///
|
QuadTo, ///
|
||||||
BezierTo, ///
|
BezierTo, ///
|
||||||
|
End, /// no more commands (this command is not `valid`!)
|
||||||
}
|
}
|
||||||
Kind code; ///
|
Kind code; ///
|
||||||
const(float)[] args; ///
|
const(float)[] args; ///
|
||||||
@property bool valid () const pure nothrow @safe @nogc { pragma(inline, true); return (code >= 0 && code <= 3 && args.length >= 2); } ///
|
@property bool valid () const pure nothrow @safe @nogc { pragma(inline, true); return (code >= Kind.min && code < Kind.End && args.length >= 2); } ///
|
||||||
|
|
||||||
/// perform NanoVega command with stored data.
|
/// perform NanoVega command with stored data.
|
||||||
void perform (NVGContext ctx) const nothrow @trusted @nogc {
|
void perform (NVGContext ctx) const nothrow @trusted @nogc {
|
||||||
if (ctx is null) return;
|
if (ctx is null) return;
|
||||||
switch (code) {
|
final switch (code) {
|
||||||
case Kind.MoveTo: if (args.length > 1) ctx.moveTo(args.ptr[0..2]); break;
|
case Kind.MoveTo: if (args.length > 1) ctx.moveTo(args.ptr[0..2]); break;
|
||||||
case Kind.LineTo: if (args.length > 1) ctx.lineTo(args.ptr[0..2]); break;
|
case Kind.LineTo: if (args.length > 1) ctx.lineTo(args.ptr[0..2]); break;
|
||||||
case Kind.QuadTo: if (args.length > 3) ctx.quadTo(args.ptr[0..4]); break;
|
case Kind.QuadTo: if (args.length > 3) ctx.quadTo(args.ptr[0..4]); break;
|
||||||
case Kind.BezierTo: if (args.length > 5) ctx.bezierTo(args.ptr[0..6]); break;
|
case Kind.BezierTo: if (args.length > 5) ctx.bezierTo(args.ptr[0..6]); break;
|
||||||
default: break;
|
case Kind.End: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7659,71 +7732,83 @@ public:
|
||||||
float[6] pts = void;
|
float[6] pts = void;
|
||||||
pts[0..args.length] = args[];
|
pts[0..args.length] = args[];
|
||||||
foreach (immutable pidx; 0..args.length/2) xform.point(pts.ptr[pidx*2+0], pts.ptr[pidx*2+1]);
|
foreach (immutable pidx; 0..args.length/2) xform.point(pts.ptr[pidx*2+0], pts.ptr[pidx*2+1]);
|
||||||
switch (code) {
|
final switch (code) {
|
||||||
case Kind.MoveTo: if (args.length > 1) ctx.moveTo(pts.ptr[0..2]); break;
|
case Kind.MoveTo: if (args.length > 1) ctx.moveTo(pts.ptr[0..2]); break;
|
||||||
case Kind.LineTo: if (args.length > 1) ctx.lineTo(pts.ptr[0..2]); break;
|
case Kind.LineTo: if (args.length > 1) ctx.lineTo(pts.ptr[0..2]); break;
|
||||||
case Kind.QuadTo: if (args.length > 3) ctx.quadTo(pts.ptr[0..4]); break;
|
case Kind.QuadTo: if (args.length > 3) ctx.quadTo(pts.ptr[0..4]); break;
|
||||||
case Kind.BezierTo: if (args.length > 5) ctx.bezierTo(pts.ptr[0..6]); break;
|
case Kind.BezierTo: if (args.length > 5) ctx.bezierTo(pts.ptr[0..6]); break;
|
||||||
default: break;
|
case Kind.End: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@disable this (this); // no copies
|
public:
|
||||||
|
this (this) { pragma(inline, true); incRef(cast(DataStore*)dsaddr); }
|
||||||
|
~this () { pragma(inline, true); decRef(cast(DataStore*)dsaddr); }
|
||||||
|
|
||||||
private:
|
void opAssign() (in auto ref NVGPathOutline a) {
|
||||||
ubyte* data;
|
incRef(cast(DataStore*)a.dsaddr);
|
||||||
uint used;
|
decRef(cast(DataStore*)dsaddr);
|
||||||
uint size;
|
dsaddr = a.dsaddr;
|
||||||
uint ccount; // number of commands
|
|
||||||
|
|
||||||
private:
|
|
||||||
void clear () nothrow @trusted @nogc {
|
|
||||||
import core.stdc.stdlib : free;
|
|
||||||
if (data !is null) { free(data); data = null; }
|
|
||||||
used = size = ccount = 0;
|
|
||||||
bounds[] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
/// Clear storage.
|
||||||
float[4] bounds = 0; /// glyph outline bounds
|
void clear () {
|
||||||
|
pragma(inline, true);
|
||||||
|
decRef(ds);
|
||||||
|
dsaddr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
@property int length () const pure { pragma(inline, true); return ccount; } /// number of commands in outline
|
/// Is this outline empty?
|
||||||
|
@property empty () const pure { pragma(inline, true); return (dsaddr == 0 || ds.ccount == 0); }
|
||||||
|
|
||||||
|
/// Returns umber of commands in outline.
|
||||||
|
@property int length () const pure { pragma(inline, true); return (dsaddr ? ds.ccount : 0); }
|
||||||
|
|
||||||
public:
|
|
||||||
/// Returns forward range with all glyph commands.
|
/// Returns forward range with all glyph commands.
|
||||||
/// $(WARNING returned rande should not outlive parent struct!)
|
|
||||||
auto commands () nothrow @trusted @nogc {
|
auto commands () nothrow @trusted @nogc {
|
||||||
static struct Range {
|
static struct Range {
|
||||||
private nothrow @trusted @nogc:
|
private nothrow @trusted @nogc:
|
||||||
const(ubyte)* data;
|
usize dsaddr;
|
||||||
|
uint cpos; // current position in data
|
||||||
uint cleft; // number of commands left
|
uint cleft; // number of commands left
|
||||||
|
@property const(ubyte)* data () inout pure { pragma(inline, true); return (dsaddr ? (cast(DataStore*)dsaddr).data : null); }
|
||||||
public:
|
public:
|
||||||
|
this (this) { pragma(inline, true); incRef(cast(DataStore*)dsaddr); }
|
||||||
|
~this () { pragma(inline, true); decRef(cast(DataStore*)dsaddr); }
|
||||||
|
void opAssign() (in auto ref Range a) {
|
||||||
|
incRef(cast(DataStore*)a.dsaddr);
|
||||||
|
decRef(cast(DataStore*)dsaddr);
|
||||||
|
dsaddr = a.dsaddr;
|
||||||
|
cpos = a.cpos;
|
||||||
|
cleft = a.cleft;
|
||||||
|
}
|
||||||
|
float[4] bounds () const pure { float[4] res = 0; pragma(inline, true); if (dsaddr) res[] = (cast(DataStore*)dsaddr).bounds[]; return res; } /// outline bounds
|
||||||
@property bool empty () const pure { pragma(inline, true); return (cleft == 0); }
|
@property bool empty () const pure { pragma(inline, true); return (cleft == 0); }
|
||||||
@property int length () const pure { pragma(inline, true); return cleft; }
|
@property int length () const pure { pragma(inline, true); return cleft; }
|
||||||
@property Range save () const pure { pragma(inline, true); Range res = this; return res; }
|
@property Range save () const { pragma(inline, true); Range res = this; return res; }
|
||||||
@property Command front () const {
|
@property Command front () const {
|
||||||
Command res = void;
|
Command res = void;
|
||||||
if (cleft > 0) {
|
if (cleft > 0) {
|
||||||
res.code = cast(Command.Kind)data[0];
|
res.code = cast(Command.Kind)data[cpos];
|
||||||
switch (res.code) {
|
switch (res.code) {
|
||||||
case Command.Kind.MoveTo:
|
case Command.Kind.MoveTo:
|
||||||
case Command.Kind.LineTo:
|
case Command.Kind.LineTo:
|
||||||
res.args = (cast(const(float*))(data+1))[0..1*2];
|
res.args = (cast(const(float*))(data+cpos+1))[0..1*2];
|
||||||
break;
|
break;
|
||||||
case Command.Kind.QuadTo:
|
case Command.Kind.QuadTo:
|
||||||
res.args = (cast(const(float*))(data+1))[0..2*2];
|
res.args = (cast(const(float*))(data+cpos+1))[0..2*2];
|
||||||
break;
|
break;
|
||||||
case Command.Kind.BezierTo:
|
case Command.Kind.BezierTo:
|
||||||
res.args = (cast(const(float*))(data+1))[0..3*2];
|
res.args = (cast(const(float*))(data+cpos+1))[0..3*2];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
res.code = cast(Command.Kind)255;
|
res.code = Command.Kind.End;
|
||||||
res.args = null;
|
res.args = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res.code = cast(Command.Kind)255;
|
res.code = Command.Kind.End;
|
||||||
res.args = null;
|
res.args = null;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -7731,16 +7816,16 @@ public:
|
||||||
void popFront () {
|
void popFront () {
|
||||||
if (cleft == 0) return;
|
if (cleft == 0) return;
|
||||||
if (--cleft == 0) return; // don't waste time skipping last command
|
if (--cleft == 0) return; // don't waste time skipping last command
|
||||||
switch (data[0]) {
|
switch (data[cpos]) {
|
||||||
case Command.Kind.MoveTo:
|
case Command.Kind.MoveTo:
|
||||||
case Command.Kind.LineTo:
|
case Command.Kind.LineTo:
|
||||||
data += 1+1*2*cast(uint)float.sizeof;
|
cpos += 1+1*2*cast(uint)float.sizeof;
|
||||||
break;
|
break;
|
||||||
case Command.Kind.QuadTo:
|
case Command.Kind.QuadTo:
|
||||||
data += 1+2*2*cast(uint)float.sizeof;
|
cpos += 1+2*2*cast(uint)float.sizeof;
|
||||||
break;
|
break;
|
||||||
case Command.Kind.BezierTo:
|
case Command.Kind.BezierTo:
|
||||||
data += 1+3*2*cast(uint)float.sizeof;
|
cpos += 1+3*2*cast(uint)float.sizeof;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cleft = 0;
|
cleft = 0;
|
||||||
|
|
@ -7748,19 +7833,22 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Range(data, ccount);
|
if (dsaddr) {
|
||||||
|
incRef(cast(DataStore*)dsaddr); // range anchors it
|
||||||
|
return Range(dsaddr, 0, ds.ccount);
|
||||||
|
} else {
|
||||||
|
return Range.init;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public alias NVGGlyphOutline = NVGPathOutline; /// For backwards compatibility.
|
||||||
|
|
||||||
/// Destroy glyph outiline and free allocated memory.
|
/// Destroy glyph outiline and free allocated memory.
|
||||||
/// Group: text_api
|
/// Group: text_api
|
||||||
public void kill (ref NVGGlyphOutline* ol) nothrow @trusted @nogc {
|
public void kill (ref NVGPathOutline ol) nothrow @trusted @nogc {
|
||||||
if (ol !is null) {
|
pragma(inline, true);
|
||||||
import core.stdc.stdlib : free;
|
ol.clear();
|
||||||
ol.clear();
|
|
||||||
free(ol);
|
|
||||||
ol = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static if (is(typeof(&fons__nvg__toOutline))) {
|
static if (is(typeof(&fons__nvg__toOutline))) {
|
||||||
|
|
@ -7773,17 +7861,14 @@ static if (is(typeof(&fons__nvg__toOutline))) {
|
||||||
/// The glyph is not scaled in any way, so you have to use NanoVega transformations instead.
|
/// The glyph is not scaled in any way, so you have to use NanoVega transformations instead.
|
||||||
/// Returns `null` if there is no such glyph, or current font is not scalable.
|
/// Returns `null` if there is no such glyph, or current font is not scalable.
|
||||||
/// Group: text_api
|
/// Group: text_api
|
||||||
public NVGGlyphOutline* charOutline (NVGContext ctx, dchar dch) nothrow @trusted @nogc {
|
public NVGPathOutline charOutline (NVGContext ctx, dchar dch) nothrow @trusted @nogc {
|
||||||
import core.stdc.stdlib : malloc;
|
import core.stdc.stdlib : malloc;
|
||||||
import core.stdc.string : memcpy;
|
import core.stdc.string : memcpy;
|
||||||
NVGstate* state = nvg__getState(ctx);
|
NVGstate* state = nvg__getState(ctx);
|
||||||
fonsSetFont(ctx.fs, state.fontId);
|
fonsSetFont(ctx.fs, state.fontId);
|
||||||
NVGGlyphOutline oline;
|
auto oline = NVGPathOutline.createNew();
|
||||||
if (!fonsToOutline(ctx.fs, dch, &oline)) { oline.clear(); return null; }
|
if (!fonsToOutline(ctx.fs, dch, oline.ds)) oline.clear();
|
||||||
auto res = cast(NVGGlyphOutline*)malloc(NVGGlyphOutline.sizeof);
|
return oline;
|
||||||
if (res is null) { oline.clear(); return null; }
|
|
||||||
memcpy(res, &oline, oline.sizeof);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -9139,38 +9224,20 @@ extern(C) nothrow @trusted @nogc {
|
||||||
static struct OutlinerData {
|
static struct OutlinerData {
|
||||||
@disable this (this);
|
@disable this (this);
|
||||||
NVGContext vg;
|
NVGContext vg;
|
||||||
NVGGlyphOutline* ol;
|
NVGPathOutline.DataStore* ol;
|
||||||
FT_BBox outlineBBox;
|
FT_BBox outlineBBox;
|
||||||
nothrow @trusted @nogc:
|
nothrow @trusted @nogc:
|
||||||
static float transx(T) (T v) pure { pragma(inline, true); return cast(float)v; }
|
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; }
|
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]); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int fons__nvg__moveto_cb (const(FT_Vector)* to, void* user) {
|
int fons__nvg__moveto_cb (const(FT_Vector)* to, void* user) {
|
||||||
auto odata = cast(OutlinerData*)user;
|
auto odata = cast(OutlinerData*)user;
|
||||||
if (odata.vg !is null) odata.vg.moveTo(odata.transx(to.x), odata.transy(to.y));
|
if (odata.vg !is null) odata.vg.moveTo(odata.transx(to.x), odata.transy(to.y));
|
||||||
if (odata.ol !is null) {
|
if (odata.ol !is null) {
|
||||||
odata.newCommand(odata.ol.Command.Kind.MoveTo);
|
odata.ol.putCommand(NVGPathOutline.Command.Kind.MoveTo);
|
||||||
odata.putArg(odata.transx(to.x));
|
odata.ol.putArgs(odata.transx(to.x));
|
||||||
odata.putArg(odata.transy(to.y));
|
odata.ol.putArgs(odata.transy(to.y));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -9179,9 +9246,9 @@ extern(C) nothrow @trusted @nogc {
|
||||||
auto odata = cast(OutlinerData*)user;
|
auto odata = cast(OutlinerData*)user;
|
||||||
if (odata.vg !is null) odata.vg.lineTo(odata.transx(to.x), odata.transy(to.y));
|
if (odata.vg !is null) odata.vg.lineTo(odata.transx(to.x), odata.transy(to.y));
|
||||||
if (odata.ol !is null) {
|
if (odata.ol !is null) {
|
||||||
odata.newCommand(odata.ol.Command.Kind.LineTo);
|
odata.ol.putCommand(NVGPathOutline.Command.Kind.LineTo);
|
||||||
odata.putArg(odata.transx(to.x));
|
odata.ol.putArgs(odata.transx(to.x));
|
||||||
odata.putArg(odata.transy(to.y));
|
odata.ol.putArgs(odata.transy(to.y));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -9190,11 +9257,11 @@ extern(C) nothrow @trusted @nogc {
|
||||||
auto odata = cast(OutlinerData*)user;
|
auto odata = cast(OutlinerData*)user;
|
||||||
if (odata.vg !is null) odata.vg.quadTo(odata.transx(c1.x), odata.transy(c1.y), odata.transx(to.x), odata.transy(to.y));
|
if (odata.vg !is null) odata.vg.quadTo(odata.transx(c1.x), odata.transy(c1.y), odata.transx(to.x), odata.transy(to.y));
|
||||||
if (odata.ol !is null) {
|
if (odata.ol !is null) {
|
||||||
odata.newCommand(odata.ol.Command.Kind.QuadTo);
|
odata.ol.putCommand(NVGPathOutline.Command.Kind.QuadTo);
|
||||||
odata.putArg(odata.transx(c1.x));
|
odata.ol.putArgs(odata.transx(c1.x));
|
||||||
odata.putArg(odata.transy(c1.y));
|
odata.ol.putArgs(odata.transy(c1.y));
|
||||||
odata.putArg(odata.transx(to.x));
|
odata.ol.putArgs(odata.transx(to.x));
|
||||||
odata.putArg(odata.transy(to.y));
|
odata.ol.putArgs(odata.transy(to.y));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -9203,13 +9270,13 @@ extern(C) nothrow @trusted @nogc {
|
||||||
auto odata = cast(OutlinerData*)user;
|
auto odata = cast(OutlinerData*)user;
|
||||||
if (odata.vg !is null) odata.vg.bezierTo(odata.transx(c1.x), odata.transy(c1.y), odata.transx(c2.x), odata.transy(c2.y), odata.transx(to.x), odata.transy(to.y));
|
if (odata.vg !is null) odata.vg.bezierTo(odata.transx(c1.x), odata.transy(c1.y), odata.transx(c2.x), odata.transy(c2.y), odata.transx(to.x), odata.transy(to.y));
|
||||||
if (odata.ol !is null) {
|
if (odata.ol !is null) {
|
||||||
odata.newCommand(odata.ol.Command.Kind.BezierTo);
|
odata.ol.putCommand(NVGPathOutline.Command.Kind.BezierTo);
|
||||||
odata.putArg(odata.transx(c1.x));
|
odata.ol.putArgs(odata.transx(c1.x));
|
||||||
odata.putArg(odata.transy(c1.y));
|
odata.ol.putArgs(odata.transy(c1.y));
|
||||||
odata.putArg(odata.transx(c2.x));
|
odata.ol.putArgs(odata.transx(c2.x));
|
||||||
odata.putArg(odata.transy(c2.y));
|
odata.ol.putArgs(odata.transy(c2.y));
|
||||||
odata.putArg(odata.transx(to.x));
|
odata.ol.putArgs(odata.transx(to.x));
|
||||||
odata.putArg(odata.transy(to.y));
|
odata.ol.putArgs(odata.transy(to.y));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -9243,7 +9310,7 @@ bool fons__nvg__toPath (NVGContext vg, FONSttFontImpl* font, uint glyphidx, floa
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fons__nvg__toOutline (FONSttFontImpl* font, uint glyphidx, NVGGlyphOutline* ol) nothrow @trusted @nogc {
|
bool fons__nvg__toOutline (FONSttFontImpl* font, uint glyphidx, NVGPathOutline.DataStore* ol) nothrow @trusted @nogc {
|
||||||
FT_Outline_Funcs funcs;
|
FT_Outline_Funcs funcs;
|
||||||
funcs.move_to = &fons__nvg__moveto_cb;
|
funcs.move_to = &fons__nvg__moveto_cb;
|
||||||
funcs.line_to = &fons__nvg__lineto_cb;
|
funcs.line_to = &fons__nvg__lineto_cb;
|
||||||
|
|
@ -9377,28 +9444,10 @@ static if (is(typeof(STBTT_vcubic))) {
|
||||||
|
|
||||||
static struct OutlinerData {
|
static struct OutlinerData {
|
||||||
@disable this (this);
|
@disable this (this);
|
||||||
NVGGlyphOutline* ol;
|
NVGPathOutline.DataStore* ol;
|
||||||
nothrow @trusted @nogc:
|
nothrow @trusted @nogc:
|
||||||
static float transx(T) (T v) pure { pragma(inline, true); return cast(float)v; }
|
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; }
|
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]); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -9442,7 +9491,7 @@ bool fons__nvg__toPath (NVGContext vg, FONSttFontImpl* font, uint glyphidx, floa
|
||||||
return okflag;
|
return okflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fons__nvg__toOutline (FONSttFontImpl* font, uint glyphidx, NVGGlyphOutline* ol) nothrow @trusted @nogc {
|
bool fons__nvg__toOutline (FONSttFontImpl* font, uint glyphidx, NVGPathOutline.DataStore* ol) nothrow @trusted @nogc {
|
||||||
bool okflag = false;
|
bool okflag = false;
|
||||||
|
|
||||||
forceNoThrowNoGC({
|
forceNoThrowNoGC({
|
||||||
|
|
@ -9469,30 +9518,30 @@ bool fons__nvg__toOutline (FONSttFontImpl* font, uint glyphidx, NVGGlyphOutline*
|
||||||
foreach (const ref vt; verts[0..vcount]) {
|
foreach (const ref vt; verts[0..vcount]) {
|
||||||
switch (vt.type) {
|
switch (vt.type) {
|
||||||
case STBTT_vmove:
|
case STBTT_vmove:
|
||||||
odata.newCommand(odata.ol.Command.Kind.MoveTo);
|
odata.ol.putCommand(NVGPathOutline.Command.Kind.MoveTo);
|
||||||
odata.putArg(odata.transx(vt.x));
|
odata.ol.putArgs(odata.transx(vt.x));
|
||||||
odata.putArg(odata.transy(vt.y));
|
odata.ol.putArgs(odata.transy(vt.y));
|
||||||
break;
|
break;
|
||||||
case STBTT_vline:
|
case STBTT_vline:
|
||||||
odata.newCommand(odata.ol.Command.Kind.LineTo);
|
odata.ol.putCommand(NVGPathOutline.Command.Kind.LineTo);
|
||||||
odata.putArg(odata.transx(vt.x));
|
odata.ol.putArgs(odata.transx(vt.x));
|
||||||
odata.putArg(odata.transy(vt.y));
|
odata.ol.putArgs(odata.transy(vt.y));
|
||||||
break;
|
break;
|
||||||
case STBTT_vcurve:
|
case STBTT_vcurve:
|
||||||
odata.newCommand(odata.ol.Command.Kind.QuadTo);
|
odata.ol.putCommand(NVGPathOutline.Command.Kind.QuadTo);
|
||||||
odata.putArg(odata.transx(vt.x));
|
odata.ol.putArgs(odata.transx(vt.x));
|
||||||
odata.putArg(odata.transy(vt.y));
|
odata.ol.putArgs(odata.transy(vt.y));
|
||||||
odata.putArg(odata.transx(vt.cx));
|
odata.ol.putArgs(odata.transx(vt.cx));
|
||||||
odata.putArg(odata.transy(vt.cy));
|
odata.ol.putArgs(odata.transy(vt.cy));
|
||||||
break;
|
break;
|
||||||
case STBTT_vcubic:
|
case STBTT_vcubic:
|
||||||
odata.newCommand(odata.ol.Command.Kind.BezierTo);
|
odata.ol.putCommand(NVGPathOutline.Command.Kind.BezierTo);
|
||||||
odata.putArg(odata.transx(vt.x));
|
odata.ol.putArgs(odata.transx(vt.x));
|
||||||
odata.putArg(odata.transy(vt.y));
|
odata.ol.putArgs(odata.transy(vt.y));
|
||||||
odata.putArg(odata.transx(vt.cx));
|
odata.ol.putArgs(odata.transx(vt.cx));
|
||||||
odata.putArg(odata.transy(vt.cy));
|
odata.ol.putArgs(odata.transy(vt.cy));
|
||||||
odata.putArg(odata.transx(vt.cx1));
|
odata.ol.putArgs(odata.transx(vt.cx1));
|
||||||
odata.putArg(odata.transy(vt.cy1));
|
odata.ol.putArgs(odata.transy(vt.cy1));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
@ -10603,7 +10652,7 @@ public bool fonsToPath (FONScontext* stash, NVGContext vg, dchar dch, float[] bo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool fonsToOutline (FONScontext* stash, dchar dch, NVGGlyphOutline* ol) nothrow @trusted @nogc {
|
public bool fonsToOutline (FONScontext* stash, dchar dch, NVGPathOutline.DataStore* ol) nothrow @trusted @nogc {
|
||||||
if (stash is null || ol is null) return false;
|
if (stash is null || ol is null) return false;
|
||||||
static if (is(typeof(&fons__nvg__toOutline))) {
|
static if (is(typeof(&fons__nvg__toOutline))) {
|
||||||
FONSstate* state = fons__getState(stash);
|
FONSstate* state = fons__getState(stash);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue