- added function to allow to combine scissor rects using intersectionshared-context
@@ -1017,6 +1017,42 @@ void drawCaps(NVGcontext* vg, float x, float y, float width) | |||||
nvgRestore(vg); | nvgRestore(vg); | ||||
} | } | ||||
void drawScissor(NVGcontext* vg, float x, float y, float t) | |||||
{ | |||||
nvgSave(vg); | |||||
// Draw first rect and set scissor to it's area. | |||||
nvgTranslate(vg, x, y); | |||||
nvgRotate(vg, nvgDegToRad(5)); | |||||
nvgBeginPath(vg); | |||||
nvgRect(vg, -20,-20,60,40); | |||||
nvgFillColor(vg, nvgRGBA(255,0,0,255)); | |||||
nvgFill(vg); | |||||
nvgScissor(vg, -20,-20,60,40); | |||||
// Draw second rectangle with offset and rotation. | |||||
nvgTranslate(vg, 40,0); | |||||
nvgRotate(vg, t); | |||||
// Draw the intended second rectangle without any scissoring. | |||||
nvgSave(vg); | |||||
nvgResetScissor(vg); | |||||
nvgBeginPath(vg); | |||||
nvgRect(vg, -20,-10,60,30); | |||||
nvgFillColor(vg, nvgRGBA(255,128,0,64)); | |||||
nvgFill(vg); | |||||
nvgRestore(vg); | |||||
// Draw second rectangle with combined scissoring. | |||||
nvgIntersectScissor(vg, -20,-10,60,30); | |||||
nvgBeginPath(vg); | |||||
nvgRect(vg, -20,-10,60,30); | |||||
nvgFillColor(vg, nvgRGBA(255,128,0,255)); | |||||
nvgFill(vg); | |||||
nvgRestore(vg); | |||||
} | |||||
void renderDemo(NVGcontext* vg, float mx, float my, float width, float height, | void renderDemo(NVGcontext* vg, float mx, float my, float width, float height, | ||||
float t, int blowup, DemoData* data) | float t, int blowup, DemoData* data) | ||||
{ | { | ||||
@@ -1028,7 +1064,7 @@ void renderDemo(NVGcontext* vg, float mx, float my, float width, float height, | |||||
drawColorwheel(vg, width - 300, height - 300, 250.0f, 250.0f, t); | drawColorwheel(vg, width - 300, height - 300, 250.0f, 250.0f, t); | ||||
// Line joints | // Line joints | ||||
drawLines(vg, 50, height-50, 600, 50, t); | |||||
drawLines(vg, 120, height-50, 600, 50, t); | |||||
// Line caps | // Line caps | ||||
drawWidths(vg, 10, 50, 30); | drawWidths(vg, 10, 50, 30); | ||||
@@ -1036,6 +1072,8 @@ void renderDemo(NVGcontext* vg, float mx, float my, float width, float height, | |||||
// Line caps | // Line caps | ||||
drawCaps(vg, 10, 300, 30); | drawCaps(vg, 10, 300, 30); | ||||
drawScissor(vg, 50, height-80, t); | |||||
nvgSave(vg); | nvgSave(vg); | ||||
if (blowup) { | if (blowup) { | ||||
nvgRotate(vg, sinf(t*0.3f)*5.0f/180.0f*NVG_PI); | nvgRotate(vg, sinf(t*0.3f)*5.0f/180.0f*NVG_PI); | ||||
@@ -881,6 +881,49 @@ void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h) | |||||
state->scissor.extent[1] = h*0.5f; | state->scissor.extent[1] = h*0.5f; | ||||
} | } | ||||
static void nvg__isectRects(float* dst, | |||||
float ax, float ay, float aw, float ah, | |||||
float bx, float by, float bw, float bh) | |||||
{ | |||||
float minx = nvg__maxf(ax, bx); | |||||
float miny = nvg__maxf(ay, by); | |||||
float maxx = nvg__minf(ax+aw, bx+bw); | |||||
float maxy = nvg__minf(ay+ah, by+bh); | |||||
dst[0] = minx; | |||||
dst[1] = miny; | |||||
dst[2] = nvg__maxf(0.0f, maxx - minx); | |||||
dst[3] = nvg__maxf(0.0f, maxy - miny); | |||||
} | |||||
void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h) | |||||
{ | |||||
NVGstate* state = nvg__getState(ctx); | |||||
float pxform[6], invxorm[6]; | |||||
float rect[4]; | |||||
float ex, ey, tex, tey; | |||||
// If no previous scissor has been set, set the scissor as current scissor. | |||||
if (state->scissor.extent[0] < 0) { | |||||
nvgScissor(ctx, x, y, w, h); | |||||
return; | |||||
} | |||||
// Transform the current scissor rect into current transform space. | |||||
// If there is difference in rotation, this will be approximation. | |||||
memcpy(pxform, state->scissor.xform, sizeof(float)*6); | |||||
ex = state->scissor.extent[0]; | |||||
ey = state->scissor.extent[1]; | |||||
nvgTransformInverse(invxorm, state->xform); | |||||
nvgTransformMultiply(pxform, invxorm); | |||||
tex = ex*nvg__absf(pxform[0]) + ey*nvg__absf(pxform[2]); | |||||
tey = ex*nvg__absf(pxform[1]) + ey*nvg__absf(pxform[3]); | |||||
// Intersect rects. | |||||
nvg__isectRects(rect, pxform[4]-tex,pxform[5]-tey,tex*2,tey*2, x,y,w,h); | |||||
nvgScissor(ctx, rect[0], rect[1], rect[2], rect[3]); | |||||
} | |||||
void nvgResetScissor(NVGcontext* ctx) | void nvgResetScissor(NVGcontext* ctx) | ||||
{ | { | ||||
NVGstate* state = nvg__getState(ctx); | NVGstate* state = nvg__getState(ctx); | ||||
@@ -370,10 +370,18 @@ NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey | |||||
// Scissoring allows you to clip the rendering into a rectangle. This is useful for varius | // Scissoring allows you to clip the rendering into a rectangle. This is useful for varius | ||||
// user interface cases like rendering a text edit or a timeline. | // user interface cases like rendering a text edit or a timeline. | ||||
// Sets the current | |||||
// Sets the current scissor rectangle. | |||||
// The scissor rectangle is transformed by the current transform. | // The scissor rectangle is transformed by the current transform. | ||||
void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h); | void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h); | ||||
// Intersects current scissor rectangle with the specified rectangle. | |||||
// The scissor rectangle is transformed by the current transform. | |||||
// Note: in case the rotation of previous scissor rect differs from | |||||
// the current one, the intersection will be done between the specified | |||||
// rectangle and the previous scissor rectangle transformed in the current | |||||
// transform space. The resulting shape is always rectangle. | |||||
void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h); | |||||
// Reset and disables scissoring. | // Reset and disables scissoring. | ||||
void nvgResetScissor(NVGcontext* ctx); | void nvgResetScissor(NVGcontext* ctx); | ||||