Screenshot tool and saving/reading files works on android

This commit is contained in:
Yousef Khadadeh 2026-03-05 15:03:05 +03:00
parent 19983c7b1c
commit fe37c3348b
6 changed files with 30 additions and 58 deletions

View file

@ -103,7 +103,8 @@ void ScreenshotTool::gui_toolbox() {
auto world = w.lock();
if(world && world->drawProg.drawTool->get_type() == DrawingProgramToolType::SCREENSHOT) {
ScreenshotTool* screenshotTool = static_cast<ScreenshotTool*>(world->drawProg.drawTool.get());
screenshotTool->controls.screenshotSavePath = force_extension_on_path(p, setExtensionFilter.extensions);
screenshotTool->controls.screenshotSavePath = p;
screenshotTool->controls.screenshotSaveType = world->main.toolConfig.screenshot.selectedType;
screenshotTool->controls.setToTakeScreenshot = true;
}
}, "screenshot", true);
@ -281,24 +282,13 @@ bool ScreenshotTool::dragging_area_update(const Vector2f& camCursorPos) {
void ScreenshotTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) {
}
void ScreenshotTool::take_screenshot(const std::filesystem::path& filePath) {
void ScreenshotTool::take_screenshot(const std::filesystem::path& filePath, ScreenshotType screenshotType) {
if(controls.imageSize.x() <= 0 || controls.imageSize.y() <= 0) {
std::cout << "[ScreenshotTool::take_screenshot] Image size is 0 or negative" << std::endl;
return;
}
std::string ext = filePath.extension().string();
size_t extType = SCREENSHOT_JPG;
if(ext == ".jpg" || ext == ".jpeg")
extType = SCREENSHOT_JPG;
else if(ext == ".png")
extType = SCREENSHOT_PNG;
else if(ext == ".webp")
extType = SCREENSHOT_WEBP;
else if(ext == ".svg")
extType = SCREENSHOT_SVG;
if(extType != SCREENSHOT_SVG) {
if(screenshotType != SCREENSHOT_SVG) {
size_t imageByteSize = (size_t)controls.imageSize.x() * (size_t)controls.imageSize.y() * 4;
size_t imageRowSize = 4 * controls.imageSize.x();
@ -315,12 +305,12 @@ void ScreenshotTool::take_screenshot(const std::filesystem::path& filePath) {
for(int i = 0; i < controls.imageSize.x(); i += drawP.world.main.window.size.x())
for(int j = 0; j < controls.imageSize.y(); j += drawP.world.main.window.size.y())
take_screenshot_area_hw(surface, screenshotCanvas, finalImgRawData.data(), controls.imageSize, Vector2i{i, j}, Vector2i{std::min(drawP.world.main.window.size.x(), controls.imageSize.x() - i), std::min(drawP.world.main.window.size.y(), controls.imageSize.y() - j)}, drawP.world.main.window.size, extType != 0 && controls.transparentBackground);
take_screenshot_area_hw(surface, screenshotCanvas, finalImgRawData.data(), controls.imageSize, Vector2i{i, j}, Vector2i{std::min(drawP.world.main.window.size.x(), controls.imageSize.x() - i), std::min(drawP.world.main.window.size.y(), controls.imageSize.y() - j)}, drawP.world.main.window.size, screenshotType != SCREENSHOT_JPG && controls.transparentBackground);
bool success = false;
SkDynamicMemoryWStream out;
switch(extType) {
switch(screenshotType) {
case SCREENSHOT_JPG:
success = SkJpegEncoder::Encode(&out, finalImgData, {});
break;
@ -341,10 +331,9 @@ void ScreenshotTool::take_screenshot(const std::filesystem::path& filePath) {
#ifndef __EMSCRIPTEN__
try {
std::ofstream fi(filePath, std::ios::out | std::ios::binary);
auto skData = out.detachAsData();
fi.write((const char*)skData->bytes(), skData->size());
fi.close();
if(!SDL_SaveFile(filePath.c_str(), skData->bytes(), skData->size()))
throw std::runtime_error("SDL_SaveFile failed with error: " + std::string(SDL_GetError()));
}
catch(const std::exception& e) {
Logger::get().log("WORLDFATAL", std::string("[ScreenshotTool::take_screenshot] Save screenshot error: ") + e.what());
@ -372,10 +361,9 @@ void ScreenshotTool::take_screenshot(const std::filesystem::path& filePath) {
#ifndef __EMSCRIPTEN__
try {
std::ofstream fi(filePath, std::ios::out | std::ios::binary);
auto skData = out.detachAsData();
fi.write((const char*)skData->bytes(), skData->size());
fi.close();
if(!SDL_SaveFile(filePath.c_str(), skData->bytes(), skData->size()))
throw std::runtime_error("SDL_SaveFile failed with error: " + std::string(SDL_GetError()));
}
catch(const std::exception& e) {
Logger::get().log("WORLDFATAL", std::string("[ScreenshotTool::take_screenshot] Save screenshot error: ") + e.what());
@ -467,7 +455,7 @@ void ScreenshotTool::switch_tool(DrawingProgramToolType newTool) {
void ScreenshotTool::tool_update() {
if(controls.setToTakeScreenshot) {
controls.setToTakeScreenshot = false;
take_screenshot(controls.screenshotSavePath);
take_screenshot(controls.screenshotSavePath, controls.screenshotSaveType);
}
if(controls.selectionMode == ScreenshotControls::SelectionMode::SELECTION_EXISTS)
selection_exists_update();

View file

@ -29,7 +29,7 @@ class ScreenshotTool : public DrawingProgramToolBase {
};
private:
void commit_rect();
void take_screenshot(const std::filesystem::path& filePath);
void take_screenshot(const std::filesystem::path& filePath, ScreenshotType screenshotType);
void take_screenshot_area_hw(const sk_sp<SkSurface>& surface, SkCanvas* canvas, void* fullImgRawData, const Vector2i& fullImageSize, const Vector2i& sectionImagePos, const Vector2i& sectionImageSize, const Vector2i& canvasSize, bool transparentBackground);
void take_screenshot_svg(SkCanvas* canvas, bool transparentBackground);
@ -47,7 +47,7 @@ class ScreenshotTool : public DrawingProgramToolBase {
DRAGGING_BORDER,
SELECTION_EXISTS,
DRAGGING_AREA
} selectionMode;
} selectionMode = SelectionMode::NO_SELECTION;
int dragType = 0;
Vector2i imageSize = {0, 0};
std::array<SCollision::Circle<float>, 8> circles;
@ -59,6 +59,7 @@ class ScreenshotTool : public DrawingProgramToolBase {
std::atomic<bool> setToTakeScreenshot = false;
std::filesystem::path screenshotSavePath;
ScreenshotType screenshotSaveType;
} controls;
bool dragging_border_update(const Vector2f& camCursorPos);
bool selection_exists_update();

View file

@ -108,6 +108,7 @@ struct UpdateInputData {
std::vector<SCollision::Circle<float>> hoverObstructingCircles;
bool acceptingTextInput = false;
float deltaTime = 0.0f;
bool isTouch = true;
std::shared_ptr<FontData> fonts;
sk_sp<SkTypeface> textTypeface;

View file

@ -85,36 +85,17 @@ void ResourceManager::update() {
}
NetworkingObjects::NetObjTemporaryPtr<ResourceData> ResourceManager::add_resource_file(const std::filesystem::path& filePath) {
// https://nullptr.org/cpp-read-file-into-string/
std::ifstream file(filePath, std::ios::in | std::ios::binary | std::ios::ate);
if(!file.is_open()) {
Logger::get().log("INFO", "[ResourceManager::add_resource_file] Could not open file " + filePath.string());
return {};
}
size_t resourcesize;
auto tellgResult = file.tellg();
if(tellgResult == -1) {
Logger::get().log("INFO", "[ResourceManager::add_resource_file] tellg failed for file " + filePath.string());
return {};
}
resourcesize = static_cast<size_t>(tellgResult);
file.seekg(0, std::ios_base::beg);
ResourceData resource;
resource.data = std::make_shared<std::string>();
resource.name = std::filesystem::path(filePath).filename().string();
std::string& toPlaceIn = *resource.data;
toPlaceIn.resize(resourcesize);
file.read(toPlaceIn.data(), resourcesize);
file.close();
try {
*resource.data = read_file_to_string(filePath);
}
catch(...) {
Logger::get().log("INFO", "[ResourceManager::add_resource_file] Could not open file " + filePath.string());
return {};
}
Logger::get().log("INFO", "[ResourceManager::add_resource_file] Successfully read file " + filePath.string());

View file

@ -1,6 +1,7 @@
#include "Toolbar.hpp"
#include "DrawingProgram/Tools/DrawingProgramToolBase.hpp"
#include "DrawingProgram/Tools/ScreenshotTool.hpp"
#include "FileHelpers.hpp"
#include "Helpers/ConvertVec.hpp"
#include "Helpers/FileDownloader.hpp"
#include "Helpers/MathExtras.hpp"
@ -746,7 +747,7 @@ void Toolbar::top_toolbar() {
open_file_selector("Open File", {{"Any File", "*"}}, [w = make_weak_ptr(main.world)](const std::filesystem::path& p, const auto& e) {
auto wLock = w.lock();
if(wLock)
wLock->drawProg.add_file_to_canvas_by_path(p.string(), wLock->main.window.size.cast<float>() / 2.0f, false);
wLock->drawProg.add_file_to_canvas_by_path(p, wLock->main.window.size.cast<float>() / 2.0f, false);
else
Logger::get().log("INFO", "Loading image to canvas that has been destroyed");
});
@ -2252,7 +2253,7 @@ void Toolbar::file_picker_gui() {
if(gui.text_button_wide("filepicker done", "Done") || isDoneByDoubleClick) {
if(!filePicker.fileName.empty()) {
pathToRet = filePicker.currentSearchPath / filePicker.fileName;
filePicker.postSelectionFunc(pathToRet, filePicker.extensionFiltersComplete[filePicker.extensionSelected]);
filePicker.postSelectionFunc(force_extension_on_path(pathToRet, filePicker.extensionFiltersComplete[filePicker.extensionSelected].extensions), filePicker.extensionFiltersComplete[filePicker.extensionSelected]);
}
filePicker.isOpen = false;
}
@ -2403,6 +2404,7 @@ void Toolbar::start_gui() {
io->hoverObstructed = false;
io->hoverObstructingAABBs.clear();
io->hoverObstructingCircles.clear();
io->isTouch = main.input.isTouchDevice;
gui.begin();
}

View file

@ -440,7 +440,7 @@ void World::autosave_to_directory(const std::filesystem::path& directoryToSaveAt
void World::save_to_file(const std::filesystem::path& filePathToSaveAt) {
try {
filePath = force_extension_on_path(filePathToSaveAt, FILE_EXTENSION);
filePath = filePathToSaveAt;
std::stringstream f;
f.write(VersionConstants::CURRENT_SAVEFILE_HEADER.c_str(), VersionConstants::SAVEFILE_HEADER_LEN);
@ -468,9 +468,8 @@ void World::save_to_file(const std::filesystem::path& filePathToSaveAt) {
f.view()
);
#else
std::ofstream fi(filePath, std::ios::out | std::ios::binary);
fi << f.view();
fi.close();
if(!SDL_SaveFile(filePath.c_str(), f.view().data(), f.view().size()))
throw std::runtime_error("SDL_SaveFile failed with error: " + std::string(SDL_GetError()));
#endif
Logger::get().log("USERINFO", "File saved");
@ -489,7 +488,7 @@ void World::load_empty_canvas() {
}
void World::load_from_file(const std::filesystem::path& filePathToLoadFrom, std::string_view buffer) {
filePath = force_extension_on_path(filePathToLoadFrom, FILE_EXTENSION);
filePath = filePathToLoadFrom;
std::string byteDataFromFile;