Updates nanovg to support global composite operation. (#877)

This commit updates bgfx's NanoVG codebase to adapt the latest NanoVG commit since I've implemented blending support for the original NanoVG and there is no need of `nvgState()` anymore.
This commit is contained in:
Olli Wang 2016-08-11 11:15:31 +08:00 committed by Branimir Karadžić
parent 9f7386e53a
commit 1804ba77c1
4 changed files with 206 additions and 39 deletions

View File

@ -110,6 +110,7 @@ enum NVGpointFlags
};
struct NVGstate {
NVGcompositeOperationState compositeOperation;
NVGpaint fill;
NVGpaint stroke;
float strokeWidth;
@ -247,6 +248,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;
@ -354,7 +428,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;
@ -430,7 +505,7 @@ NVGcolor nvgLerpRGBA(NVGcolor c0, NVGcolor c1, float u)
{
int i;
float oneminu;
NVGcolor cint;
NVGcolor cint = {0};
u = nvg__clampf(u, 0.0f, 1.0f);
oneminu = 1.0f - u;
@ -477,12 +552,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;
@ -615,6 +684,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;
@ -983,6 +1053,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;

View File

@ -81,10 +81,46 @@ enum NVGalign {
// Vertical align
NVG_ALIGN_TOP = 1<<3, // Align text vertically to top.
NVG_ALIGN_MIDDLE = 1<<4, // Align text vertically to middle.
NVG_ALIGN_BOTTOM = 1<<5, // Align text vertically to bottom.
NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline.
NVG_ALIGN_BOTTOM = 1<<5, // Align text vertically to bottom.
NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline.
};
enum NVGblendFactor {
NVG_ZERO = 1<<0,
NVG_ONE = 1<<1,
NVG_SRC_COLOR = 1<<2,
NVG_ONE_MINUS_SRC_COLOR = 1<<3,
NVG_DST_COLOR = 1<<4,
NVG_ONE_MINUS_DST_COLOR = 1<<5,
NVG_SRC_ALPHA = 1<<6,
NVG_ONE_MINUS_SRC_ALPHA = 1<<7,
NVG_DST_ALPHA = 1<<8,
NVG_ONE_MINUS_DST_ALPHA = 1<<9,
NVG_SRC_ALPHA_SATURATE = 1<<10,
};
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 NVGcompositeOperationState {
int srcRGB;
int dstRGB;
int srcAlpha;
int dstAlpha;
};
typedef struct NVGcompositeOperationState NVGcompositeOperationState;
struct NVGglyphPosition {
const char* str; // Position of the glyph in the input string.
float x; // The x-coordinate of the logical glyph position.
@ -125,6 +161,22 @@ void nvgCancelFrame(NVGcontext* ctx);
// Ends drawing flushing remaining render state.
void nvgEndFrame(NVGcontext* ctx);
//
// Composite operation
//
// The composite operations in NanoVG are modeled after HTML Canvas API, and
// the blend func is based on OpenGL (see corresponding manuals for more info).
// The colors in the blending state have premultiplied alpha.
// Sets the composite operation. The op parameter should be one of NVGcompositeOperation.
void nvgGlobalCompositeOperation(NVGcontext* ctx, int op);
// 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 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
//
@ -185,7 +237,7 @@ void nvgReset(NVGcontext* ctx);
// Solid color is simply defined as a color value, different kinds of paints can be created
// using nvgLinearGradient(), nvgBoxGradient(), nvgRadialGradient() and nvgImagePattern().
//
// Current render style can be saved and restored using nvgSave() and nvgRestore().
// Current render style can be saved and restored using nvgSave() and nvgRestore().
// Sets current stroke style to a solid color.
void nvgStrokeColor(NVGcontext* ctx, NVGcolor color);
@ -215,7 +267,7 @@ void nvgLineCap(NVGcontext* ctx, int cap);
void nvgLineJoin(NVGcontext* ctx, int join);
// Sets the transparency applied to all rendered shapes.
// Alreade transparent paths will get proportionally more transparent as well.
// Already transparent paths will get proportionally more transparent as well.
void nvgGlobalAlpha(NVGcontext* ctx, float alpha);
//
@ -233,7 +285,7 @@ void nvgGlobalAlpha(NVGcontext* ctx, float alpha);
// Apart from nvgResetTransform(), each transformation function first creates
// specific transformation matrix and pre-multiplies the current transformation by it.
//
// Current coordinate system (transformation) can be saved and restored using nvgSave() and nvgRestore().
// Current coordinate system (transformation) can be saved and restored using nvgSave() and nvgRestore().
// Resets current transform to a identity matrix.
void nvgResetTransform(NVGcontext* ctx);
@ -347,7 +399,7 @@ NVGpaint nvgLinearGradient(NVGcontext* ctx, float sx, float sy, float ex, float
NVGcolor icol, NVGcolor ocol);
// Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
// drop shadows or hilights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
// drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
// (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry
// the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
@ -369,8 +421,8 @@ NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey
//
// Scissoring
//
// 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.
// Scissoring allows you to clip the rendering into a rectangle. This is useful for various
// user interface cases like rendering a text edit or a timeline.
// Sets the current scissor rectangle.
// The scissor rectangle is transformed by the current transform.
@ -425,7 +477,7 @@ void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float rad
// Closes current sub-path with a line segment.
void nvgClosePath(NVGcontext* ctx);
// Sets the current sub-path winding, see NVGwinding and NVGsolidity.
// Sets the current sub-path winding, see NVGwinding and NVGsolidity.
void nvgPathWinding(NVGcontext* ctx, int dir);
// Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r,
@ -442,7 +494,7 @@ void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r
// Creates new ellipse shaped sub-path.
void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry);
// Creates new circle shaped sub-path.
// Creates new circle shaped sub-path.
void nvgCircle(NVGcontext* ctx, float cx, float cy, float r);
// Fills the current path with current fill style.
@ -489,7 +541,7 @@ void nvgStroke(NVGcontext* ctx);
// Returns handle to the font.
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename);
// Creates image by loading it from the specified memory chunk.
// Creates font by loading it from the specified memory chunk.
// Returns handle to the font.
int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData);
@ -505,7 +557,7 @@ void nvgFontBlur(NVGcontext* ctx, float blur);
// Sets the letter spacing of current text style.
void nvgTextLetterSpacing(NVGcontext* ctx, float spacing);
// Sets the proportional line height of current text style. The line height is specified as multiple of font size.
// Sets the proportional line height of current text style. The line height is specified as multiple of font size.
void nvgTextLineHeight(NVGcontext* ctx, float lineHeight);
// Sets the text align of current text style, see NVGalign for options.
@ -592,7 +644,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 (*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);

