robustified file path handling

This commit is contained in:
Blake Lucas 2026-03-28 16:28:14 -07:00
parent ac851e991d
commit 41ac3a0acf
8 changed files with 103 additions and 85 deletions

View file

@ -3,6 +3,7 @@
#include <string.h>
#include <string>
#include <array>
#include <filesystem>
#include <vector>
#ifdef _MSC_VER
@ -887,40 +888,57 @@ void drawLines(nvg::Context& vg, float x, float y, float w, float h, float lineW
int loadDemoData(nvg::Context& vg, DemoData* data)
{
int i;
namespace fs = std::filesystem;
auto findFile=[](const fs::path& name){
fs::path current_dir = fs::current_path();
fs::path path =current_dir/"example"/ name;
if (fs::exists(path)) {
return path.string();
}
path = current_dir.parent_path()/"example"/ name;
if (fs::exists(path)) {
return path.string();
}
path = current_dir.parent_path().parent_path()/"example"/name;
return path.string();
};
for (i = 0; i < 12; i++) {
std::array<char, 128> file{};
snprintf(file.data(), (int)file.size(), "../example/images/image%d.jpg", i+1);
data->images[i] = vg.createImage( file.data(), 0);
const std::string file = findFile(fs::path("images")/("image" + std::to_string(i+1) + ".jpg"));
data->images[i] = vg.createImage(file.c_str(), 0);
if (data->images[i] == 0) {
printf("Could not load %s.\n", file.data());
printf("Could not load %s.\n", file.c_str());
return -1;
}
}
const std::string ex = "../example/";
data->fontIcons = vg.createFont( "icons", (ex + "entypo.ttf").c_str());
const std::string fontIcons = findFile("entypo.ttf");
data->fontIcons = vg.createFont("icons", fontIcons.c_str());
if (data->fontIcons == -1) {
printf("Could not add font icons.\n");
return -1;
}
data->fontNormal = vg.createFont( "sans", (ex + "Roboto-Regular.ttf").c_str());
const std::string fontNormal = findFile("Roboto-Regular.ttf");
data->fontNormal = vg.createFont( "sans", fontNormal.c_str());
if (data->fontNormal == -1) {
printf("Could not add font italic.\n");
printf("Could not add font normal %s\n",fontNormal.c_str());
return -1;
}
data->fontBold = vg.createFont( "sans-bold", (ex + "Roboto-Bold.ttf").c_str());
const std::string fontBold = findFile("Roboto-Bold.ttf");
data->fontBold = vg.createFont( "sans-bold", fontBold.c_str());
if (data->fontBold == -1) {
printf("Could not add font bold.\n");
printf("Could not add font bold %s\n",fontBold.c_str());
return -1;
}
data->fontEmoji = vg.createFont( "emoji", (ex + "NotoEmoji-Regular.ttf").c_str());
const std::string fontEmoji = findFile("NotoEmoji-Regular.ttf");
data->fontEmoji = vg.createFont("emoji",fontEmoji.c_str());
if (data->fontEmoji == -1) {
printf("Could not add font emoji.\n");
printf("Could not add font emoji %s\n",fontEmoji.c_str());
return -1;
}
vg.addFallbackFontId( data->fontNormal, data->fontEmoji);
vg.addFallbackFontId( data->fontBold, data->fontEmoji);
vg.addFallbackFontId(data->fontNormal, data->fontEmoji);
vg.addFallbackFont(fontNormal.c_str(), fontEmoji.c_str());
return 0;
}

View file

@ -118,9 +118,9 @@ int main()
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(&cpuGraph, GRAPH_RENDER_MS, "CPU Time");
initGraph(&gpuGraph, GRAPH_RENDER_MS, "GPU Time");
initGraph(fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(cpuGraph, GRAPH_RENDER_MS, "CPU Time");
initGraph(gpuGraph, GRAPH_RENDER_MS, "GPU Time");
glfwSetErrorCallback(errorcb);
#ifndef _WIN32 // don't require this on win32, and works with more cards
@ -241,23 +241,23 @@ int main()
vg.restore();
}
renderGraph(vg, 5,5, &fps);
renderGraph(vg, 5+200+5,5, &cpuGraph);
renderGraph(vg, 5,5, fps);
renderGraph(vg, 5+200+5,5, cpuGraph);
if (gpuTimer.supported)
renderGraph(vg, 5+200+5+200+5,5, &gpuGraph);
renderGraph(vg, 5+200+5+200+5,5, gpuGraph);
vg.endFrame();
// Measure the CPU time taken excluding swap buffers (as the swap may wait for GPU)
cpuTime = glfwGetTime() - t;
updateGraph(&fps, static_cast<float>(dt));
updateGraph(&cpuGraph, static_cast<float>(cpuTime));
updateGraph(fps, static_cast<float>(dt));
updateGraph(cpuGraph, static_cast<float>(cpuTime));
// We may get multiple results.
n = stopGPUTimer(&gpuTimer, gpuTimes.data(), (int)gpuTimes.size());
for (i = 0; i < n; i++)
updateGraph(&gpuGraph, gpuTimes[i]);
updateGraph(gpuGraph, gpuTimes[i]);
glfwSwapBuffers(window);
glfwPollEvents();
@ -267,9 +267,9 @@ int main()
nvg::deleteGL(vgOwner);
printf("Average Frame Time: %.2f ms\n", getGraphAverage(&fps) * 1000.0f);
printf(" CPU Time: %.2f ms\n", getGraphAverage(&cpuGraph) * 1000.0f);
printf(" GPU Time: %.2f ms\n", getGraphAverage(&gpuGraph) * 1000.0f);
printf("Average Frame Time: %.2f ms\n", getGraphAverage(fps) * 1000.0f);
printf(" CPU Time: %.2f ms\n", getGraphAverage(cpuGraph) * 1000.0f);
printf(" GPU Time: %.2f ms\n", getGraphAverage(gpuGraph) * 1000.0f);
glfwTerminate();
return 0;

View file

@ -65,7 +65,7 @@ int main()
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(fps, GRAPH_RENDER_FPS, "Frame Time");
glfwSetErrorCallback(errorcb);
@ -121,7 +121,7 @@ int main()
t = glfwGetTime();
dt = t - prevt;
prevt = t;
updateGraph(&fps, static_cast<float>(dt));
updateGraph(fps, static_cast<float>(dt));
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
@ -141,7 +141,7 @@ int main()
vg.beginFrame( static_cast<float>(winWidth), static_cast<float>(winHeight), pxRatio);
renderDemo(vg, static_cast<float>(mx), static_cast<float>(my), static_cast<float>(winWidth), static_cast<float>(winHeight), static_cast<float>(t), blowup, &data);
renderGraph(vg, 5,5, &fps);
renderGraph(vg, 5,5, fps);
vg.endFrame();

View file

@ -68,7 +68,7 @@ int main(int argc, char** argv)
PerfGraph fps, cpuGraph, gpuGraph;
double prevt = 0, cpuTime = 0;
int testCount = 0;
bool testSpecified = false;
bool testRequested = false;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--test")) {
if (i + 1 >= argc) {
@ -82,7 +82,7 @@ int main(int argc, char** argv)
return -1;
}
testCount = static_cast<int>(v);
testSpecified = true;
testRequested = true;
i++;
} else if (!strncmp(argv[i], "--test=", 7)) {
char* endptr = NULL;
@ -92,7 +92,7 @@ int main(int argc, char** argv)
return -1;
}
testCount = static_cast<int>(v);
testSpecified = true;
testRequested = true;
}
}
int testRemaining = testCount;
@ -102,9 +102,9 @@ int main(int argc, char** argv)
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(&cpuGraph, GRAPH_RENDER_MS, "CPU Time");
initGraph(&gpuGraph, GRAPH_RENDER_MS, "GPU Time");
initGraph(fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(cpuGraph, GRAPH_RENDER_MS, "CPU Time");
initGraph(gpuGraph, GRAPH_RENDER_MS, "GPU Time");
glfwSetErrorCallback(errorcb);
#ifndef _WIN32 // don't require this on win32, and works with more cards
@ -154,7 +154,7 @@ int main(int argc, char** argv)
return -1;
}
if (testSpecified && testCount == 0)
if (testRequested && testCount == 0)
glfwSetWindowShouldClose(window, GL_TRUE);
glfwSwapInterval(0);
@ -165,7 +165,7 @@ int main(int argc, char** argv)
long long frameCounter = 0;
int sampleRate = 5;
bool success= true;
if(testSpecified)
if(testRequested)
prevt = 0.0f;
else
prevt = glfwGetTime();
@ -179,7 +179,7 @@ int main(int argc, char** argv)
std::array<float, 3> gpuTimes{};
int i, n;
if(testSpecified)
if(testRequested)
t=frameCounter/30.0f;
else
t = glfwGetTime();
@ -192,7 +192,7 @@ int main(int argc, char** argv)
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
if(testSpecified){
if(testRequested){
double angle = 2.0 * nvg::PI * testRemaining / (double)testCount;
mx=winWidth/2.0f+cos(angle)*winWidth/4.0f;
my=winHeight/2.0f+sin(angle)*winHeight/4.0f;
@ -214,11 +214,11 @@ int main(int argc, char** argv)
renderDemo(vg, (float)mx, (float)my, (float)winWidth, (float)winHeight, (float)t, blowup, &data);
if(!testSpecified){
renderGraph(vg, 5,5, &fps);
renderGraph(vg, 5+200+5,5, &cpuGraph);
if(!testRequested){
renderGraph(vg, 5,5, fps);
renderGraph(vg, 5+200+5,5, cpuGraph);
if (gpuTimer.supported) {
renderGraph(vg, 5+200+5+200+5,5, &gpuGraph);
renderGraph(vg, 5+200+5+200+5,5, gpuGraph);
}
}
vg.endFrame();
@ -226,13 +226,13 @@ int main(int argc, char** argv)
// Measure the CPU time taken excluding swap buffers (as the swap may wait for GPU)
cpuTime = glfwGetTime() - t;
updateGraph(&fps, (float)dt);
updateGraph(&cpuGraph, (float)cpuTime);
updateGraph(fps, (float)dt);
updateGraph(cpuGraph, (float)cpuTime);
// We may get multiple results.
n = stopGPUTimer(&gpuTimer, gpuTimes.data(), (int)gpuTimes.size());
for (i = 0; i < n; i++)
updateGraph(&gpuGraph, gpuTimes[i]);
updateGraph(gpuGraph, gpuTimes[i]);
if (testRemaining > 0 && frameCounter % sampleRate ==0) {
std::array<char, 256> fileName{};
@ -242,7 +242,7 @@ int main(int argc, char** argv)
testRemaining--;
if (testRemaining == 0)
glfwSetWindowShouldClose(window, GL_TRUE);
} else if (screenshot) {
} else if (screenshot&&!testRequested) {
screenshot = 0;
success&=saveScreenShot(fbWidth, fbHeight, premult, "dump.png");
}
@ -255,10 +255,10 @@ int main(int argc, char** argv)
nvg::deleteGL(vgOwner);
if (!testSpecified) {
printf("Average Frame Time: %.2f ms\n", getGraphAverage(&fps) * 1000.0f);
printf(" CPU Time: %.2f ms\n", getGraphAverage(&cpuGraph) * 1000.0f);
printf(" GPU Time: %.2f ms\n", getGraphAverage(&gpuGraph) * 1000.0f);
if (!testRequested) {
printf("Average Frame Time: %.2f ms\n", getGraphAverage(fps) * 1000.0f);
printf(" CPU Time: %.2f ms\n", getGraphAverage(cpuGraph) * 1000.0f);
printf(" GPU Time: %.2f ms\n", getGraphAverage(gpuGraph) * 1000.0f);
} else {
if(success)
printf("Test passed!\n");

View file

@ -65,7 +65,7 @@ int main()
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(fps, GRAPH_RENDER_FPS, "Frame Time");
glfwSetErrorCallback(errorcb);
@ -109,7 +109,7 @@ int main()
t = glfwGetTime();
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
updateGraph(fps, dt);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
@ -133,7 +133,7 @@ int main()
beginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
renderGraph(vg, 5,5, fps);
endFrame(vg);

View file

@ -65,7 +65,7 @@ int main()
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(fps, GRAPH_RENDER_FPS, "Frame Time");
glfwSetErrorCallback(errorcb);
@ -109,7 +109,7 @@ int main()
t = glfwGetTime();
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
updateGraph(fps, dt);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
@ -133,7 +133,7 @@ int main()
beginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
renderGraph(vg, 5,5, fps);
endFrame(vg);

View file

@ -78,39 +78,39 @@ int stopGPUTimer(GPUtimer* timer, float* times, int maxTimes)
}
void initGraph(PerfGraph* fps, int style, const std::string& name)
void initGraph(PerfGraph& graph, int style, const std::string& name)
{
fps->style = style;
fps->head = 0;
fps->values.fill(0.0f);
fps->name.fill('\0');
strncpy(fps->name.data(), name.c_str(), fps->name.size());
fps->name[fps->name.size()-1] = '\0';
graph.style = style;
graph.head = 0;
graph.values.fill(0.0f);
graph.name.fill('\0');
strncpy(graph.name.data(), name.c_str(), graph.name.size());
graph.name[graph.name.size()-1] = '\0';
}
void updateGraph(PerfGraph* fps, float frameTime)
void updateGraph(PerfGraph& graph, float frameTime)
{
fps->head = (fps->head+1) % GRAPH_HISTORY_COUNT;
fps->values[fps->head] = frameTime;
graph.head = (graph.head+1) % GRAPH_HISTORY_COUNT;
graph.values[graph.head] = frameTime;
}
float getGraphAverage(PerfGraph* fps)
float getGraphAverage(PerfGraph& graph)
{
int i;
float avg = 0;
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
avg += fps->values[i];
avg += graph.values[i];
}
return avg / (float)GRAPH_HISTORY_COUNT;
}
void renderGraph(nvg::Context& vg, float x, float y, PerfGraph* fps)
void renderGraph(nvg::Context& vg, float x, float y, PerfGraph& graph)
{
int i;
float avg, w, h;
std::array<char, 64> str{};
avg = getGraphAverage(fps);
avg = getGraphAverage(graph);
w = 200;
h = 35;
@ -122,18 +122,18 @@ void renderGraph(nvg::Context& vg, float x, float y, PerfGraph* fps)
vg.beginPath();
vg.moveTo( x, y+h);
if (fps->style == GRAPH_RENDER_FPS) {
if (graph.style == GRAPH_RENDER_FPS) {
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
float v = 1.0f / (0.00001f + fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT]);
float v = 1.0f / (0.00001f + graph.values[(graph.head+i) % GRAPH_HISTORY_COUNT]);
float vx, vy;
if (v > 80.0f) v = 80.0f;
vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w;
vy = y + h - ((v / 80.0f) * h);
vg.lineTo( vx, vy);
}
} else if (fps->style == GRAPH_RENDER_PERCENT) {
} else if (graph.style == GRAPH_RENDER_PERCENT) {
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
float v = fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT] * 1.0f;
float v = graph.values[(graph.head+i) % GRAPH_HISTORY_COUNT] * 1.0f;
float vx, vy;
if (v > 100.0f) v = 100.0f;
vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w;
@ -142,7 +142,7 @@ void renderGraph(nvg::Context& vg, float x, float y, PerfGraph* fps)
}
} else {
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
float v = fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT] * 1000.0f;
float v = graph.values[(graph.head+i) % GRAPH_HISTORY_COUNT] * 1000.0f;
float vx, vy;
if (v > 20.0f) v = 20.0f;
vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w;
@ -156,14 +156,14 @@ void renderGraph(nvg::Context& vg, float x, float y, PerfGraph* fps)
vg.fontFace( "sans");
if (fps->name[0] != '\0') {
if (graph.name[0] != '\0') {
vg.fontSize( 12.0f);
vg.textAlign( static_cast<int>(nvg::Align::Left | nvg::Align::Top));
vg.fillColor( nvg::rgba(240,240,240,192));
vg.text( x+3,y+3, fps->name.data(), NULL);
vg.text( x+3,y+3, graph.name.data(), NULL);
}
if (fps->style == GRAPH_RENDER_FPS) {
if (graph.style == GRAPH_RENDER_FPS) {
vg.fontSize( 15.0f);
vg.textAlign( static_cast<int>(nvg::Align::Right | nvg::Align::Top));
vg.fillColor( nvg::rgba(240,240,240,255));
@ -176,7 +176,7 @@ void renderGraph(nvg::Context& vg, float x, float y, PerfGraph* fps)
sprintf(str.data(), "%.2f ms", avg * 1000.0f);
vg.text( x+w-3,y+h-3, str.data(), NULL);
}
else if (fps->style == GRAPH_RENDER_PERCENT) {
else if (graph.style == GRAPH_RENDER_PERCENT) {
vg.fontSize( 15.0f);
vg.textAlign( static_cast<int>(nvg::Align::Right | nvg::Align::Top));
vg.fillColor( nvg::rgba(240,240,240,255));

View file

@ -19,10 +19,10 @@ struct PerfGraph {
};
typedef struct PerfGraph PerfGraph;
void initGraph(PerfGraph* fps, int style, const std::string& name);
void updateGraph(PerfGraph* fps, float frameTime);
void renderGraph(nvg::Context& vg, float x, float y, PerfGraph* fps);
float getGraphAverage(PerfGraph* fps);
void initGraph(PerfGraph& graph, int style, const std::string& name);
void updateGraph(PerfGraph& graph, float frameTime);
void renderGraph(nvg::Context& vg, float x, float y, PerfGraph& graph);
float getGraphAverage(PerfGraph& graph);
#define GPU_QUERY_COUNT 5
struct GPUtimer {