Refactor the "File → Export Image" command.

The existing code is horrible and needlessly platform-dependent.
Even worse, it causes a freeze on GTK. Instead of propping that up
with a few more crutches, just fix the root cause.
pull/168/merge
whitequark 2017-01-23 00:24:18 +00:00
parent bb2cc4aa56
commit 495a7ac166
4 changed files with 25 additions and 47 deletions

View File

@ -154,6 +154,7 @@ set(solvespace_core_SOURCES
drawconstraint.cpp drawconstraint.cpp
drawentity.cpp drawentity.cpp
entity.cpp entity.cpp
export.cpp
exportstep.cpp exportstep.cpp
exportvector.cpp exportvector.cpp
expr.cpp expr.cpp
@ -191,7 +192,6 @@ set(solvespace_core_SOURCES
srf/triangulate.cpp) srf/triangulate.cpp)
set(solvespace_core_gl_SOURCES set(solvespace_core_gl_SOURCES
export.cpp
solvespace.cpp) solvespace.cpp)
add_library(solvespace-core STATIC add_library(solvespace-core STATIC

View File

@ -885,26 +885,34 @@ void GraphicsWindow::Paint() {
/*outlineColor=*/Style::Color(Style::HOVERED)); /*outlineColor=*/Style::Color(Style::HOVERED));
} }
// If we've had a screenshot requested, take it now, before the UI is overlaid.
if(!SS.screenshotFile.empty()) {
FILE *f = ssfopen(SS.screenshotFile, "wb");
if(!f || !canvas->ReadFrame()->WritePng(f, /*flip=*/true)) {
Error("Couldn't write to '%s'", SS.screenshotFile.c_str());
}
if(f) fclose(f);
SS.screenshotFile.clear();
}
// And finally the toolbar. // And finally the toolbar.
if(SS.showToolbar) { if(SS.showToolbar) {
canvas->SetCamera(camera); canvas->SetCamera(camera);
ToolbarDraw(&uiCanvas); ToolbarDraw(&uiCanvas);
} }
// If we display UI elements, also display an fps counter. // Also display an fps counter.
if(SS.showToolbar) { RgbaColor renderTimeColor;
RgbaColor renderTimeColor; if(1000 / renderTime.count() < 60) {
if(1000 / renderTime.count() < 60) { // We aim for a steady 60fps; draw the counter in red when we're slower.
// We aim for a steady 60fps; draw the counter in red when we're slower. renderTimeColor = { 255, 0, 0, 255 };
renderTimeColor = { 255, 0, 0, 255 }; } else {
} else { renderTimeColor = { 255, 255, 255, 255 };
renderTimeColor = { 255, 255, 255, 255 };
}
uiCanvas.DrawBitmapText(ssprintf("rendered in %ld ms (%ld 1/s)",
(long)renderTime.count(),
(long)(1000/renderTime.count())),
5, 5, renderTimeColor);
} }
uiCanvas.DrawBitmapText(ssprintf("rendered in %ld ms (%ld 1/s)",
(long)renderTime.count(),
(long)(1000/renderTime.count())),
5, 5, renderTimeColor);
canvas->FlushFrame(); canvas->FlushFrame();
canvas->Clear(); canvas->Clear();

View File

@ -1117,39 +1117,8 @@ void SolveSpaceUI::ExportMeshAsThreeJsTo(FILE *f, const std::string &filename,
// rendering the view in the usual way and then copying the pixels. // rendering the view in the usual way and then copying the pixels.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void SolveSpaceUI::ExportAsPngTo(const std::string &filename) { void SolveSpaceUI::ExportAsPngTo(const std::string &filename) {
#if !defined(HEADLESS) screenshotFile = filename;
// No guarantee that the back buffer contains anything valid right now, // The rest of the work is done in the next redraw.
// so repaint the scene. And hide the toolbar too.
bool prevShowToolbar = SS.showToolbar;
SS.showToolbar = false;
// Somewhat hacky way to invoke glReadPixels without dragging in all OpenGL headers.
std::shared_ptr<ViewportCanvas> canvas = CreateRenderer();
canvas->SetCamera(SS.GW.GetCamera());
std::shared_ptr<Pixmap> screenshot;
#if !defined(WIN32)
GlOffscreen offscreen;
offscreen.Render((int)SS.GW.width, (int)SS.GW.height, [&] {
SS.GW.Paint();
screenshot = canvas->ReadFrame();
});
#else
SS.GW.Paint(); SS.GW.Paint();
screenshot = canvas->ReadFrame();
#endif
SS.showToolbar = prevShowToolbar;
FILE *f = ssfopen(filename, "wb");
if(!f || !screenshot->WritePng(f, /*flip=*/true)) {
Error("Couldn't write to '%s'", filename.c_str());
}
if(f) fclose(f);
#if !defined(WIN32)
offscreen.Clear();
#endif
return;
#endif
} }

View File

@ -676,6 +676,7 @@ public:
bool drawBackFaces; bool drawBackFaces;
bool checkClosedContour; bool checkClosedContour;
bool showToolbar; bool showToolbar;
std::string screenshotFile;
RgbaColor backgroundColor; RgbaColor backgroundColor;
bool exportShadedTriangles; bool exportShadedTriangles;
bool exportPwlCurves; bool exportPwlCurves;