mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 14:38:13 +02:00
Add dashes, collapse stroke_style/fill_style into gstate
This commit is contained in:
parent
ba6c497130
commit
20f631ce22
10 changed files with 172 additions and 68 deletions
3
Xr.h
3
Xr.h
|
|
@ -127,6 +127,9 @@ typedef enum _XrLineJoin { XrLineJoinMiter, XrLineJoinRound, XrLineJoinBevel } X
|
|||
void
|
||||
XrSetLineJoin(XrState *xrs, XrLineJoin line_join);
|
||||
|
||||
void
|
||||
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset);
|
||||
|
||||
void
|
||||
XrSetMiterLimit(XrState *xrs, double limit);
|
||||
|
||||
|
|
|
|||
3
src/Xr.h
3
src/Xr.h
|
|
@ -127,6 +127,9 @@ typedef enum _XrLineJoin { XrLineJoinMiter, XrLineJoinRound, XrLineJoinBevel } X
|
|||
void
|
||||
XrSetLineJoin(XrState *xrs, XrLineJoin line_join);
|
||||
|
||||
void
|
||||
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset);
|
||||
|
||||
void
|
||||
XrSetMiterLimit(XrState *xrs, double limit);
|
||||
|
||||
|
|
|
|||
9
src/xr.c
9
src/xr.c
|
|
@ -107,6 +107,15 @@ XrSetLineJoin(XrState *xrs, XrLineJoin line_join)
|
|||
XrGStateSetLineJoin(CURRENT_GSTATE(xrs), line_join);
|
||||
}
|
||||
|
||||
void
|
||||
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset)
|
||||
{
|
||||
XrError err;
|
||||
err = XrGStateSetDash(CURRENT_GSTATE(xrs), dashes, ndash, offset);
|
||||
if (err)
|
||||
xrs->error = err;
|
||||
}
|
||||
|
||||
void
|
||||
XrSetMiterLimit(XrState *xrs, double limit)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,12 +49,15 @@ XrGStateInit(XrGState *gstate, Display *dpy)
|
|||
|
||||
gstate->operator = XR_GSTATE_OPERATOR_DEFAULT;
|
||||
|
||||
gstate->fill_style.winding = XR_GSTATE_WINDING_DEFAULT;
|
||||
gstate->winding = XR_GSTATE_WINDING_DEFAULT;
|
||||
|
||||
gstate->stroke_style.line_width = XR_GSTATE_LINE_WIDTH_DEFAULT;
|
||||
gstate->stroke_style.line_cap = XR_GSTATE_LINE_CAP_DEFAULT;
|
||||
gstate->stroke_style.line_join = XR_GSTATE_LINE_JOIN_DEFAULT;
|
||||
gstate->stroke_style.miter_limit = XR_GSTATE_MITER_LIMIT_DEFAULT;
|
||||
gstate->line_width = XR_GSTATE_LINE_WIDTH_DEFAULT;
|
||||
gstate->line_cap = XR_GSTATE_LINE_CAP_DEFAULT;
|
||||
gstate->line_join = XR_GSTATE_LINE_JOIN_DEFAULT;
|
||||
gstate->miter_limit = XR_GSTATE_MITER_LIMIT_DEFAULT;
|
||||
gstate->dashes = 0;
|
||||
gstate->ndashes = 0;
|
||||
gstate->dash_offset = 0.0;
|
||||
|
||||
gstate->solidFormat = XcFindStandardFormat(dpy, PictStandardARGB32);
|
||||
gstate->alphaFormat = XcFindStandardFormat(dpy, PictStandardA8);
|
||||
|
|
@ -74,12 +77,27 @@ XrGStateInit(XrGState *gstate, Display *dpy)
|
|||
XrError
|
||||
XrGStateInitCopy(XrGState *gstate, XrGState *other)
|
||||
{
|
||||
XrError err;
|
||||
|
||||
*gstate = *other;
|
||||
if (other->dashes) {
|
||||
gstate->dashes = malloc (other->ndashes * sizeof (double));
|
||||
if (gstate->dashes == NULL)
|
||||
return XrErrorNoMemory;
|
||||
memcpy (gstate->dashes, other->dashes, other->ndashes * sizeof (double));
|
||||
}
|
||||
|
||||
XrSurfaceInit(&gstate->src, gstate->dpy);
|
||||
XrSurfaceSetSolidColor(&gstate->src, &gstate->color, gstate->solidFormat);
|
||||
|
||||
return XrPathInitCopy(&gstate->path, &other->path);
|
||||
err = XrPathInitCopy(&gstate->path, &other->path);
|
||||
if (err) {
|
||||
if (gstate->dashes) {
|
||||
free (gstate->dashes);
|
||||
gstate->dashes = 0;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -92,6 +110,8 @@ XrGStateDeinit(XrGState *gstate)
|
|||
XrTransformDeinit(&gstate->ctm_inverse);
|
||||
|
||||
XrPathDeinit(&gstate->path);
|
||||
if (gstate->dashes)
|
||||
free (gstate->dashes);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -160,25 +180,45 @@ XrGStateSetAlpha(XrGState *gstate, double alpha)
|
|||
void
|
||||
XrGStateSetLineWidth(XrGState *gstate, double width)
|
||||
{
|
||||
gstate->stroke_style.line_width = width;
|
||||
gstate->line_width = width;
|
||||
}
|
||||
|
||||
void
|
||||
XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap)
|
||||
{
|
||||
gstate->stroke_style.line_cap = line_cap;
|
||||
gstate->line_cap = line_cap;
|
||||
}
|
||||
|
||||
void
|
||||
XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join)
|
||||
{
|
||||
gstate->stroke_style.line_join = line_join;
|
||||
gstate->line_join = line_join;
|
||||
}
|
||||
|
||||
XrError
|
||||
XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset)
|
||||
{
|
||||
double *ndashes;
|
||||
|
||||
if (gstate->dashes) {
|
||||
free (gstate->dashes);
|
||||
}
|
||||
|
||||
gstate->dashes = malloc (ndash * sizeof (double));
|
||||
if (!gstate->dashes) {
|
||||
gstate->ndashes = 0;
|
||||
return XrErrorNoMemory;
|
||||
}
|
||||
gstate->ndashes = ndash;
|
||||
memcpy (gstate->dashes, dashes, ndash * sizeof (double));
|
||||
gstate->dash_offset = offset;
|
||||
return XrErrorSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
XrGStateSetMiterLimit(XrGState *gstate, double limit)
|
||||
{
|
||||
gstate->stroke_style.miter_limit = limit;
|
||||
gstate->miter_limit = limit;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -332,7 +372,7 @@ XrGStateFill(XrGState *gstate)
|
|||
|
||||
XrTrapsInit(&traps);
|
||||
|
||||
err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->fill_style.winding);
|
||||
err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->winding);
|
||||
if (err) {
|
||||
XrTrapsDeinit(&traps);
|
||||
return err;
|
||||
|
|
|
|||
27
src/xrint.h
27
src/xrint.h
|
|
@ -154,22 +154,20 @@ typedef struct _XrTraps {
|
|||
#define XR_GSTATE_LINE_JOIN_DEFAULT XrLineJoinMiter
|
||||
#define XR_GSTATE_MITER_LIMIT_DEFAULT 10.0
|
||||
|
||||
typedef struct _XrStrokeStyle {
|
||||
double line_width;
|
||||
XrLineCap line_cap;
|
||||
XrLineJoin line_join;
|
||||
double miter_limit;
|
||||
} XrStrokeStyle;
|
||||
|
||||
typedef struct _XrFillStyle {
|
||||
int winding;
|
||||
} XrFillStyle;
|
||||
|
||||
typedef struct _XrGState {
|
||||
Display *dpy;
|
||||
|
||||
XrStrokeStyle stroke_style;
|
||||
XrFillStyle fill_style;
|
||||
/* stroke style */
|
||||
double line_width;
|
||||
XrLineCap line_cap;
|
||||
XrLineJoin line_join;
|
||||
double *dashes;
|
||||
int ndashes;
|
||||
double dash_offset;
|
||||
double miter_limit;
|
||||
|
||||
/* fill style */
|
||||
int winding;
|
||||
|
||||
XrOperator operator;
|
||||
|
||||
|
|
@ -277,6 +275,9 @@ XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap);
|
|||
void
|
||||
XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join);
|
||||
|
||||
XrError
|
||||
XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset);
|
||||
|
||||
void
|
||||
XrGStateSetMiterLimit(XrGState *gstate, double limit);
|
||||
|
||||
|
|
|
|||
|
|
@ -89,12 +89,12 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out)
|
|||
outpt = &out->ccw;
|
||||
}
|
||||
XrPolygonInit (&polygon);
|
||||
switch (gstate->stroke_style.line_join) {
|
||||
switch (gstate->line_join) {
|
||||
case XrLineJoinRound: {
|
||||
}
|
||||
case XrLineJoinMiter: {
|
||||
XDouble c = in->vector.x * out->vector.x + in->vector.y * out->vector.y;
|
||||
double ml = gstate->stroke_style.miter_limit;
|
||||
double ml = gstate->miter_limit;
|
||||
if (2 <= ml * ml * (1 - c))
|
||||
{
|
||||
XDouble x1, y1, x2, y2;
|
||||
|
|
@ -155,11 +155,11 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
|
|||
XrGState *gstate = stroker->gstate;
|
||||
XrPolygon polygon;
|
||||
|
||||
if (gstate->stroke_style.line_cap == XrLineCapButt)
|
||||
if (gstate->line_cap == XrLineCapButt)
|
||||
return XrErrorSuccess;
|
||||
|
||||
XrPolygonInit (&polygon);
|
||||
switch (gstate->stroke_style.line_cap) {
|
||||
switch (gstate->line_cap) {
|
||||
case XrLineCapRound: {
|
||||
break;
|
||||
}
|
||||
|
|
@ -167,8 +167,8 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
|
|||
XPointDouble vector = f->vector;
|
||||
XPointFixed fvector;
|
||||
XPointFixed outer, occw, ocw;
|
||||
vector.x *= gstate->stroke_style.line_width / 2.0;
|
||||
vector.y *= gstate->stroke_style.line_width / 2.0;
|
||||
vector.x *= gstate->line_width / 2.0;
|
||||
vector.y *= gstate->line_width / 2.0;
|
||||
XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
|
||||
fvector.x = XDoubleToFixed(vector.x);
|
||||
fvector.y = XDoubleToFixed(vector.y);
|
||||
|
|
@ -200,14 +200,13 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
|
|||
XrError err;
|
||||
XrStroker *stroker = closure;
|
||||
XrGState *gstate = stroker->gstate;
|
||||
XrStrokeStyle *style = &gstate->stroke_style;
|
||||
XrTraps *traps = stroker->traps;
|
||||
double mag, tmp;
|
||||
XPointDouble vector;
|
||||
XPointDouble user_vector;
|
||||
XPointFixed offset_ccw, offset_cw;
|
||||
XPointFixed quad[4];
|
||||
XrStrokeFace face;
|
||||
XrStrokeFace face;
|
||||
|
||||
vector.x = XFixedToDouble(p2->x - p1->x);
|
||||
vector.y = XFixedToDouble(p2->y - p1->y);
|
||||
|
|
@ -225,8 +224,8 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
|
|||
user_vector = vector;
|
||||
|
||||
tmp = vector.x;
|
||||
vector.x = - vector.y * (style->line_width / 2.0);
|
||||
vector.y = tmp * (style->line_width / 2.0);
|
||||
vector.x = - vector.y * (gstate->line_width / 2.0);
|
||||
vector.y = tmp * (gstate->line_width / 2.0);
|
||||
|
||||
XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
|
||||
|
||||
|
|
|
|||
9
xr.c
9
xr.c
|
|
@ -107,6 +107,15 @@ XrSetLineJoin(XrState *xrs, XrLineJoin line_join)
|
|||
XrGStateSetLineJoin(CURRENT_GSTATE(xrs), line_join);
|
||||
}
|
||||
|
||||
void
|
||||
XrSetDash(XrState *xrs, double *dashes, int ndash, double offset)
|
||||
{
|
||||
XrError err;
|
||||
err = XrGStateSetDash(CURRENT_GSTATE(xrs), dashes, ndash, offset);
|
||||
if (err)
|
||||
xrs->error = err;
|
||||
}
|
||||
|
||||
void
|
||||
XrSetMiterLimit(XrState *xrs, double limit)
|
||||
{
|
||||
|
|
|
|||
62
xrgstate.c
62
xrgstate.c
|
|
@ -49,12 +49,15 @@ XrGStateInit(XrGState *gstate, Display *dpy)
|
|||
|
||||
gstate->operator = XR_GSTATE_OPERATOR_DEFAULT;
|
||||
|
||||
gstate->fill_style.winding = XR_GSTATE_WINDING_DEFAULT;
|
||||
gstate->winding = XR_GSTATE_WINDING_DEFAULT;
|
||||
|
||||
gstate->stroke_style.line_width = XR_GSTATE_LINE_WIDTH_DEFAULT;
|
||||
gstate->stroke_style.line_cap = XR_GSTATE_LINE_CAP_DEFAULT;
|
||||
gstate->stroke_style.line_join = XR_GSTATE_LINE_JOIN_DEFAULT;
|
||||
gstate->stroke_style.miter_limit = XR_GSTATE_MITER_LIMIT_DEFAULT;
|
||||
gstate->line_width = XR_GSTATE_LINE_WIDTH_DEFAULT;
|
||||
gstate->line_cap = XR_GSTATE_LINE_CAP_DEFAULT;
|
||||
gstate->line_join = XR_GSTATE_LINE_JOIN_DEFAULT;
|
||||
gstate->miter_limit = XR_GSTATE_MITER_LIMIT_DEFAULT;
|
||||
gstate->dashes = 0;
|
||||
gstate->ndashes = 0;
|
||||
gstate->dash_offset = 0.0;
|
||||
|
||||
gstate->solidFormat = XcFindStandardFormat(dpy, PictStandardARGB32);
|
||||
gstate->alphaFormat = XcFindStandardFormat(dpy, PictStandardA8);
|
||||
|
|
@ -74,12 +77,27 @@ XrGStateInit(XrGState *gstate, Display *dpy)
|
|||
XrError
|
||||
XrGStateInitCopy(XrGState *gstate, XrGState *other)
|
||||
{
|
||||
XrError err;
|
||||
|
||||
*gstate = *other;
|
||||
if (other->dashes) {
|
||||
gstate->dashes = malloc (other->ndashes * sizeof (double));
|
||||
if (gstate->dashes == NULL)
|
||||
return XrErrorNoMemory;
|
||||
memcpy (gstate->dashes, other->dashes, other->ndashes * sizeof (double));
|
||||
}
|
||||
|
||||
XrSurfaceInit(&gstate->src, gstate->dpy);
|
||||
XrSurfaceSetSolidColor(&gstate->src, &gstate->color, gstate->solidFormat);
|
||||
|
||||
return XrPathInitCopy(&gstate->path, &other->path);
|
||||
err = XrPathInitCopy(&gstate->path, &other->path);
|
||||
if (err) {
|
||||
if (gstate->dashes) {
|
||||
free (gstate->dashes);
|
||||
gstate->dashes = 0;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -92,6 +110,8 @@ XrGStateDeinit(XrGState *gstate)
|
|||
XrTransformDeinit(&gstate->ctm_inverse);
|
||||
|
||||
XrPathDeinit(&gstate->path);
|
||||
if (gstate->dashes)
|
||||
free (gstate->dashes);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -160,25 +180,45 @@ XrGStateSetAlpha(XrGState *gstate, double alpha)
|
|||
void
|
||||
XrGStateSetLineWidth(XrGState *gstate, double width)
|
||||
{
|
||||
gstate->stroke_style.line_width = width;
|
||||
gstate->line_width = width;
|
||||
}
|
||||
|
||||
void
|
||||
XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap)
|
||||
{
|
||||
gstate->stroke_style.line_cap = line_cap;
|
||||
gstate->line_cap = line_cap;
|
||||
}
|
||||
|
||||
void
|
||||
XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join)
|
||||
{
|
||||
gstate->stroke_style.line_join = line_join;
|
||||
gstate->line_join = line_join;
|
||||
}
|
||||
|
||||
XrError
|
||||
XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset)
|
||||
{
|
||||
double *ndashes;
|
||||
|
||||
if (gstate->dashes) {
|
||||
free (gstate->dashes);
|
||||
}
|
||||
|
||||
gstate->dashes = malloc (ndash * sizeof (double));
|
||||
if (!gstate->dashes) {
|
||||
gstate->ndashes = 0;
|
||||
return XrErrorNoMemory;
|
||||
}
|
||||
gstate->ndashes = ndash;
|
||||
memcpy (gstate->dashes, dashes, ndash * sizeof (double));
|
||||
gstate->dash_offset = offset;
|
||||
return XrErrorSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
XrGStateSetMiterLimit(XrGState *gstate, double limit)
|
||||
{
|
||||
gstate->stroke_style.miter_limit = limit;
|
||||
gstate->miter_limit = limit;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -332,7 +372,7 @@ XrGStateFill(XrGState *gstate)
|
|||
|
||||
XrTrapsInit(&traps);
|
||||
|
||||
err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->fill_style.winding);
|
||||
err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->winding);
|
||||
if (err) {
|
||||
XrTrapsDeinit(&traps);
|
||||
return err;
|
||||
|
|
|
|||
27
xrint.h
27
xrint.h
|
|
@ -154,22 +154,20 @@ typedef struct _XrTraps {
|
|||
#define XR_GSTATE_LINE_JOIN_DEFAULT XrLineJoinMiter
|
||||
#define XR_GSTATE_MITER_LIMIT_DEFAULT 10.0
|
||||
|
||||
typedef struct _XrStrokeStyle {
|
||||
double line_width;
|
||||
XrLineCap line_cap;
|
||||
XrLineJoin line_join;
|
||||
double miter_limit;
|
||||
} XrStrokeStyle;
|
||||
|
||||
typedef struct _XrFillStyle {
|
||||
int winding;
|
||||
} XrFillStyle;
|
||||
|
||||
typedef struct _XrGState {
|
||||
Display *dpy;
|
||||
|
||||
XrStrokeStyle stroke_style;
|
||||
XrFillStyle fill_style;
|
||||
/* stroke style */
|
||||
double line_width;
|
||||
XrLineCap line_cap;
|
||||
XrLineJoin line_join;
|
||||
double *dashes;
|
||||
int ndashes;
|
||||
double dash_offset;
|
||||
double miter_limit;
|
||||
|
||||
/* fill style */
|
||||
int winding;
|
||||
|
||||
XrOperator operator;
|
||||
|
||||
|
|
@ -277,6 +275,9 @@ XrGStateSetLineCap(XrGState *gstate, XrLineCap line_cap);
|
|||
void
|
||||
XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join);
|
||||
|
||||
XrError
|
||||
XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset);
|
||||
|
||||
void
|
||||
XrGStateSetMiterLimit(XrGState *gstate, double limit);
|
||||
|
||||
|
|
|
|||
19
xrstroker.c
19
xrstroker.c
|
|
@ -89,12 +89,12 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out)
|
|||
outpt = &out->ccw;
|
||||
}
|
||||
XrPolygonInit (&polygon);
|
||||
switch (gstate->stroke_style.line_join) {
|
||||
switch (gstate->line_join) {
|
||||
case XrLineJoinRound: {
|
||||
}
|
||||
case XrLineJoinMiter: {
|
||||
XDouble c = in->vector.x * out->vector.x + in->vector.y * out->vector.y;
|
||||
double ml = gstate->stroke_style.miter_limit;
|
||||
double ml = gstate->miter_limit;
|
||||
if (2 <= ml * ml * (1 - c))
|
||||
{
|
||||
XDouble x1, y1, x2, y2;
|
||||
|
|
@ -155,11 +155,11 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
|
|||
XrGState *gstate = stroker->gstate;
|
||||
XrPolygon polygon;
|
||||
|
||||
if (gstate->stroke_style.line_cap == XrLineCapButt)
|
||||
if (gstate->line_cap == XrLineCapButt)
|
||||
return XrErrorSuccess;
|
||||
|
||||
XrPolygonInit (&polygon);
|
||||
switch (gstate->stroke_style.line_cap) {
|
||||
switch (gstate->line_cap) {
|
||||
case XrLineCapRound: {
|
||||
break;
|
||||
}
|
||||
|
|
@ -167,8 +167,8 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f)
|
|||
XPointDouble vector = f->vector;
|
||||
XPointFixed fvector;
|
||||
XPointFixed outer, occw, ocw;
|
||||
vector.x *= gstate->stroke_style.line_width / 2.0;
|
||||
vector.y *= gstate->stroke_style.line_width / 2.0;
|
||||
vector.x *= gstate->line_width / 2.0;
|
||||
vector.y *= gstate->line_width / 2.0;
|
||||
XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
|
||||
fvector.x = XDoubleToFixed(vector.x);
|
||||
fvector.y = XDoubleToFixed(vector.y);
|
||||
|
|
@ -200,14 +200,13 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
|
|||
XrError err;
|
||||
XrStroker *stroker = closure;
|
||||
XrGState *gstate = stroker->gstate;
|
||||
XrStrokeStyle *style = &gstate->stroke_style;
|
||||
XrTraps *traps = stroker->traps;
|
||||
double mag, tmp;
|
||||
XPointDouble vector;
|
||||
XPointDouble user_vector;
|
||||
XPointFixed offset_ccw, offset_cw;
|
||||
XPointFixed quad[4];
|
||||
XrStrokeFace face;
|
||||
XrStrokeFace face;
|
||||
|
||||
vector.x = XFixedToDouble(p2->x - p1->x);
|
||||
vector.y = XFixedToDouble(p2->y - p1->y);
|
||||
|
|
@ -225,8 +224,8 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
|
|||
user_vector = vector;
|
||||
|
||||
tmp = vector.x;
|
||||
vector.x = - vector.y * (style->line_width / 2.0);
|
||||
vector.y = tmp * (style->line_width / 2.0);
|
||||
vector.x = - vector.y * (gstate->line_width / 2.0);
|
||||
vector.y = tmp * (gstate->line_width / 2.0);
|
||||
|
||||
XrTransformPointWithoutTranslate(&gstate->ctm, &vector);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue