Add OpenGL 4.6 backend for NanoVG
This commit introduces a new header file `nanovg_gl46.h` that implements the NanoVG rendering context using OpenGL 4.6. The new backend utilizes Direct State Access (DSA) functions, immutable texture storage, and explicit layout qualifiers. It includes definitions for creating and deleting the rendering context, as well as functions for handling images with OpenGL 4.6.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -15,3 +15,4 @@ cmake/
|
||||
*.flac
|
||||
*.aac
|
||||
*.opus
|
||||
external/nanovg
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "external/nanovg"]
|
||||
path = external/nanovg
|
||||
url = https://github.com/memononen/nanovg.git
|
||||
16
.vscode/c_cpp_properties.json
vendored
Normal file
16
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/gcc-14",
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++20",
|
||||
"intelliSenseMode": "linux-gcc-x64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
@@ -57,9 +57,9 @@ if(stb_ADDED)
|
||||
add_library(stb INTERFACE)
|
||||
target_include_directories(stb INTERFACE ${stb_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# ── Local dependencies ───────────────────────────────────────────────────────
|
||||
add_subdirectory(external/glad)
|
||||
add_subdirectory(external/nanovg)
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(X11 REQUIRED)
|
||||
@@ -90,6 +90,7 @@ target_link_libraries(${PROJECT_NAME}
|
||||
Lua::Library
|
||||
sol2
|
||||
stb
|
||||
nanovg
|
||||
glad
|
||||
PkgConfig::GST
|
||||
)
|
||||
|
||||
1
external/nanovg
vendored
Submodule
1
external/nanovg
vendored
Submodule
Submodule external/nanovg added at ce3bf745eb
BIN
samples/font.otf
Normal file
BIN
samples/font.otf
Normal file
Binary file not shown.
@@ -1,5 +1,11 @@
|
||||
effect = nil
|
||||
video = nil
|
||||
ctx = nil
|
||||
|
||||
timeDisplayText = ""
|
||||
dateDisplayText = ""
|
||||
|
||||
timer = 0.0
|
||||
|
||||
function _create()
|
||||
video = Texture.FromGStreamer("filesrc location=" .. Resolve("video.mkv"))
|
||||
@@ -21,10 +27,28 @@ function _create()
|
||||
}
|
||||
]]
|
||||
effect = Effect.new(fxSrc)
|
||||
|
||||
ctx = GraphicsContext.new()
|
||||
|
||||
local fontPath = Resolve("font.otf")
|
||||
ctx:CreateFont("font", fontPath)
|
||||
|
||||
UpdateTimeAndDate()
|
||||
end
|
||||
|
||||
function UpdateTimeAndDate()
|
||||
local now = os.date("*t")
|
||||
timeDisplayText = string.format("%02d:%02d", now.hour, now.min)
|
||||
dateDisplayText = os.date("%A, %B %d, %Y")
|
||||
end
|
||||
|
||||
function _update(dt)
|
||||
timer = timer + dt
|
||||
|
||||
if timer >= 0.5 then
|
||||
timer = 0.0
|
||||
UpdateTimeAndDate()
|
||||
end
|
||||
end
|
||||
|
||||
function _render()
|
||||
@@ -32,4 +56,23 @@ function _render()
|
||||
effect:Use()
|
||||
effect:SetTexture("uTexture", video, 0)
|
||||
effect:Render()
|
||||
|
||||
ctx:BeginFrame(DesktopSize.x, DesktopSize.y, DesktopSize.x / DesktopSize.y)
|
||||
|
||||
local xPos = 80.0
|
||||
local yPos = 120.0
|
||||
local timeFontSize = 80
|
||||
local dateFontSize = 28
|
||||
|
||||
ctx:FontSize(timeFontSize)
|
||||
ctx:FontFace("font")
|
||||
ctx:FillColor(RGBAf(1, 1, 1, 0.75))
|
||||
ctx:TextAlign(Align.RIGHT | Align.BOTTOM)
|
||||
ctx:Text(Displays[1].x + Displays[1].z - xPos, Displays[1].y + Displays[1].w - yPos, timeDisplayText)
|
||||
|
||||
ctx:FontSize(dateFontSize)
|
||||
ctx:FillColor(RGBAf(1, 1, 1, 0.45))
|
||||
ctx:Text(Displays[1].x + Displays[1].z - xPos, Displays[1].y + Displays[1].w - (yPos + timeFontSize + 8), dateDisplayText)
|
||||
|
||||
ctx:EndFrame()
|
||||
end
|
||||
225
src/lua.cpp
225
src/lua.cpp
@@ -8,6 +8,7 @@
|
||||
#include "framebuffer.h"
|
||||
#include "effect.h"
|
||||
#include "opengl.h"
|
||||
#include "nanovg_cpp.h"
|
||||
#include "globals.h"
|
||||
|
||||
static void RegisterTMath(sol::state& lua) {
|
||||
@@ -403,13 +404,234 @@ static void RegisterOpenGL(sol::state& lua) {
|
||||
gl["ONE_MINUS_DST_ALPHA"] = GL_ONE_MINUS_DST_ALPHA;
|
||||
}
|
||||
|
||||
#pragma region NanoVG bindings
|
||||
|
||||
static void RegisterNanoVG(sol::state& lua) {
|
||||
// ── NVGcolor ─────────────────────────────────────────────────────────
|
||||
lua.new_usertype<NVGcolor>("Color",
|
||||
sol::constructors<>(),
|
||||
"r", &NVGcolor::r,
|
||||
"g", &NVGcolor::g,
|
||||
"b", &NVGcolor::b,
|
||||
"a", &NVGcolor::a,
|
||||
sol::meta_function::to_string, [](const NVGcolor& c) {
|
||||
return "Color(" + std::to_string(c.r) + ", " + std::to_string(c.g) + ", " + std::to_string(c.b) + ", " + std::to_string(c.a) + ")";
|
||||
}
|
||||
);
|
||||
|
||||
// ── NVGpaint ────────────────────────────────────────────────────────
|
||||
lua.new_usertype<NVGpaint>("Paint",
|
||||
sol::constructors<>(),
|
||||
"innerColor", &NVGpaint::innerColor,
|
||||
"outerColor", &NVGpaint::outerColor,
|
||||
"image", &NVGpaint::image,
|
||||
"radius", &NVGpaint::radius,
|
||||
"feather", &NVGpaint::feather
|
||||
);
|
||||
|
||||
// ── NVG Enums ───────────────────────────────────────────────────────
|
||||
lua.new_enum<NVGwinding>("Winding", {
|
||||
{ "CCW", NVG_CCW },
|
||||
{ "CW", NVG_CW }
|
||||
});
|
||||
|
||||
lua.new_enum<NVGsolidity>("Solidity", {
|
||||
{ "SOLID", NVG_SOLID },
|
||||
{ "HOLE", NVG_HOLE }
|
||||
});
|
||||
|
||||
lua.new_enum<NVGlineCap>("LineCap", {
|
||||
{ "BUTT", NVG_BUTT },
|
||||
{ "ROUND", NVG_ROUND },
|
||||
{ "SQUARE", NVG_SQUARE },
|
||||
{ "BEVEL", NVG_BEVEL },
|
||||
{ "MITER", NVG_MITER }
|
||||
});
|
||||
|
||||
lua.new_enum<NVGalign>("Align", {
|
||||
{ "LEFT", NVG_ALIGN_LEFT },
|
||||
{ "CENTER", NVG_ALIGN_CENTER },
|
||||
{ "RIGHT", NVG_ALIGN_RIGHT },
|
||||
{ "TOP", NVG_ALIGN_TOP },
|
||||
{ "MIDDLE", NVG_ALIGN_MIDDLE },
|
||||
{ "BOTTOM", NVG_ALIGN_BOTTOM },
|
||||
{ "BASELINE", NVG_ALIGN_BASELINE }
|
||||
});
|
||||
|
||||
lua.new_enum<NVGcompositeOperation>("CompositeOperation", {
|
||||
{ "SOURCE_OVER", NVG_SOURCE_OVER },
|
||||
{ "SOURCE_IN", NVG_SOURCE_IN },
|
||||
{ "SOURCE_OUT", NVG_SOURCE_OUT },
|
||||
{ "ATOP", NVG_ATOP },
|
||||
{ "DESTINATION_OVER", NVG_DESTINATION_OVER },
|
||||
{ "DESTINATION_IN", NVG_DESTINATION_IN },
|
||||
{ "DESTINATION_OUT", NVG_DESTINATION_OUT },
|
||||
{ "DESTINATION_ATOP", NVG_DESTINATION_ATOP },
|
||||
{ "LIGHTER", NVG_LIGHTER },
|
||||
{ "COPY", NVG_COPY },
|
||||
{ "XOR", NVG_XOR }
|
||||
});
|
||||
|
||||
lua.create_named_table("ImageFlags",
|
||||
"GENERATE_MIPMAPS", NVG_IMAGE_GENERATE_MIPMAPS,
|
||||
"REPEATX", NVG_IMAGE_REPEATX,
|
||||
"REPEATY", NVG_IMAGE_REPEATY,
|
||||
"FLIPY", NVG_IMAGE_FLIPY,
|
||||
"PREMULTIPLIED", NVG_IMAGE_PREMULTIPLIED,
|
||||
"NEAREST", NVG_IMAGE_NEAREST
|
||||
);
|
||||
|
||||
// ── GraphicsContext ─────────────────────────────────────────────────
|
||||
lua.new_usertype<GraphicsContext>("GraphicsContext",
|
||||
sol::constructors<GraphicsContext()>(),
|
||||
|
||||
// Frame management
|
||||
"BeginFrame", &GraphicsContext::BeginFrame,
|
||||
"CancelFrame", &GraphicsContext::CancelFrame,
|
||||
"EndFrame", &GraphicsContext::EndFrame,
|
||||
|
||||
// Composite operations
|
||||
"GlobalCompositeOperation", &GraphicsContext::GlobalCompositeOperation,
|
||||
"GlobalCompositeBlendFunc", &GraphicsContext::GlobalCompositeBlendFunc,
|
||||
"GlobalCompositeBlendFuncSeparate", &GraphicsContext::GlobalCompositeBlendFuncSeparate,
|
||||
|
||||
// State handling
|
||||
"Save", &GraphicsContext::Save,
|
||||
"Restore", &GraphicsContext::Restore,
|
||||
"Reset", &GraphicsContext::Reset,
|
||||
|
||||
// Render styles
|
||||
"ShapeAntiAlias", &GraphicsContext::ShapeAntiAlias,
|
||||
"StrokeColor", &GraphicsContext::StrokeColor,
|
||||
"StrokePaint", &GraphicsContext::StrokePaint,
|
||||
"FillColor", &GraphicsContext::FillColor,
|
||||
"FillPaint", &GraphicsContext::FillPaint,
|
||||
"MiterLimit", &GraphicsContext::MiterLimit,
|
||||
"StrokeWidth", &GraphicsContext::StrokeWidth,
|
||||
"LineCap", &GraphicsContext::LineCap,
|
||||
"LineJoin", &GraphicsContext::LineJoin,
|
||||
"GlobalAlpha", &GraphicsContext::GlobalAlpha,
|
||||
|
||||
// Transforms
|
||||
"ResetTransform", &GraphicsContext::ResetTransform,
|
||||
"Transform", &GraphicsContext::Transform,
|
||||
"Translate", &GraphicsContext::Translate,
|
||||
"Rotate", &GraphicsContext::Rotate,
|
||||
"SkewX", &GraphicsContext::SkewX,
|
||||
"SkewY", &GraphicsContext::SkewY,
|
||||
"Scale", &GraphicsContext::Scale,
|
||||
"DegToRad", &GraphicsContext::DegToRad,
|
||||
"RadToDeg", &GraphicsContext::RadToDeg,
|
||||
|
||||
// Images
|
||||
"CreateImage", &GraphicsContext::CreateImage,
|
||||
"CreateImageRGBA", &GraphicsContext::CreateImageRGBA,
|
||||
"ImageSize", [](GraphicsContext& g, int image) -> std::pair<int, int> {
|
||||
return g.ImageSize(image);
|
||||
},
|
||||
"DeleteImage", &GraphicsContext::DeleteImage,
|
||||
|
||||
// Paints (gradients & patterns)
|
||||
"LinearGradient", &GraphicsContext::LinearGradient,
|
||||
"BoxGradient", &GraphicsContext::BoxGradient,
|
||||
"RadialGradient", &GraphicsContext::RadialGradient,
|
||||
"ImagePattern", &GraphicsContext::ImagePattern,
|
||||
|
||||
// Scissoring
|
||||
"Scissor", &GraphicsContext::Scissor,
|
||||
"IntersectScissor", &GraphicsContext::IntersectScissor,
|
||||
"ResetScissor", &GraphicsContext::ResetScissor,
|
||||
|
||||
// Paths
|
||||
"BeginPath", &GraphicsContext::BeginPath,
|
||||
"MoveTo", &GraphicsContext::MoveTo,
|
||||
"LineTo", &GraphicsContext::LineTo,
|
||||
"BezierTo", &GraphicsContext::BezierTo,
|
||||
"QuadTo", &GraphicsContext::QuadTo,
|
||||
"ArcTo", &GraphicsContext::ArcTo,
|
||||
"ClosePath", &GraphicsContext::ClosePath,
|
||||
"PathWinding", &GraphicsContext::PathWinding,
|
||||
"Arc", &GraphicsContext::Arc,
|
||||
"Rect", &GraphicsContext::Rect,
|
||||
"RoundedRect", &GraphicsContext::RoundedRect,
|
||||
"RoundedRectVarying", &GraphicsContext::RoundedRectVarying,
|
||||
"Ellipse", &GraphicsContext::Ellipse,
|
||||
"Circle", &GraphicsContext::Circle,
|
||||
"Fill", &GraphicsContext::Fill,
|
||||
"Stroke", &GraphicsContext::Stroke,
|
||||
|
||||
// Fonts
|
||||
"CreateFont", &GraphicsContext::CreateFont,
|
||||
"CreateFontAtIndex", &GraphicsContext::CreateFontAtIndex,
|
||||
"FindFont", &GraphicsContext::FindFont,
|
||||
"AddFallbackFontId", &GraphicsContext::AddFallbackFontId,
|
||||
"AddFallbackFont", &GraphicsContext::AddFallbackFont,
|
||||
"ResetFallbackFontsId", &GraphicsContext::ResetFallbackFontsId,
|
||||
"ResetFallbackFonts", &GraphicsContext::ResetFallbackFonts,
|
||||
|
||||
// Text styling
|
||||
"FontSize", &GraphicsContext::FontSize,
|
||||
"FontBlur", &GraphicsContext::FontBlur,
|
||||
"TextLetterSpacing", &GraphicsContext::TextLetterSpacing,
|
||||
"TextLineHeight", &GraphicsContext::TextLineHeight,
|
||||
"TextAlign", &GraphicsContext::TextAlign,
|
||||
"FontFaceId", &GraphicsContext::FontFaceId,
|
||||
"FontFace", &GraphicsContext::FontFace,
|
||||
|
||||
// Text rendering & measurement
|
||||
"Text", [](GraphicsContext& g, float x, float y, const std::string& str) -> float {
|
||||
return g.Text(x, y, str.c_str());
|
||||
},
|
||||
"TextBox", [](GraphicsContext& g, float x, float y, float breakRowWidth, const std::string& str) {
|
||||
g.TextBox(x, y, breakRowWidth, str.c_str());
|
||||
},
|
||||
"TextBounds", [](GraphicsContext& g, float x, float y, const std::string& str) -> std::tuple<float, float, float, float, float> {
|
||||
float bounds[4];
|
||||
float advance = g.TextBounds(x, y, str.c_str(), nullptr, bounds);
|
||||
return { advance, bounds[0], bounds[1], bounds[2], bounds[3] };
|
||||
},
|
||||
"TextBoxBounds", [](GraphicsContext& g, float x, float y, float breakRowWidth, const std::string& str) -> std::tuple<float, float, float, float> {
|
||||
float bounds[4];
|
||||
g.TextBoxBounds(x, y, breakRowWidth, str.c_str(), nullptr, bounds);
|
||||
return { bounds[0], bounds[1], bounds[2], bounds[3] };
|
||||
},
|
||||
"TextMetrics", [](GraphicsContext& g) -> std::tuple<float, float, float> {
|
||||
return g.TextMetrics();
|
||||
}
|
||||
);
|
||||
|
||||
// Loose functions
|
||||
lua.set_function("RGB", &GraphicsContext::RGB);
|
||||
lua.set_function("RGBf", &GraphicsContext::RGBf);
|
||||
lua.set_function("RGBA", &GraphicsContext::RGBA);
|
||||
lua.set_function("RGBAf", &GraphicsContext::RGBAf);
|
||||
lua.set_function("LerpRGBA", &GraphicsContext::LerpRGBA);
|
||||
lua.set_function("TransRGBA", &GraphicsContext::TransRGBA);
|
||||
lua.set_function("TransRGBAf", &GraphicsContext::TransRGBAf);
|
||||
lua.set_function("HSL", &GraphicsContext::HSL);
|
||||
lua.set_function("HSLA", &GraphicsContext::HSLA);
|
||||
|
||||
// Matrices/utils
|
||||
lua.set_function("DegToRad", &GraphicsContext::DegToRad);
|
||||
lua.set_function("RadToDeg", &GraphicsContext::RadToDeg);
|
||||
|
||||
lua.set_function("Rotate", &GraphicsContext::Rotate);
|
||||
lua.set_function("Translate", &GraphicsContext::Translate);
|
||||
lua.set_function("Scale", &GraphicsContext::Scale);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
void RegisterLuaBindings(sol::state& lua) {
|
||||
lua.open_libraries(
|
||||
sol::lib::base,
|
||||
sol::lib::math,
|
||||
sol::lib::string,
|
||||
sol::lib::table,
|
||||
sol::lib::package
|
||||
sol::lib::package,
|
||||
sol::lib::os,
|
||||
sol::lib::io,
|
||||
sol::lib::coroutine
|
||||
);
|
||||
|
||||
RegisterTMath(lua);
|
||||
@@ -417,6 +639,7 @@ void RegisterLuaBindings(sol::state& lua) {
|
||||
RegisterFrameBuffer(lua);
|
||||
RegisterEffect(lua);
|
||||
RegisterOpenGL(lua);
|
||||
RegisterNanoVG(lua);
|
||||
|
||||
// Globals
|
||||
lua["DesktopSize"] = g_DesktopSize;
|
||||
|
||||
171
src/nanovg_cpp.cpp
Normal file
171
src/nanovg_cpp.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
#include "nanovg_cpp.h"
|
||||
|
||||
GraphicsContext::GraphicsContext()
|
||||
{
|
||||
ctx = nvgCreateGL46(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
|
||||
}
|
||||
|
||||
GraphicsContext::~GraphicsContext()
|
||||
{
|
||||
if (ctx) {
|
||||
nvgDeleteGL46(ctx);
|
||||
ctx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Frame management
|
||||
|
||||
void GraphicsContext::BeginFrame(float width, float height, float devicePixelRatio)
|
||||
{
|
||||
nvgBeginFrame(ctx, width, height, devicePixelRatio);
|
||||
}
|
||||
|
||||
void GraphicsContext::CancelFrame() { nvgCancelFrame(ctx); }
|
||||
|
||||
void GraphicsContext::EndFrame()
|
||||
{
|
||||
nvgEndFrame(ctx);
|
||||
glBindVertexArray(0);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
// Composite operations
|
||||
|
||||
void GraphicsContext::GlobalCompositeOperation(int op) { nvgGlobalCompositeOperation(ctx, op); }
|
||||
void GraphicsContext::GlobalCompositeBlendFunc(int sfactor, int dfactor) { nvgGlobalCompositeBlendFunc(ctx, sfactor, dfactor); }
|
||||
void GraphicsContext::GlobalCompositeBlendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) { nvgGlobalCompositeBlendFuncSeparate(ctx, srcRGB, dstRGB, srcAlpha, dstAlpha); }
|
||||
|
||||
// Color utilities
|
||||
|
||||
NVGcolor GraphicsContext::RGB(unsigned char r, unsigned char g, unsigned char b) { return nvgRGB(r, g, b); }
|
||||
NVGcolor GraphicsContext::RGBf(float r, float g, float b) { return nvgRGBf(r, g, b); }
|
||||
NVGcolor GraphicsContext::RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { return nvgRGBA(r, g, b, a); }
|
||||
NVGcolor GraphicsContext::RGBAf(float r, float g, float b, float a) { return nvgRGBAf(r, g, b, a); }
|
||||
NVGcolor GraphicsContext::LerpRGBA(NVGcolor c0, NVGcolor c1, float u) { return nvgLerpRGBA(c0, c1, u); }
|
||||
NVGcolor GraphicsContext::TransRGBA(NVGcolor c0, unsigned char a) { return nvgTransRGBA(c0, a); }
|
||||
NVGcolor GraphicsContext::TransRGBAf(NVGcolor c0, float a) { return nvgTransRGBAf(c0, a); }
|
||||
NVGcolor GraphicsContext::HSL(float h, float s, float l) { return nvgHSL(h, s, l); }
|
||||
NVGcolor GraphicsContext::HSLA(float h, float s, float l, unsigned char a) { return nvgHSLA(h, s, l, a); }
|
||||
|
||||
// State handling
|
||||
|
||||
void GraphicsContext::Save() { nvgSave(ctx); }
|
||||
void GraphicsContext::Restore() { nvgRestore(ctx); }
|
||||
void GraphicsContext::Reset() { nvgReset(ctx); }
|
||||
|
||||
// Render styles
|
||||
|
||||
void GraphicsContext::ShapeAntiAlias(int enabled) { nvgShapeAntiAlias(ctx, enabled); }
|
||||
void GraphicsContext::StrokeColor(NVGcolor color) { nvgStrokeColor(ctx, color); }
|
||||
void GraphicsContext::StrokePaint(NVGpaint paint) { nvgStrokePaint(ctx, paint); }
|
||||
void GraphicsContext::FillColor(NVGcolor color) { nvgFillColor(ctx, color); }
|
||||
void GraphicsContext::FillPaint(NVGpaint paint) { nvgFillPaint(ctx, paint); }
|
||||
void GraphicsContext::MiterLimit(float limit) { nvgMiterLimit(ctx, limit); }
|
||||
void GraphicsContext::StrokeWidth(float size) { nvgStrokeWidth(ctx, size); }
|
||||
void GraphicsContext::LineCap(int cap) { nvgLineCap(ctx, cap); }
|
||||
void GraphicsContext::LineJoin(int join) { nvgLineJoin(ctx, join); }
|
||||
void GraphicsContext::GlobalAlpha(float alpha) { nvgGlobalAlpha(ctx, alpha); }
|
||||
|
||||
// Transforms
|
||||
|
||||
void GraphicsContext::ResetTransform() { nvgResetTransform(ctx); }
|
||||
void GraphicsContext::Transform(float a, float b, float c, float d, float e, float f) { nvgTransform(ctx, a, b, c, d, e, f); }
|
||||
void GraphicsContext::Translate(float x, float y) { nvgTranslate(ctx, x, y); }
|
||||
void GraphicsContext::Rotate(float angle) { nvgRotate(ctx, angle); }
|
||||
void GraphicsContext::SkewX(float angle) { nvgSkewX(ctx, angle); }
|
||||
void GraphicsContext::SkewY(float angle) { nvgSkewY(ctx, angle); }
|
||||
void GraphicsContext::Scale(float x, float y) { nvgScale(ctx, x, y); }
|
||||
void GraphicsContext::CurrentTransform(float* xform) { nvgCurrentTransform(ctx, xform); }
|
||||
|
||||
// Transform matrix utilities
|
||||
|
||||
void GraphicsContext::TransformIdentity(float* dst) { nvgTransformIdentity(dst); }
|
||||
void GraphicsContext::TransformTranslate(float* dst, float tx, float ty) { nvgTransformTranslate(dst, tx, ty); }
|
||||
void GraphicsContext::TransformScale(float* dst, float sx, float sy) { nvgTransformScale(dst, sx, sy); }
|
||||
void GraphicsContext::TransformRotate(float* dst, float a) { nvgTransformRotate(dst, a); }
|
||||
void GraphicsContext::TransformSkewX(float* dst, float a) { nvgTransformSkewX(dst, a); }
|
||||
void GraphicsContext::TransformSkewY(float* dst, float a) { nvgTransformSkewY(dst, a); }
|
||||
void GraphicsContext::TransformMultiply(float* dst, const float* src) { nvgTransformMultiply(dst, src); }
|
||||
void GraphicsContext::TransformPremultiply(float* dst, const float* src) { nvgTransformPremultiply(dst, src); }
|
||||
int GraphicsContext::TransformInverse(float* dst, const float* src) { return nvgTransformInverse(dst, src); }
|
||||
void GraphicsContext::TransformPoint(float* dstx, float* dsty, const float* xform, float srcx, float srcy) { nvgTransformPoint(dstx, dsty, xform, srcx, srcy); }
|
||||
|
||||
float GraphicsContext::DegToRad(float deg) { return nvgDegToRad(deg); }
|
||||
float GraphicsContext::RadToDeg(float rad) { return nvgRadToDeg(rad); }
|
||||
|
||||
// Images
|
||||
|
||||
int GraphicsContext::CreateImage(const char* filename, int imageFlags) { return nvgCreateImage(ctx, filename, imageFlags); }
|
||||
int GraphicsContext::CreateImageMem(int imageFlags, unsigned char* data, int ndata) { return nvgCreateImageMem(ctx, imageFlags, data, ndata); }
|
||||
int GraphicsContext::CreateImageRGBA(int w, int h, int imageFlags, const unsigned char* data) { return nvgCreateImageRGBA(ctx, w, h, imageFlags, data); }
|
||||
void GraphicsContext::UpdateImage(int image, const unsigned char* data) { nvgUpdateImage(ctx, image, data); }
|
||||
void GraphicsContext::ImageSize(int image, int* w, int* h) { nvgImageSize(ctx, image, w, h); }
|
||||
std::pair<int, int> GraphicsContext::ImageSize(int image) { int w, h; nvgImageSize(ctx, image, &w, &h); return {w, h}; }
|
||||
void GraphicsContext::DeleteImage(int image) { nvgDeleteImage(ctx, image); }
|
||||
|
||||
// Paints (gradients & patterns)
|
||||
|
||||
NVGpaint GraphicsContext::LinearGradient(float sx, float sy, float ex, float ey, NVGcolor icol, NVGcolor ocol) { return nvgLinearGradient(ctx, sx, sy, ex, ey, icol, ocol); }
|
||||
NVGpaint GraphicsContext::BoxGradient(float x, float y, float w, float h, float r, float f, NVGcolor icol, NVGcolor ocol) { return nvgBoxGradient(ctx, x, y, w, h, r, f, icol, ocol); }
|
||||
NVGpaint GraphicsContext::RadialGradient(float cx, float cy, float inr, float outr, NVGcolor icol, NVGcolor ocol) { return nvgRadialGradient(ctx, cx, cy, inr, outr, icol, ocol); }
|
||||
NVGpaint GraphicsContext::ImagePattern(float ox, float oy, float ex, float ey, float angle, int image, float alpha) { return nvgImagePattern(ctx, ox, oy, ex, ey, angle, image, alpha); }
|
||||
|
||||
// Scissoring
|
||||
|
||||
void GraphicsContext::Scissor(float x, float y, float w, float h) { nvgScissor(ctx, x, y, w, h); }
|
||||
void GraphicsContext::IntersectScissor(float x, float y, float w, float h) { nvgIntersectScissor(ctx, x, y, w, h); }
|
||||
void GraphicsContext::ResetScissor() { nvgResetScissor(ctx); }
|
||||
|
||||
// Paths
|
||||
|
||||
void GraphicsContext::BeginPath() { nvgBeginPath(ctx); }
|
||||
void GraphicsContext::MoveTo(float x, float y) { nvgMoveTo(ctx, x, y); }
|
||||
void GraphicsContext::LineTo(float x, float y) { nvgLineTo(ctx, x, y); }
|
||||
void GraphicsContext::BezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y) { nvgBezierTo(ctx, c1x, c1y, c2x, c2y, x, y); }
|
||||
void GraphicsContext::QuadTo(float cx, float cy, float x, float y) { nvgQuadTo(ctx, cx, cy, x, y); }
|
||||
void GraphicsContext::ArcTo(float x1, float y1, float x2, float y2, float radius) { nvgArcTo(ctx, x1, y1, x2, y2, radius); }
|
||||
void GraphicsContext::ClosePath() { nvgClosePath(ctx); }
|
||||
void GraphicsContext::PathWinding(int dir) { nvgPathWinding(ctx, dir); }
|
||||
void GraphicsContext::Arc(float cx, float cy, float r, float a0, float a1, int dir) { nvgArc(ctx, cx, cy, r, a0, a1, dir); }
|
||||
void GraphicsContext::Rect(float x, float y, float w, float h) { nvgRect(ctx, x, y, w, h); }
|
||||
void GraphicsContext::RoundedRect(float x, float y, float w, float h, float r) { nvgRoundedRect(ctx, x, y, w, h, r); }
|
||||
void GraphicsContext::RoundedRectVarying(float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft) { nvgRoundedRectVarying(ctx, x, y, w, h, radTopLeft, radTopRight, radBottomRight, radBottomLeft); }
|
||||
void GraphicsContext::Ellipse(float cx, float cy, float rx, float ry) { nvgEllipse(ctx, cx, cy, rx, ry); }
|
||||
void GraphicsContext::Circle(float cx, float cy, float r) { nvgCircle(ctx, cx, cy, r); }
|
||||
void GraphicsContext::Fill() { nvgFill(ctx); }
|
||||
void GraphicsContext::Stroke() { nvgStroke(ctx); }
|
||||
|
||||
// Fonts
|
||||
|
||||
int GraphicsContext::CreateFont(const char* name, const char* filename) { return nvgCreateFont(ctx, name, filename); }
|
||||
int GraphicsContext::CreateFontAtIndex(const char* name, const char* filename, int fontIndex) { return nvgCreateFontAtIndex(ctx, name, filename, fontIndex); }
|
||||
int GraphicsContext::CreateFontMem(const char* name, unsigned char* data, int ndata, int freeData) { return nvgCreateFontMem(ctx, name, data, ndata, freeData); }
|
||||
int GraphicsContext::CreateFontMemAtIndex(const char* name, unsigned char* data, int ndata, int freeData, int fontIndex) { return nvgCreateFontMemAtIndex(ctx, name, data, ndata, freeData, fontIndex); }
|
||||
int GraphicsContext::FindFont(const char* name) { return nvgFindFont(ctx, name); }
|
||||
int GraphicsContext::AddFallbackFontId(int baseFont, int fallbackFont) { return nvgAddFallbackFontId(ctx, baseFont, fallbackFont); }
|
||||
int GraphicsContext::AddFallbackFont(const char* baseFont, const char* fallbackFont) { return nvgAddFallbackFont(ctx, baseFont, fallbackFont); }
|
||||
void GraphicsContext::ResetFallbackFontsId(int baseFont) { nvgResetFallbackFontsId(ctx, baseFont); }
|
||||
void GraphicsContext::ResetFallbackFonts(const char* baseFont) { nvgResetFallbackFonts(ctx, baseFont); }
|
||||
|
||||
// Text styling
|
||||
|
||||
void GraphicsContext::FontSize(float size) { nvgFontSize(ctx, size); }
|
||||
void GraphicsContext::FontBlur(float blur) { nvgFontBlur(ctx, blur); }
|
||||
void GraphicsContext::TextLetterSpacing(float spacing) { nvgTextLetterSpacing(ctx, spacing); }
|
||||
void GraphicsContext::TextLineHeight(float lineHeight) { nvgTextLineHeight(ctx, lineHeight); }
|
||||
void GraphicsContext::TextAlign(int align) { nvgTextAlign(ctx, align); }
|
||||
void GraphicsContext::FontFaceId(int font) { nvgFontFaceId(ctx, font); }
|
||||
void GraphicsContext::FontFace(const char* font) { nvgFontFace(ctx, font); }
|
||||
|
||||
// Text rendering & measurement
|
||||
|
||||
float GraphicsContext::Text(float x, float y, const char* string, const char* end) { return nvgText(ctx, x, y, string, end); }
|
||||
void GraphicsContext::TextBox(float x, float y, float breakRowWidth, const char* string, const char* end) { nvgTextBox(ctx, x, y, breakRowWidth, string, end); }
|
||||
float GraphicsContext::TextBounds(float x, float y, const char* string, const char* end, float* bounds) { return nvgTextBounds(ctx, x, y, string, end, bounds); }
|
||||
void GraphicsContext::TextBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds) { nvgTextBoxBounds(ctx, x, y, breakRowWidth, string, end, bounds); }
|
||||
int GraphicsContext::TextGlyphPositions(float x, float y, const char* string, const char* end, NVGglyphPosition* positions, int maxPositions) { return nvgTextGlyphPositions(ctx, x, y, string, end, positions, maxPositions); }
|
||||
void GraphicsContext::TextMetrics(float* ascender, float* descender, float* lineh) { nvgTextMetrics(ctx, ascender, descender, lineh); }
|
||||
std::tuple<float, float, float> GraphicsContext::TextMetrics() { float a, d, l; nvgTextMetrics(ctx, &a, &d, &l); return {a, d, l}; }
|
||||
int GraphicsContext::TextBreakLines(const char* string, const char* end, float breakRowWidth, NVGtextRow* rows, int maxRows) { return nvgTextBreakLines(ctx, string, end, breakRowWidth, rows, maxRows); }
|
||||
149
src/nanovg_cpp.h
Normal file
149
src/nanovg_cpp.h
Normal file
@@ -0,0 +1,149 @@
|
||||
#pragma once
|
||||
|
||||
#include "nanovg.h"
|
||||
#include "nanovg_gl46.h"
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
class GraphicsContext {
|
||||
public:
|
||||
GraphicsContext();
|
||||
~GraphicsContext();
|
||||
|
||||
NVGcontext* GetNVG() const { return ctx; }
|
||||
|
||||
// Frame management
|
||||
void BeginFrame(float width, float height, float devicePixelRatio);
|
||||
void CancelFrame();
|
||||
void EndFrame();
|
||||
|
||||
// Composite operations
|
||||
void GlobalCompositeOperation(int op);
|
||||
void GlobalCompositeBlendFunc(int sfactor, int dfactor);
|
||||
void GlobalCompositeBlendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha);
|
||||
|
||||
// Color utilities (static)
|
||||
static NVGcolor RGB(unsigned char r, unsigned char g, unsigned char b);
|
||||
static NVGcolor RGBf(float r, float g, float b);
|
||||
static NVGcolor RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
|
||||
static NVGcolor RGBAf(float r, float g, float b, float a);
|
||||
static NVGcolor LerpRGBA(NVGcolor c0, NVGcolor c1, float u);
|
||||
static NVGcolor TransRGBA(NVGcolor c0, unsigned char a);
|
||||
static NVGcolor TransRGBAf(NVGcolor c0, float a);
|
||||
static NVGcolor HSL(float h, float s, float l);
|
||||
static NVGcolor HSLA(float h, float s, float l, unsigned char a);
|
||||
|
||||
// State handling
|
||||
void Save();
|
||||
void Restore();
|
||||
void Reset();
|
||||
|
||||
// Render styles
|
||||
void ShapeAntiAlias(int enabled);
|
||||
void StrokeColor(NVGcolor color);
|
||||
void StrokePaint(NVGpaint paint);
|
||||
void FillColor(NVGcolor color);
|
||||
void FillPaint(NVGpaint paint);
|
||||
void MiterLimit(float limit);
|
||||
void StrokeWidth(float size);
|
||||
void LineCap(int cap);
|
||||
void LineJoin(int join);
|
||||
void GlobalAlpha(float alpha);
|
||||
|
||||
// Transforms
|
||||
void ResetTransform();
|
||||
void Transform(float a, float b, float c, float d, float e, float f);
|
||||
void Translate(float x, float y);
|
||||
void Rotate(float angle);
|
||||
void SkewX(float angle);
|
||||
void SkewY(float angle);
|
||||
void Scale(float x, float y);
|
||||
void CurrentTransform(float* xform);
|
||||
|
||||
// Transform matrix utilities (static)
|
||||
static void TransformIdentity(float* dst);
|
||||
static void TransformTranslate(float* dst, float tx, float ty);
|
||||
static void TransformScale(float* dst, float sx, float sy);
|
||||
static void TransformRotate(float* dst, float a);
|
||||
static void TransformSkewX(float* dst, float a);
|
||||
static void TransformSkewY(float* dst, float a);
|
||||
static void TransformMultiply(float* dst, const float* src);
|
||||
static void TransformPremultiply(float* dst, const float* src);
|
||||
static int TransformInverse(float* dst, const float* src);
|
||||
static void TransformPoint(float* dstx, float* dsty, const float* xform, float srcx, float srcy);
|
||||
|
||||
static float DegToRad(float deg);
|
||||
static float RadToDeg(float rad);
|
||||
|
||||
// Images
|
||||
int CreateImage(const char* filename, int imageFlags);
|
||||
int CreateImageMem(int imageFlags, unsigned char* data, int ndata);
|
||||
int CreateImageRGBA(int w, int h, int imageFlags, const unsigned char* data);
|
||||
void UpdateImage(int image, const unsigned char* data);
|
||||
void ImageSize(int image, int* w, int* h);
|
||||
std::pair<int, int> ImageSize(int image);
|
||||
void DeleteImage(int image);
|
||||
|
||||
// Paints (gradients & patterns)
|
||||
NVGpaint LinearGradient(float sx, float sy, float ex, float ey, NVGcolor icol, NVGcolor ocol);
|
||||
NVGpaint BoxGradient(float x, float y, float w, float h, float r, float f, NVGcolor icol, NVGcolor ocol);
|
||||
NVGpaint RadialGradient(float cx, float cy, float inr, float outr, NVGcolor icol, NVGcolor ocol);
|
||||
NVGpaint ImagePattern(float ox, float oy, float ex, float ey, float angle, int image, float alpha);
|
||||
|
||||
// Scissoring
|
||||
void Scissor(float x, float y, float w, float h);
|
||||
void IntersectScissor(float x, float y, float w, float h);
|
||||
void ResetScissor();
|
||||
|
||||
// Paths
|
||||
void BeginPath();
|
||||
void MoveTo(float x, float y);
|
||||
void LineTo(float x, float y);
|
||||
void BezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y);
|
||||
void QuadTo(float cx, float cy, float x, float y);
|
||||
void ArcTo(float x1, float y1, float x2, float y2, float radius);
|
||||
void ClosePath();
|
||||
void PathWinding(int dir);
|
||||
void Arc(float cx, float cy, float r, float a0, float a1, int dir);
|
||||
void Rect(float x, float y, float w, float h);
|
||||
void RoundedRect(float x, float y, float w, float h, float r);
|
||||
void RoundedRectVarying(float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft);
|
||||
void Ellipse(float cx, float cy, float rx, float ry);
|
||||
void Circle(float cx, float cy, float r);
|
||||
void Fill();
|
||||
void Stroke();
|
||||
|
||||
// Fonts
|
||||
int CreateFont(const char* name, const char* filename);
|
||||
int CreateFontAtIndex(const char* name, const char* filename, int fontIndex);
|
||||
int CreateFontMem(const char* name, unsigned char* data, int ndata, int freeData);
|
||||
int CreateFontMemAtIndex(const char* name, unsigned char* data, int ndata, int freeData, int fontIndex);
|
||||
int FindFont(const char* name);
|
||||
int AddFallbackFontId(int baseFont, int fallbackFont);
|
||||
int AddFallbackFont(const char* baseFont, const char* fallbackFont);
|
||||
void ResetFallbackFontsId(int baseFont);
|
||||
void ResetFallbackFonts(const char* baseFont);
|
||||
|
||||
// Text styling
|
||||
void FontSize(float size);
|
||||
void FontBlur(float blur);
|
||||
void TextLetterSpacing(float spacing);
|
||||
void TextLineHeight(float lineHeight);
|
||||
void TextAlign(int align);
|
||||
void FontFaceId(int font);
|
||||
void FontFace(const char* font);
|
||||
|
||||
// Text rendering & measurement
|
||||
float Text(float x, float y, const char* string, const char* end = nullptr);
|
||||
void TextBox(float x, float y, float breakRowWidth, const char* string, const char* end = nullptr);
|
||||
float TextBounds(float x, float y, const char* string, const char* end, float* bounds);
|
||||
void TextBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds);
|
||||
int TextGlyphPositions(float x, float y, const char* string, const char* end, NVGglyphPosition* positions, int maxPositions);
|
||||
void TextMetrics(float* ascender, float* descender, float* lineh);
|
||||
std::tuple<float, float, float> TextMetrics();
|
||||
int TextBreakLines(const char* string, const char* end, float breakRowWidth, NVGtextRow* rows, int maxRows);
|
||||
|
||||
private:
|
||||
NVGcontext* ctx = nullptr;
|
||||
};
|
||||
1208
src/nanovg_gl46.cpp
Normal file
1208
src/nanovg_gl46.cpp
Normal file
File diff suppressed because it is too large
Load Diff
31
src/nanovg_gl46.h
Normal file
31
src/nanovg_gl46.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// NanoVG OpenGL 4.6 Core Profile backend
|
||||
//
|
||||
// Based on nanovg_gl.h by Mikko Mononen (Copyright (c) 2009-2013)
|
||||
// Adapted to use OpenGL 4.6 Direct State Access (DSA) functions,
|
||||
// immutable texture storage, and explicit layout qualifiers.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "glad/gl.h"
|
||||
|
||||
struct NVGcontext;
|
||||
|
||||
// Create flags (same as nanovg_gl.h, guarded to avoid redefinition)
|
||||
#ifndef NANOVG_GL_H
|
||||
enum NVGcreateFlags {
|
||||
NVG_ANTIALIAS = 1 << 0,
|
||||
NVG_STENCIL_STROKES = 1 << 1,
|
||||
NVG_DEBUG = 1 << 2,
|
||||
};
|
||||
|
||||
enum NVGimageFlagsGL {
|
||||
NVG_IMAGE_NODELETE = 1 << 16,
|
||||
};
|
||||
#endif
|
||||
|
||||
NVGcontext* nvgCreateGL46(int flags);
|
||||
void nvgDeleteGL46(NVGcontext* ctx);
|
||||
|
||||
int nvglCreateImageFromHandleGL46(NVGcontext* ctx, GLuint textureId, int w, int h, int flags);
|
||||
GLuint nvglImageHandleGL46(NVGcontext* ctx, int image);
|
||||
Reference in New Issue
Block a user