View File

@ -537,7 +537,6 @@ namespace
static void nvgRenderViewport(void* _userPtr, int width, int height, float devicePixelRatio)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)_userPtr;
gl->state = 0;
gl->view[0] = (float)width;
gl->view[1] = (float)height;
bgfx::setViewRect(gl->m_viewId, 0, 0, width * devicePixelRatio, height * devicePixelRatio);
@ -694,7 +693,42 @@ namespace
}
}
static void nvgRenderFlush(void* _userPtr)
static uint64_t glnvg_convertBlendFuncFactor(int factor)
{
if (factor == NVG_ZERO)
return BGFX_STATE_BLEND_ZERO;
if (factor == NVG_ONE)
return BGFX_STATE_BLEND_ONE;
if (factor == NVG_SRC_COLOR)
return BGFX_STATE_BLEND_SRC_COLOR;
if (factor == NVG_ONE_MINUS_SRC_COLOR)
return BGFX_STATE_BLEND_INV_SRC_COLOR;
if (factor == NVG_DST_COLOR)
return BGFX_STATE_BLEND_DST_COLOR;
if (factor == NVG_ONE_MINUS_DST_COLOR)
return BGFX_STATE_BLEND_INV_DST_COLOR;
if (factor == NVG_SRC_ALPHA)
return BGFX_STATE_BLEND_SRC_ALPHA;
if (factor == NVG_ONE_MINUS_SRC_ALPHA)
return BGFX_STATE_BLEND_INV_SRC_ALPHA;
if (factor == NVG_DST_ALPHA)
return BGFX_STATE_BLEND_DST_ALPHA;
if (factor == NVG_ONE_MINUS_DST_ALPHA)
return BGFX_STATE_BLEND_INV_DST_ALPHA;
if (factor == NVG_SRC_ALPHA_SATURATE)
return BGFX_STATE_BLEND_SRC_ALPHA_SAT;
}
static uint64_t glnvg__blendCompositeOperation(NVGcompositeOperationState op)
{
return BGFX_STATE_BLEND_FUNC_SEPARATE(
glnvg_convertBlendFuncFactor(op.srcRGB),
glnvg_convertBlendFuncFactor(op.dstRGB),
glnvg_convertBlendFuncFactor(op.srcAlpha),
glnvg_convertBlendFuncFactor(op.dstAlpha));
}
static void nvgRenderFlush(void* _userPtr, NVGcompositeOperationState compositeOperation)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)_userPtr;
@ -712,12 +746,7 @@ namespace
memcpy(gl->tvb.data, gl->verts, gl->nverts * sizeof(struct NVGvertex) );
if (0 == gl->state)
{
gl->state = BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_INV_SRC_ALPHA);
}
gl->state |= 0
gl->state = glnvg__blendCompositeOperation(compositeOperation)
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_ALPHA_WRITE
;
@ -1078,13 +1107,6 @@ void nvgDelete(struct NVGcontext* ctx)
nvgDeleteInternal(ctx);
}
void nvgState(struct NVGcontext* ctx, uint64_t state)
{
struct NVGparams* params = nvgInternalParams(ctx);
struct GLNVGcontext* gl = (struct GLNVGcontext*)params->userPtr;
gl->state = state;
}
uint8_t nvgViewId(struct NVGcontext* ctx)
{
struct NVGparams* params = nvgInternalParams(ctx);
@ -1144,9 +1166,9 @@ void nvgluBindFramebuffer(NVGLUframebuffer* framebuffer) {
void nvgluDeleteFramebuffer(NVGLUframebuffer* framebuffer) {
if (framebuffer == NULL)
return;
if (framebuffer->image >= 0)
nvgDeleteImage(framebuffer->ctx, framebuffer->image);
if (bgfx::isValid(framebuffer->handle))
bgfx::destroyFrameBuffer(framebuffer->handle);
if (framebuffer->image > 0)
nvgDeleteImage(framebuffer->ctx, framebuffer->image);
delete framebuffer;
}

View File

@ -23,7 +23,6 @@ typedef struct NVGLUframebuffer NVGLUframebuffer;
NVGcontext* nvgCreate(int edgeaa, unsigned char _viewId, bx::AllocatorI* _allocator);
NVGcontext* nvgCreate(int edgeaa, unsigned char _viewId);
void nvgDelete(struct NVGcontext* ctx);
void nvgState(struct NVGcontext* ctx, uint64_t state);
uint8_t nvgViewId(struct NVGcontext* ctx);
void nvgViewId(struct NVGcontext* ctx, unsigned char _viewId);