#include "graphics/paths/PathRenderer.h" #include "graphics/paths/NanoVGRenderer.h" namespace { NVGcolor fsColorToNVG(color* c) { return nvgRGBA(c->red, c->green, c->blue, c->is_alphacolor ? c->alpha : 255); } } namespace graphics { namespace paths { std::unique_ptr PathRenderer::s_instance; bool PathRenderer::init() { s_instance = std::unique_ptr(new PathRenderer()); return true; } void PathRenderer::shutdown() { s_instance = nullptr; } PathRenderer::PathRenderer() : m_inFrame(false) { m_context = createNanoVGContext(); } PathRenderer::~PathRenderer() { if (m_context) { deleteNanoVGContext(m_context); m_context = nullptr; } } void PathRenderer::beginFrame() { Assertion(!m_inFrame, "beginFrame() was called withoug ending previous frame! Check your path renderer calls or get a coder!"); nvgBeginFrame(m_context, gr_screen.max_w, gr_screen.max_h, 1.0f); m_inFrame = true; } void PathRenderer::cancelFrame() { nvgCancelFrame(m_context); m_inFrame = false; } void PathRenderer::endFrame() { nvgEndFrame(m_context); m_inFrame = false; } void PathRenderer::scissor(float x, float y, float w, float h) { nvgScissor(m_context, x, y, w, h); } void PathRenderer::resetScissor() { nvgResetScissor(m_context); } void PathRenderer::resetTransform() { nvgResetTransform(m_context); } void PathRenderer::translate(float x, float y) { nvgTranslate(m_context, x, y); } void PathRenderer::rotate(float rad) { nvgRotate(m_context, rad); } void PathRenderer::skewX(float rad) { nvgSkewX(m_context, rad); } void PathRenderer::skewY(float rad) { nvgSkewY(m_context, rad); } void PathRenderer::scale(float x, float y) { nvgScale(m_context, x, y); } DrawPaint PathRenderer::createLinearGradient(float sx, float sy, float ex, float ey, color* icol, color* ocol) { DrawPaint p; p.nvg = nvgLinearGradient(m_context, sx, sy, ex, ey, fsColorToNVG(icol), fsColorToNVG(ocol)); return p; } void PathRenderer::setAlpha(float alpha) { nvgGlobalAlpha(m_context, alpha); } void PathRenderer::setFillColor(color* color) { nvgFillColor(m_context, fsColorToNVG(color)); } void PathRenderer::setFillPaint(const DrawPaint& paint) { nvgFillPaint(m_context, paint.nvg); } void PathRenderer::setStrokeColor(::color* color) { nvgStrokeColor(m_context, fsColorToNVG(color)); } void PathRenderer::setStrokePaint(const DrawPaint& paint) { nvgStrokePaint(m_context, paint.nvg); } void PathRenderer::setStrokeWidth(float width) { nvgStrokeWidth(m_context, width); } void PathRenderer::beginPath() { nvgBeginPath(m_context); } void PathRenderer::moveTo(float x, float y) { nvgMoveTo(m_context, x, y); } void PathRenderer::setSolidity(Solidity solid) { int nvgSolid; switch (solid) { case SOLIDITY_HOLE: nvgSolid = NVG_HOLE; break; case SOLIDITY_SOLID: nvgSolid = NVG_SOLID; break; default: nvgSolid = NVG_SOLID; break; } nvgPathWinding(m_context, nvgSolid); } void PathRenderer::lineTo(float x, float y) { nvgLineTo(m_context, x, y); } void PathRenderer::rectangle(float x, float y, float w, float h) { nvgRect(m_context, x, y, w, h); } void PathRenderer::roundedRectangle(float x, float y, float w, float h, float radius) { nvgRoundedRect(m_context, x, y, w, h, radius); } void PathRenderer::circle(float x, float y, float r) { nvgCircle(m_context, x, y, r); } void PathRenderer::ellipse(float x, float y, float rx, float ry) { nvgEllipse(m_context, x, y, rx, ry); } void PathRenderer::arc(float cx, float cy, float r, float a0, float a1, Direction dir) { int nvgDir; switch (dir) { case DIR_CCW: nvgDir = NVG_CCW; break; case DIR_CW: nvgDir = NVG_CW; break; default: nvgDir = NVG_CW; break; } nvgArc(m_context, cx, cy, r, a0, a1, nvgDir); } void PathRenderer::closePath() { nvgClosePath(m_context); } int PathRenderer::createFontMem(const char* name, unsigned char* data, int ndata, int freeData) { return nvgCreateFontMem(m_context, name, data, ndata, freeData); } void PathRenderer::fontSize(float size) { nvgFontSize(m_context, size); } void PathRenderer::textLetterSpacing(float spacing) { nvgTextLetterSpacing(m_context, spacing); } void PathRenderer::fontFaceId(int font) { nvgFontFaceId(m_context, font); } float PathRenderer::text(float x, float y, const char* string, const char* end) { return nvgText(m_context, x, y, string, end); } float PathRenderer::textBounds(float x, float y, const char* string, const char* end, float* bounds) { return nvgTextBounds(m_context, x, y, string, end, bounds); } void PathRenderer::textMetrics(float* ascender, float* descender, float* lineh) { nvgTextMetrics(m_context, ascender, descender, lineh); } void PathRenderer::textAlign(TextAlign align) { int nvgAlign = 0; if (align & ALIGN_LEFT) { nvgAlign |= NVG_ALIGN_LEFT; } if (align & ALIGN_CENTER) { nvgAlign |= NVG_ALIGN_CENTER; } if (align & ALIGN_RIGHT) { nvgAlign |= NVG_ALIGN_RIGHT; } if (align & ALIGN_TOP) { nvgAlign |= NVG_ALIGN_TOP; } if (align & ALIGN_MIDDLE) { nvgAlign |= NVG_ALIGN_MIDDLE; } if (align & ALIGN_BOTTOM) { nvgAlign |= NVG_ALIGN_BOTTOM; } if (align & ALIGN_BASELINE) { nvgAlign |= NVG_ALIGN_BASELINE; } nvgTextAlign(m_context, nvgAlign); } void PathRenderer::fill() { nvgFill(m_context); } void PathRenderer::stroke() { nvgStroke(m_context); } void PathRenderer::saveState() { nvgSave(m_context); } void PathRenderer::resetState() { nvgReset(m_context); } void PathRenderer::restoreState() { nvgRestore(m_context); } } }