[client,sdl] added resource manager

This commit is contained in:
Armin Novak
2023-12-18 23:24:34 +01:00
committed by akallabeth
parent 14a4a6a2e2
commit 41665700bb
20 changed files with 496 additions and 193 deletions

View File

@@ -98,8 +98,9 @@ set(LIBS
freerdp
freerdp-client
Threads::Threads
sdl_client_res
dialogs
aad-view
aad-view
)
add_executable(${PROJECT_NAME}

View File

@@ -21,8 +21,7 @@ set(SRCS
set(LIBS
${SDL2_LIBRARIES}
font
icon
sdl_client_res
winpr
)
@@ -53,8 +52,7 @@ endmacro()
find_sdl_component(SDL2_ttf)
find_sdl_component(SDL2_image)
add_subdirectory(font)
add_subdirectory(icon)
add_subdirectory(res)
add_library(dialogs STATIC
${SRCS}

View File

@@ -1,11 +0,0 @@
add_executable(
convert_font_to_c
convert_font_to_c.cpp
)
add_library(font OBJECT
opensans_variable_font.hpp
opensans_variable_font.cpp
)
set_property(TARGET font PROPERTY POSITION_INDEPENDENT_CODE ON)

View File

@@ -1,121 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <string>
#define BLOCK_SIZE 8192
#define LINEWIDTH 80
static void usage(const char* prg)
{
fprintf(stderr, "%s <font file> <buffer file without extension> <buffer name>\n", prg);
}
static int write_header(FILE* out, const char* outname, const char* buffername, const char* font,
size_t size)
{
std::string header = outname;
auto pos = header.find_last_of("/");
if (pos != std::string::npos)
header = header.substr(pos + 1);
pos = header.find_last_of("\\");
if (pos != std::string::npos)
header = header.substr(pos + 1);
pos = header.find_last_of(".");
if (pos != std::string::npos)
header = header.substr(0, pos);
fprintf(out, "/* AUTOGENERATED file, do not edit\n");
fprintf(out, " *\n");
fprintf(out, " * contains the converted font %s\n", font);
fprintf(out, " */\n");
fprintf(out, "#include <vector>\n");
fprintf(out, "#include \"%s.hpp\"\n", header.c_str());
fprintf(out, "\n");
fprintf(out, "static std::vector<unsigned char> init();\n");
fprintf(out, "const std::vector<unsigned char> %s = init();\n\n", buffername);
fprintf(out, "std::vector<unsigned char> init() {\n");
fprintf(out, "static const unsigned char data[] = {\n");
return 0;
}
static int read(FILE* out, const char* font, const char* outname, const char* buffername)
{
FILE* fp = fopen(font, "rb");
if (!fp)
{
fprintf(stderr, "Failed to open font file '%s'\n", font);
return -11;
}
fseek(fp, 0, SEEK_END);
off_t size = ftell(fp);
fseek(fp, 0, SEEK_SET);
const int rc = write_header(out, outname, buffername, font, static_cast<size_t>(size));
if (rc != 0)
{
fclose(fp);
return -12;
}
int first = 1;
while (!feof(fp))
{
char buffer[BLOCK_SIZE] = {};
const size_t read = fread(buffer, 1, sizeof(buffer), fp);
for (size_t x = 0; x < read; x++)
{
if (!first)
fprintf(out, ",");
first = 0;
fprintf(out, "0x%02x", buffer[x] & 0xFF);
if ((x % (LINEWIDTH / 5)) == 0)
fprintf(out, "\n");
}
}
fclose(fp);
return rc;
}
static int write_trailer(FILE* out)
{
fprintf(out, "};\n");
fprintf(out, "return std::vector<unsigned char>(data, data + sizeof(data));\n");
fprintf(out, "};\n");
return 0;
}
int main(int argc, char* argv[])
{
int rc = -3;
if (argc != 4)
{
usage(argv[0]);
return -1;
}
const char* font = argv[1];
std::string header = argv[2];
const char* name = argv[3];
header += ".cpp";
FILE* fp = fopen(header.c_str(), "w");
if (!fp)
{
fprintf(stderr, "Failed to open header file '%s'", header.c_str());
return -2;
}
rc = read(fp, font, header.c_str(), name);
if (rc != 0)
goto fail;
rc = write_trailer(fp);
fail:
fclose(fp);
return rc;
}

View File

@@ -1,5 +0,0 @@
#pragma once
#include <vector>
extern const std::vector<unsigned char> font_buffer;

View File

@@ -1,5 +0,0 @@
add_library(icon OBJECT
FreeRDP_Icon.hpp
FreeRDP_Icon.cpp
)
set_property(TARGET font PROPERTY POSITION_INDEPENDENT_CODE ON)

View File

@@ -1,7 +0,0 @@
#pragma once
#include <vector>
#include <string>
extern const std::vector<unsigned char> FreeRDP_Icon_buffer;
extern const std::string FreeRDP_Icon_buffer_type;

View File

@@ -0,0 +1,37 @@
add_executable(freerdp-res2bin
convert_res_to_c.cpp
)
set(SRCS
sdl_resource_manager.cpp
sdl_resource_manager.hpp
)
option(SDL_USE_COMPILED_RESOURCES "Compile in images/fonts" ON)
if (SDL_USE_COMPILED_RESOURCES)
list(APPEND SRCS
sdl_resource_file.cpp
sdl_resource_file.hpp
)
file(GLOB_RECURSE RES_CPP_FILES
LIST_DIRECTORIES false
"bin/*.cpp"
)
file(GLOB_RECURSE RES_HDR_FILES
LIST_DIRECTORIES false
"bin/*.hpp"
)
list(APPEND RES_FILES
${RES_CPP_FILES}
${RES_HDR_FILES}
)
add_definitions(-DSDL_USE_COMPILED_RESOURCES)
endif()
add_library(sdl_client_res OBJECT
${RES_FILES}
${SRCS}
)
set_property(TARGET sdl_client_res PROPERTY POSITION_INDEPENDENT_CODE ON)

View File

@@ -1,15 +1,25 @@
/* AUTOGENERATED file, do not edit
*
* contains the converted font resources/FreeRDP_Icon.svg
* generated by '"freerdp-res2bin"'
*
* contains the converted file 'FreeRDP_Icon.svg'
*/
#include <vector>
#include "FreeRDP_Icon.hpp"
#include "FreeRDP_Icon_svg.hpp"
const std::string FreeRDP_Icon_buffer_type = "svg";
static std::vector<unsigned char> init();
const std::vector<unsigned char> FreeRDP_Icon_buffer = init();
std::string FreeRDP_Icon_svg::name()
{
return "FreeRDP_Icon.svg";
}
std::string FreeRDP_Icon_svg::type()
{
return "images";
}
std::vector<unsigned char> init()
const SDLResourceFile FreeRDP_Icon_svg::_initializer(type(), name(), init());
std::vector<unsigned char> FreeRDP_Icon_svg::init()
{
static const unsigned char data[] = {
0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22,
@@ -352,5 +362,6 @@ std::vector<unsigned char> init()
0x23, 0x30, 0x37, 0x33, 0x36, 0x35, 0x33, 0x22, 0x20, 0x2f, 0x3e, 0x0a, 0x3c, 0x2f, 0x67,
0x3e, 0x0a, 0x3c, 0x2f, 0x73, 0x76, 0x67, 0x3e
};
return std::vector<unsigned char>(data, data + sizeof(data));
};
}

View File

@@ -0,0 +1,25 @@
/* AUTOGENERATED file, do not edit
*
* generated by '"freerdp-res2bin"'
*
* contains the converted file 'FreeRDP_Icon.svg'
*/
#pragma once
#include <vector>
#include <string>
#include "../sdl_resource_file.hpp"
class FreeRDP_Icon_svg
{
public:
FreeRDP_Icon_svg() = delete;
static std::string name();
static std::string type();
private:
static std::vector<unsigned char> init();
static const SDLResourceFile _initializer;
};

View File

@@ -1,14 +1,25 @@
/* AUTOGENERATED file, do not edit
*
* contains the converted font OpenSans-VariableFont_wdth,wght.ttf
* generated by '"freerdp-res2bin"'
*
* contains the converted file 'OpenSans-VariableFont_wdth,wght.ttf'
*/
#include <vector>
#include "opensans_variable_font.hpp"
#include "OpenSans_VariableFont_wdth_wght_ttf.hpp"
static std::vector<unsigned char> init();
const std::vector<unsigned char> font_buffer = init();
std::string OpenSans_VariableFont_wdth_wght_ttf::name()
{
return "OpenSans-VariableFont_wdth,wght.ttf";
}
std::string OpenSans_VariableFont_wdth_wght_ttf::type()
{
return "fonts";
}
std::vector<unsigned char> init()
const SDLResourceFile OpenSans_VariableFont_wdth_wght_ttf::_initializer(type(), name(), init());
std::vector<unsigned char> OpenSans_VariableFont_wdth_wght_ttf::init()
{
static const unsigned char data[] = {
0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, 0x04, 0x00, 0x70, 0x47, 0x44, 0x45,
@@ -35326,5 +35337,6 @@ std::vector<unsigned char> init()
0x06, 0x81, 0x85, 0x80, 0x02, 0xc1, 0x00, 0xe2, 0x81, 0x85, 0x80, 0x40, 0xff, 0x5c, 0x80,
0x00, 0xe4, 0x81, 0x85, 0x00
};
return std::vector<unsigned char>(data, data + sizeof(data));
}

View File

@@ -0,0 +1,25 @@
/* AUTOGENERATED file, do not edit
*
* generated by '"freerdp-res2bin"'
*
* contains the converted file 'OpenSans-VariableFont_wdth,wght.ttf'
*/
#pragma once
#include <vector>
#include <string>
#include "../sdl_resource_file.hpp"
class OpenSans_VariableFont_wdth_wght_ttf
{
public:
OpenSans_VariableFont_wdth_wght_ttf() = delete;
static std::string name();
static std::string type();
private:
static std::vector<unsigned char> init();
static const SDLResourceFile _initializer;
};

View File

@@ -0,0 +1,182 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string>
#include <filesystem>
#include <fstream>
#include <algorithm>
#include <iostream>
static void usage(const char* prg)
{
std::cerr << prg << " <file> <type> <dst path>" << std::endl;
}
static int write_comment_header(std::ostream& out, const std::filesystem::path& prg,
const std::string& fname)
{
out << "/* AUTOGENERATED file, do not edit" << std::endl
<< " *" << std::endl
<< " * generated by '" << prg.filename() << "'" << std::endl
<< " *" << std::endl
<< " * contains the converted file '" << fname << "'" << std::endl
<< " */" << std::endl
<< std::endl;
return 0;
}
static int write_cpp_header(std::ostream& out, const std::filesystem::path& prg,
const std::string& fname, const std::string& name,
const std::string& type)
{
auto rc = write_comment_header(out, prg, fname);
if (rc != 0)
return rc;
out << "#include <vector>" << std::endl
<< "#include \"" << name << ".hpp\"" << std::endl
<< std::endl
<< "std::string " << name << "::name() {" << std::endl
<< "return \"" << fname << "\";" << std::endl
<< "}" << std::endl
<< "std::string " << name << "::type() {" << std::endl
<< "return \"" << type << "\";" << std::endl
<< "}" << std::endl
<< std::endl
<< "const SDLResourceFile " << name << "::_initializer(type(), name(), init());"
<< std::endl
<< std::endl
<< "std::vector<unsigned char> " << name << "::init() {" << std::endl
<< "static const unsigned char data[] = {" << std::endl;
return 0;
}
static int readwrite(std::ofstream& out, std::ifstream& ifs)
{
size_t pos = 0;
char c = 0;
while (ifs.read(&c, 1) && ifs.good())
{
unsigned val = c & 0xff;
out << "0x" << std::hex << std::setfill('0') << std::setw(2) << val;
if (ifs.peek() != EOF)
out << ",";
if ((pos++ % 16) == 15)
out << std::endl;
}
return 0;
}
static int write_cpp_trailer(std::ostream& out)
{
out << std::endl;
out << "};" << std::endl;
out << std::endl;
out << "return std::vector<unsigned char>(data, data + sizeof(data));" << std::endl;
out << "}" << std::endl;
return 0;
}
static int write_hpp_header(const std::filesystem::path prg, const std::filesystem::path& file,
const std::string& name, const std::string& fname)
{
std::ofstream out;
out.open(file);
auto rc = write_comment_header(out, prg, fname);
if (rc != 0)
return rc;
out << "#pragma once" << std::endl
<< std::endl
<< "#include <vector>" << std::endl
<< "#include <string>" << std::endl
<< "#include \"../sdl_resource_file.hpp\"" << std::endl
<< std::endl
<< "class " << name << " {" << std::endl
<< "public:" << std::endl
<< name << "() = delete;" << std::endl
<< std::endl
<< "static std::string name();" << std::endl
<< "static std::string type();" << std::endl
<< std::endl
<< "private:" << std::endl
<< "static std::vector<unsigned char> init();" << std::endl
<< "static const SDLResourceFile _initializer;" << std::endl
<< std::endl
<< "};" << std::endl;
return 0;
}
int main(int argc, char* argv[])
{
std::filesystem::path prg(argv[0]);
if (argc != 4)
{
usage(argv[0]);
return -1;
}
std::filesystem::path file(argv[1]);
std::string etype = argv[2];
std::filesystem::path dst(argv[3]);
auto name = file.filename().string();
/* replace some common symbols in file name not allowed for c++ */
std::replace(name.begin(), name.end(), '.', '_');
std::replace(name.begin(), name.end(), ';', '_');
std::replace(name.begin(), name.end(), ',', '_');
std::replace(name.begin(), name.end(), ' ', '_');
std::replace(name.begin(), name.end(), '\t', '_');
std::replace(name.begin(), name.end(), '-', '_');
dst /= name + ".cpp";
std::filesystem::path hdr(argv[3]);
hdr /= name + ".hpp";
std::ofstream out;
out.open(dst);
if (!out.is_open())
{
std::cerr << "Failed to open output file '" << dst << "'" << std::endl;
return -2;
}
std::ifstream ifs(file, std::ios::in | std::ios::binary);
if (!ifs.is_open())
{
std::cerr << "Failed to open input file '" << file << "'" << std::endl;
return -3;
}
auto rc = write_cpp_header(out, prg, file.filename(), name, etype);
if (rc != 0)
return -1;
rc = readwrite(out, ifs);
if (rc != 0)
return rc;
rc = write_cpp_trailer(out);
if (rc != 0)
return rc;
return write_hpp_header(prg, hdr, name, file.filename());
}

View File

@@ -0,0 +1,25 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sdl_resource_file.hpp"
#include "sdl_resource_manager.hpp"
SDLResourceFile::SDLResourceFile(const std::string& type, const std::string& id,
const std::vector<unsigned char>& data)
{
SDLResourceManager::insert(type, id, data);
}

View File

@@ -0,0 +1,33 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <vector>
class SDLResourceFile
{
public:
SDLResourceFile(const std::string& type, const std::string& id,
const std::vector<unsigned char>& data);
virtual ~SDLResourceFile() = default;
private:
SDLResourceFile(const SDLResourceFile& other) = delete;
SDLResourceFile(const SDLResourceFile&& other) = delete;
};

View File

@@ -0,0 +1,64 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sdl_resource_manager.hpp"
#include <filesystem>
#include <iostream>
std::map<std::string, std::vector<unsigned char>> SDLResourceManager::_resources;
SDL_RWops* SDLResourceManager::get(const std::string& type, const std::string& id)
{
std::string uuid = type + "/" + id;
#if defined(SDL_USE_COMPILED_RESOURCES)
auto val = _resources.find(uuid);
if (val == _resources.end())
return nullptr;
auto& v = _resources[uuid];
return SDL_RWFromConstMem(v.data(), v.size());
#else
std::filesystem::path path(type);
path /= id;
if (!std::filesystem::exists(path))
{
std::cerr << "sdl-freerdp expects resource '" << uuid << "' at location "
<< std::filesystem::absolute(path) << std::endl;
std::cerr << "file not found, application will fail" << std::endl;
}
return SDL_RWFromFile(path.native().c_str(), "rb");
#endif
}
const std::string SDLResourceManager::typeFonts()
{
return "fonts";
}
const std::string SDLResourceManager::typeImages()
{
return "images";
}
void SDLResourceManager::insert(const std::string& type, const std::string& id,
const std::vector<unsigned char>& data)
{
std::string uuid = type + "/" + id;
_resources.emplace(uuid, data);
}

View File

@@ -0,0 +1,47 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2023 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <map>
#include <vector>
#include <SDL.h>
class SDLResourceManager
{
friend class SDLResourceFile;
public:
static SDL_RWops* get(const std::string& type, const std::string& id);
static const std::string typeFonts();
static const std::string typeImages();
protected:
static void insert(const std::string& type, const std::string& id,
const std::vector<unsigned char>& data);
private:
static std::map<std::string, std::vector<unsigned char>> _resources;
private:
SDLResourceManager() = delete;
SDLResourceManager(const SDLResourceManager& other) = delete;
SDLResourceManager(const SDLResourceManager&& other) = delete;
~SDLResourceManager() = delete;
};

View File

@@ -22,7 +22,7 @@
#include "sdl_connection_dialog.hpp"
#include "../sdl_utils.hpp"
#include "../sdl_freerdp.hpp"
#include "icon/FreeRDP_Icon.hpp"
#include "res/sdl_resource_manager.hpp"
static const SDL_Color backgroundcolor = { 0x38, 0x36, 0x35, 0xff };
static const SDL_Color textcolor = { 0xd1, 0xcf, 0xcd, 0xff };
@@ -336,11 +336,11 @@ bool SDLConnectionDialog::createWindow()
return false;
}
SdlWidget icon = { _renderer,
{ 0, vpadding, widget_width / 4,
total_height - 3 * vpadding - widget_height },
FreeRDP_Icon_buffer,
FreeRDP_Icon_buffer_type };
SdlWidget icon = {
_renderer,
{ 0, vpadding, widget_width / 4, total_height - 3 * vpadding - widget_height },
SDLResourceManager::get(SDLResourceManager::typeImages(), "FreeRDP_Icon.svg")
};
_list.emplace_back(std::move(icon));
SDL_Rect rect = { widget_width / 4, vpadding, widget_width * 3 / 4,
total_height - 3 * vpadding - widget_height };

View File

@@ -27,7 +27,7 @@
#include "sdl_widget.hpp"
#include "../sdl_utils.hpp"
#include "font/opensans_variable_font.hpp"
#include "res/sdl_resource_manager.hpp"
#include <freerdp/log.h>
@@ -42,9 +42,10 @@ SdlWidget::SdlWidget(SDL_Renderer* renderer, const SDL_Rect& rect, bool input)
{
assert(renderer);
auto ops = SDL_RWFromConstMem(font_buffer.data(), static_cast<int>(font_buffer.size()));
auto ops = SDLResourceManager::get(SDLResourceManager::typeFonts(),
"OpenSans-VariableFont_wdth,wght.ttf");
if (!ops)
widget_log_error(-1, "SDL_RWFromConstMem");
widget_log_error(-1, "SDLResourceManager::get");
else
{
_font = TTF_OpenFontRW(ops, 1, 64);
@@ -52,24 +53,17 @@ SdlWidget::SdlWidget(SDL_Renderer* renderer, const SDL_Rect& rect, bool input)
}
}
SdlWidget::SdlWidget(SDL_Renderer* renderer, const SDL_Rect& rect, const std::string& path)
: _rect(rect)
SdlWidget::SdlWidget(SDL_Renderer* renderer, const SDL_Rect& rect, SDL_RWops* ops) : _rect(rect)
{
_image = IMG_LoadTexture(renderer, path.c_str());
if (!_image)
widget_log_error(-1, "SDL_RWFromConstMem");
}
SdlWidget::SdlWidget(SDL_Renderer* renderer, const SDL_Rect& rect,
const std::vector<unsigned char>& image, const std::string& type)
: _rect(rect)
{
auto ops = SDL_RWFromConstMem(image.data(), static_cast<int>(image.size()));
if (!ops)
widget_log_error(-1, "SDL_RWFromConstMem");
else
{
_image = IMG_LoadTextureTyped_RW(renderer, ops, 1, type.c_str());
ops = SDLResourceManager::get(SDLResourceManager::typeImages(), "FreeRDP_Icon.svg");
if (!ops)
widget_log_error(-1, "SDLResourceManager::get");
}
if (ops)
{
_image = IMG_LoadTexture_RW(renderer, ops, 1);
if (!_image)
widget_log_error(-1, "IMG_LoadTextureTyped_RW");
}

View File

@@ -52,9 +52,7 @@ class SdlWidget
{
public:
SdlWidget(SDL_Renderer* renderer, const SDL_Rect& rect, bool input);
SdlWidget(SDL_Renderer* renderer, const SDL_Rect& rect, const std::string& path);
SdlWidget(SDL_Renderer* renderer, const SDL_Rect& rect, const std::vector<unsigned char>& image,
const std::string& type = "SVG");
SdlWidget(SDL_Renderer* renderer, const SDL_Rect& rect, SDL_RWops* ops);
SdlWidget(SdlWidget&& other) noexcept;
virtual ~SdlWidget();