Browse Source

Added nvgIntersectScissor()

- added function to allow to combine scissor rects using intersection
shared-context
Mikko Mononen 10 years ago
parent
commit
14df146ea1
3 changed files with 91 additions and 2 deletions
  1. +39
    -1
      example/demo.c
  2. +43
    -0
      src/nanovg.c
  3. +9
    -1
      src/nanovg.h

+ 39
- 1
example/demo.c View File

@@ -1017,6 +1017,42 @@ void drawCaps(NVGcontext* vg, float x, float y, float width)
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,
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);

// Line joints
drawLines(vg, 50, height-50, 600, 50, t);
drawLines(vg, 120, height-50, 600, 50, t);

// Line caps
drawWidths(vg, 10, 50, 30);
@@ -1036,6 +1072,8 @@ void renderDemo(NVGcontext* vg, float mx, float my, float width, float height,
// Line caps
drawCaps(vg, 10, 300, 30);

drawScissor(vg, 50, height-80, t);

nvgSave(vg);
if (blowup) {
nvgRotate(vg, sinf(t*0.3f)*5.0f/180.0f*NVG_PI);


+ 43
- 0
src/nanovg.c View File

@@ -881,6 +881,49 @@ void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h)
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)
{
NVGstate* state = nvg__getState(ctx);


+ 9
- 1
src/nanovg.h View File

@@ -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
// 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.
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.
void nvgResetScissor(NVGcontext* ctx);



Loading…
Cancel
Save