Improves the implementation of global composite operation.
This commit updates the implmentation of global composite operation to follow the advices described at c4b865796d (r74248556)
This commit is contained in:
parent
c4b865796d
commit
1bf25e6f67
127
src/nanovg.c
127
src/nanovg.c
@ -66,6 +66,7 @@ enum NVGpointFlags
|
||||
};
|
||||
|
||||
struct NVGstate {
|
||||
NVGcompositeOperationState compositeOperation;
|
||||
NVGpaint fill;
|
||||
NVGpaint stroke;
|
||||
float strokeWidth;
|
||||
@ -203,6 +204,79 @@ static void nvg__setDevicePixelRatio(NVGcontext* ctx, float ratio)
|
||||
ctx->devicePxRatio = ratio;
|
||||
}
|
||||
|
||||
static NVGcompositeOperationState nvg__compositeOperationState(int op)
|
||||
{
|
||||
int sfactor, dfactor;
|
||||
|
||||
if (op == NVG_SOURCE_OVER)
|
||||
{
|
||||
sfactor = NVG_ONE;
|
||||
dfactor = NVG_ONE_MINUS_SRC_ALPHA;
|
||||
}
|
||||
else if (op == NVG_SOURCE_IN)
|
||||
{
|
||||
sfactor = NVG_DST_ALPHA;
|
||||
dfactor = NVG_ZERO;
|
||||
}
|
||||
else if (op == NVG_SOURCE_OUT)
|
||||
{
|
||||
sfactor = NVG_ONE_MINUS_DST_ALPHA;
|
||||
dfactor = NVG_ZERO;
|
||||
}
|
||||
else if (op == NVG_ATOP)
|
||||
{
|
||||
sfactor = NVG_DST_ALPHA;
|
||||
dfactor = NVG_ONE_MINUS_SRC_ALPHA;
|
||||
}
|
||||
else if (op == NVG_DESTINATION_OVER)
|
||||
{
|
||||
sfactor = NVG_ONE_MINUS_DST_ALPHA;
|
||||
dfactor = NVG_ONE;
|
||||
}
|
||||
else if (op == NVG_DESTINATION_IN)
|
||||
{
|
||||
sfactor = NVG_ZERO;
|
||||
dfactor = NVG_SRC_ALPHA;
|
||||
}
|
||||
else if (op == NVG_DESTINATION_OUT)
|
||||
{
|
||||
sfactor = NVG_ZERO;
|
||||
dfactor = NVG_ONE_MINUS_SRC_ALPHA;
|
||||
}
|
||||
else if (op == NVG_DESTINATION_ATOP)
|
||||
{
|
||||
sfactor = NVG_ONE_MINUS_DST_ALPHA;
|
||||
dfactor = NVG_SRC_ALPHA;
|
||||
}
|
||||
else if (op == NVG_LIGHTER)
|
||||
{
|
||||
sfactor = NVG_ONE;
|
||||
dfactor = NVG_ONE;
|
||||
}
|
||||
else if (op == NVG_COPY)
|
||||
{
|
||||
sfactor = NVG_ONE;
|
||||
dfactor = NVG_ZERO;
|
||||
}
|
||||
else if (op == NVG_XOR)
|
||||
{
|
||||
sfactor = NVG_ONE_MINUS_DST_ALPHA;
|
||||
dfactor = NVG_ONE_MINUS_SRC_ALPHA;
|
||||
}
|
||||
|
||||
NVGcompositeOperationState state;
|
||||
state.srcRGB = sfactor;
|
||||
state.dstRGB = dfactor;
|
||||
state.srcAlpha = sfactor;
|
||||
state.dstAlpha = dfactor;
|
||||
return state;
|
||||
}
|
||||
|
||||
static NVGstate* nvg__getState(NVGcontext* ctx)
|
||||
{
|
||||
return &ctx->states[ctx->nstates-1];
|
||||
}
|
||||
|
||||
NVGcontext* nvgCreateInternal(NVGparams* params)
|
||||
{
|
||||
FONSparams fontParams;
|
||||
@ -310,7 +384,8 @@ void nvgCancelFrame(NVGcontext* ctx)
|
||||
|
||||
void nvgEndFrame(NVGcontext* ctx)
|
||||
{
|
||||
ctx->params.renderFlush(ctx->params.userPtr);
|
||||
NVGstate* state = nvg__getState(ctx);
|
||||
ctx->params.renderFlush(ctx->params.userPtr, state->compositeOperation);
|
||||
if (ctx->fontImageIdx != 0) {
|
||||
int fontImage = ctx->fontImages[ctx->fontImageIdx];
|
||||
int i, j, iw, ih;
|
||||
@ -338,25 +413,6 @@ void nvgEndFrame(NVGcontext* ctx)
|
||||
}
|
||||
}
|
||||
|
||||
NVGcompositeOperation nvgBlendFunc(int sfactor, int dfactor)
|
||||
{
|
||||
return nvgBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
|
||||
}
|
||||
|
||||
NVGcompositeOperation nvgBlendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha)
|
||||
{
|
||||
NVGcompositeOperation operation;
|
||||
operation.srcRGB = srcRGB;
|
||||
operation.dstRGB = dstRGB;
|
||||
operation.srcAlpha = srcAlpha;
|
||||
operation.dstAlpha = dstAlpha;
|
||||
return operation;
|
||||
}
|
||||
|
||||
void nvgGlobalCompositeOperation(NVGcontext* ctx, NVGcompositeOperation op) {
|
||||
ctx->params.renderCompositeOperation(ctx->params.userPtr, op);
|
||||
}
|
||||
|
||||
NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b)
|
||||
{
|
||||
return nvgRGBA(r,g,b,255);
|
||||
@ -452,12 +508,6 @@ NVGcolor nvgHSLA(float h, float s, float l, unsigned char a)
|
||||
return col;
|
||||
}
|
||||
|
||||
|
||||
static NVGstate* nvg__getState(NVGcontext* ctx)
|
||||
{
|
||||
return &ctx->states[ctx->nstates-1];
|
||||
}
|
||||
|
||||
void nvgTransformIdentity(float* t)
|
||||
{
|
||||
t[0] = 1.0f; t[1] = 0.0f;
|
||||
@ -590,6 +640,7 @@ void nvgReset(NVGcontext* ctx)
|
||||
|
||||
nvg__setPaintColor(&state->fill, nvgRGBA(255,255,255,255));
|
||||
nvg__setPaintColor(&state->stroke, nvgRGBA(0,0,0,255));
|
||||
state->compositeOperation = nvg__compositeOperationState(NVG_SOURCE_OVER);
|
||||
state->strokeWidth = 1.0f;
|
||||
state->miterLimit = 10.0f;
|
||||
state->lineCap = NVG_BUTT;
|
||||
@ -958,6 +1009,30 @@ void nvgResetScissor(NVGcontext* ctx)
|
||||
state->scissor.extent[1] = -1.0f;
|
||||
}
|
||||
|
||||
// Global composite operation.
|
||||
void nvgGlobalCompositeOperation(NVGcontext* ctx, int op)
|
||||
{
|
||||
NVGstate* state = nvg__getState(ctx);
|
||||
state->compositeOperation = nvg__compositeOperationState(op);
|
||||
}
|
||||
|
||||
void nvgGlobalCompositeBlendFunc(NVGcontext* ctx, int sfactor, int dfactor)
|
||||
{
|
||||
nvgGlobalCompositeBlendFuncSeparate(ctx, sfactor, dfactor, sfactor, dfactor);
|
||||
}
|
||||
|
||||
void nvgGlobalCompositeBlendFuncSeparate(NVGcontext* ctx, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha)
|
||||
{
|
||||
NVGcompositeOperationState op;
|
||||
op.srcRGB = srcRGB;
|
||||
op.dstRGB = dstRGB;
|
||||
op.srcAlpha = srcAlpha;
|
||||
op.dstAlpha = dstAlpha;
|
||||
|
||||
NVGstate* state = nvg__getState(ctx);
|
||||
state->compositeOperation = op;
|
||||
}
|
||||
|
||||
static int nvg__ptEquals(float x1, float y1, float x2, float y2, float tol)
|
||||
{
|
||||
float dx = x2 - x1;
|
||||
|
47
src/nanovg.h
47
src/nanovg.h
@ -97,26 +97,27 @@ enum NVGblendFactor {
|
||||
NVG_SRC_ALPHA_SATURATE = 1<<10,
|
||||
};
|
||||
|
||||
struct NVGcompositeOperation {
|
||||
struct NVGcompositeOperationState {
|
||||
int srcRGB;
|
||||
int dstRGB;
|
||||
int srcAlpha;
|
||||
int dstAlpha;
|
||||
};
|
||||
typedef struct NVGcompositeOperation NVGcompositeOperation;
|
||||
typedef struct NVGcompositeOperationState NVGcompositeOperationState;
|
||||
|
||||
// Predefined composite operations.
|
||||
#define NVG_SOURCE_OVER nvgBlendFunc(NVG_ONE, NVG_ONE_MINUS_SRC_ALPHA)
|
||||
#define NVG_SOURCE_IN nvgBlendFunc(NVG_DST_ALPHA, NVG_ZERO)
|
||||
#define NVG_SOURCE_OUT nvgBlendFunc(NVG_ONE_MINUS_DST_ALPHA, NVG_ZERO)
|
||||
#define NVG_ATOP nvgBlendFunc(NVG_DST_ALPHA, NVG_ONE_MINUS_SRC_ALPHA)
|
||||
#define NVG_DESTINATION_OVER nvgBlendFunc(NVG_ONE_MINUS_DST_ALPHA, NVG_ONE)
|
||||
#define NVG_DESTINATION_IN nvgBlendFunc(NVG_ZERO, NVG_SRC_ALPHA)
|
||||
#define NVG_DESTINATION_OUT nvgBlendFunc(NVG_ZERO, NVG_ONE_MINUS_SRC_ALPHA)
|
||||
#define NVG_DESTINATION_ATOP nvgBlendFunc(NVG_ONE_MINUS_DST_ALPHA, NVG_SRC_ALPHA)
|
||||
#define NVG_LIGHTER nvgBlendFunc(NVG_ONE, NVG_ONE)
|
||||
#define NVG_COPY nvgBlendFunc(NVG_ONE, NVG_ZERO)
|
||||
#define NVG_XOR nvgBlendFunc(NVG_ONE_MINUS_DST_ALPHA NVG_ONE_MINUS_SRC_ALPHA)
|
||||
enum NVGcompositeOperation {
|
||||
NVG_SOURCE_OVER,
|
||||
NVG_SOURCE_IN,
|
||||
NVG_SOURCE_OUT,
|
||||
NVG_ATOP,
|
||||
NVG_DESTINATION_OVER,
|
||||
NVG_DESTINATION_IN,
|
||||
NVG_DESTINATION_OUT,
|
||||
NVG_DESTINATION_ATOP,
|
||||
NVG_LIGHTER,
|
||||
NVG_COPY,
|
||||
NVG_XOR,
|
||||
};
|
||||
|
||||
struct NVGglyphPosition {
|
||||
const char* str; // Position of the glyph in the input string.
|
||||
@ -162,17 +163,16 @@ void nvgEndFrame(NVGcontext* ctx);
|
||||
// Composite operation
|
||||
//
|
||||
// Composite operation in NanoVG works between frames. The default composite
|
||||
// operation of NanoVG is NVG_SOURCE_OVER, and the value is reset whenever
|
||||
// calling nvgBeginFrame().
|
||||
// operation of NanoVG is NVG_SOURCE_OVER.
|
||||
|
||||
// Creates a composite operation with custom pixel arithmetic. The parameters should be one of NVGblendFactor.
|
||||
NVGcompositeOperation nvgBlendFunc(int sfactor, int dfactor);
|
||||
// Sets the composite operation. The op parameter should be one of NVGcompositeOperation.
|
||||
void nvgGlobalCompositeOperation(NVGcontext* ctx, int op);
|
||||
|
||||
// Creates a composite operation with custom pixel arithmetic for RGB and alpha components separately. The parameters should be one of NVGblendFactor.
|
||||
NVGcompositeOperation nvgBlendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha);
|
||||
// Sets the composite operation with custom pixel arithmetic. The parameters should be one of NVGblendFactor.
|
||||
void nvgGlobalCompositeBlendFunc(NVGcontext* ctx, int sfactor, int dfactor);
|
||||
|
||||
// Sets the composite operation for the current frame. This function should be called between nvgBeginFrame() and nvgEndFrame(). The default composite operation of NanoVG is NVG_SOURCE_OVER.
|
||||
void nvgGlobalCompositeOperation(NVGcontext* ctx, NVGcompositeOperation op);
|
||||
// Sets the composite operation with custom pixel arithmetic for RGB and alpha components separately. The parameters should be one of NVGblendFactor.
|
||||
void nvgGlobalCompositeBlendFuncSeparate(NVGcontext* ctx, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha);
|
||||
|
||||
//
|
||||
// Color utils
|
||||
@ -641,8 +641,7 @@ struct NVGparams {
|
||||
int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h);
|
||||
void (*renderViewport)(void* uptr, int width, int height, float devicePixelRatio);
|
||||
void (*renderCancel)(void* uptr);
|
||||
void (*renderCompositeOperation)(void* uptr, NVGcompositeOperation op);
|
||||
void (*renderFlush)(void* uptr);
|
||||
void (*renderFlush)(void* uptr, NVGcompositeOperationState compositeOperation);
|
||||
void (*renderFill)(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);
|
||||
void (*renderStroke)(void* uptr, NVGpaint* paint, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);
|
||||
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGscissor* scissor, const NVGvertex* verts, int nverts);
|
||||
|
@ -219,7 +219,6 @@ struct GLNVGfragUniforms {
|
||||
typedef struct GLNVGfragUniforms GLNVGfragUniforms;
|
||||
|
||||
struct GLNVGcontext {
|
||||
NVGcompositeOperation compositeOperation;
|
||||
GLNVGshader shader;
|
||||
GLNVGtexture* textures;
|
||||
float view[2];
|
||||
@ -945,7 +944,6 @@ static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image)
|
||||
static void glnvg__renderViewport(void* uptr, int width, int height, float devicePixelRatio)
|
||||
{
|
||||
GLNVGcontext* gl = (GLNVGcontext*)uptr;
|
||||
gl->compositeOperation = NVG_SOURCE_OVER; // resets composition
|
||||
gl->view[0] = (float)width;
|
||||
gl->view[1] = (float)height;
|
||||
}
|
||||
@ -1100,18 +1098,12 @@ static GLenum glnvg_convertBlendFuncFactor(int factor)
|
||||
return GL_SRC_ALPHA_SATURATE;
|
||||
}
|
||||
|
||||
static void glnvg__blendCompositeOperation(NVGcompositeOperation operation)
|
||||
static void glnvg__blendCompositeOperation(NVGcompositeOperationState op)
|
||||
{
|
||||
glBlendFuncSeparate(glnvg_convertBlendFuncFactor(operation.srcRGB), glnvg_convertBlendFuncFactor(operation.dstRGB), glnvg_convertBlendFuncFactor(operation.srcAlpha), glnvg_convertBlendFuncFactor(operation.dstAlpha));
|
||||
glBlendFuncSeparate(glnvg_convertBlendFuncFactor(op.srcRGB), glnvg_convertBlendFuncFactor(op.dstRGB), glnvg_convertBlendFuncFactor(op.srcAlpha), glnvg_convertBlendFuncFactor(op.dstAlpha));
|
||||
}
|
||||
|
||||
static void glnvg__renderCompositeOperation(void* uptr, NVGcompositeOperation op)
|
||||
{
|
||||
GLNVGcontext* gl = (GLNVGcontext*)uptr;
|
||||
gl->compositeOperation = op;
|
||||
}
|
||||
|
||||
static void glnvg__renderFlush(void* uptr)
|
||||
static void glnvg__renderFlush(void* uptr, NVGcompositeOperationState compositeOperation)
|
||||
{
|
||||
GLNVGcontext* gl = (GLNVGcontext*)uptr;
|
||||
int i;
|
||||
@ -1121,7 +1113,7 @@ static void glnvg__renderFlush(void* uptr)
|
||||
// Setup require GL state.
|
||||
glUseProgram(gl->shader.prog);
|
||||
|
||||
glnvg__blendCompositeOperation(gl->compositeOperation);
|
||||
glnvg__blendCompositeOperation(compositeOperation);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CCW);
|
||||
@ -1512,7 +1504,6 @@ NVGcontext* nvgCreateGLES3(int flags)
|
||||
params.renderGetTextureSize = glnvg__renderGetTextureSize;
|
||||
params.renderViewport = glnvg__renderViewport;
|
||||
params.renderCancel = glnvg__renderCancel;
|
||||
params.renderCompositeOperation = glnvg__renderCompositeOperation;
|
||||
params.renderFlush = glnvg__renderFlush;
|
||||
params.renderFill = glnvg__renderFill;
|
||||
params.renderStroke = glnvg__renderStroke;
|
||||
|
Loading…
x
Reference in New Issue
Block a user