|
@@ -52,14 +52,15 @@
|
|
|
namespace Rml {
|
|
namespace Rml {
|
|
|
namespace SVG {
|
|
namespace SVG {
|
|
|
struct SVGKey {
|
|
struct SVGKey {
|
|
|
- String path;
|
|
|
|
|
|
|
+ String source_id;
|
|
|
Vector2i dimensions;
|
|
Vector2i dimensions;
|
|
|
bool crop_to_content;
|
|
bool crop_to_content;
|
|
|
ColourbPremultiplied colour;
|
|
ColourbPremultiplied colour;
|
|
|
|
|
|
|
|
friend bool operator==(const SVGKey& lhs, const SVGKey& rhs)
|
|
friend bool operator==(const SVGKey& lhs, const SVGKey& rhs)
|
|
|
{
|
|
{
|
|
|
- return lhs.path == rhs.path && lhs.dimensions == rhs.dimensions && lhs.crop_to_content == rhs.crop_to_content && lhs.colour == rhs.colour;
|
|
|
|
|
|
|
+ return lhs.source_id == rhs.source_id && lhs.dimensions == rhs.dimensions && lhs.crop_to_content == rhs.crop_to_content &&
|
|
|
|
|
+ lhs.colour == rhs.colour;
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
} // namespace SVG
|
|
} // namespace SVG
|
|
@@ -71,7 +72,7 @@ struct hash<::Rml::SVG::SVGKey> {
|
|
|
size_t operator()(const ::Rml::SVG::SVGKey& key) const noexcept
|
|
size_t operator()(const ::Rml::SVG::SVGKey& key) const noexcept
|
|
|
{
|
|
{
|
|
|
size_t hash = 0;
|
|
size_t hash = 0;
|
|
|
- Rml::Utilities::HashCombine(hash, key.path);
|
|
|
|
|
|
|
+ Rml::Utilities::HashCombine(hash, key.source_id);
|
|
|
Rml::Utilities::HashCombine(hash, key.dimensions.x);
|
|
Rml::Utilities::HashCombine(hash, key.dimensions.x);
|
|
|
Rml::Utilities::HashCombine(hash, key.dimensions.y);
|
|
Rml::Utilities::HashCombine(hash, key.dimensions.y);
|
|
|
Rml::Utilities::HashCombine(hash, key.crop_to_content);
|
|
Rml::Utilities::HashCombine(hash, key.crop_to_content);
|
|
@@ -85,8 +86,8 @@ struct hash<::Rml::SVG::SVGKey> {
|
|
|
namespace Rml {
|
|
namespace Rml {
|
|
|
namespace SVG {
|
|
namespace SVG {
|
|
|
|
|
|
|
|
- static SharedPtr<SVGData> GetHandle(RenderManager& render_manager, String path, Vector2i dimensions, bool crop_to_content,
|
|
|
|
|
- ColourbPremultiplied colour);
|
|
|
|
|
|
|
+ static SharedPtr<SVGData> GetHandle(RenderManager& render_manager, String source_id, const String& source, SVGCache::SourceType source_type,
|
|
|
|
|
+ Vector2i dimensions, bool crop_to_content, ColourbPremultiplied colour);
|
|
|
static void ReleaseHandle(SVGData* handle);
|
|
static void ReleaseHandle(SVGData* handle);
|
|
|
|
|
|
|
|
struct SVGGeometry {
|
|
struct SVGGeometry {
|
|
@@ -152,54 +153,62 @@ namespace SVG {
|
|
|
return default_value;
|
|
return default_value;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- static SharedPtr<SVGData> GetHandle(RenderManager& render_manager, String move_from_path, const Vector2i dimensions, const bool crop_to_content,
|
|
|
|
|
- const ColourbPremultiplied colour)
|
|
|
|
|
|
|
+ static SharedPtr<SVGData> GetHandle(RenderManager& render_manager, String move_from_id, const String& source, SVGCache::SourceType source_type,
|
|
|
|
|
+ const Vector2i dimensions, const bool crop_to_content, const ColourbPremultiplied colour)
|
|
|
{
|
|
{
|
|
|
- SVGKey key{std::move(move_from_path), dimensions, crop_to_content, colour};
|
|
|
|
|
- const String& path = key.path;
|
|
|
|
|
|
|
+ SVGKey key{std::move(move_from_id), dimensions, crop_to_content, colour};
|
|
|
|
|
+ const String& source_id = key.source_id;
|
|
|
auto& documents = svg_cache_data->documents;
|
|
auto& documents = svg_cache_data->documents;
|
|
|
auto& handles = svg_cache_data->handles;
|
|
auto& handles = svg_cache_data->handles;
|
|
|
|
|
|
|
|
const auto it_handle = handles.find(key);
|
|
const auto it_handle = handles.find(key);
|
|
|
if (it_handle != handles.cend())
|
|
if (it_handle != handles.cend())
|
|
|
{
|
|
{
|
|
|
- RMLUI_SVG_DEBUG_LOG("Found handle, reusing: %s, (%d, %d), %s, %#x", path.c_str(), dimensions.x, dimensions.y,
|
|
|
|
|
|
|
+ RMLUI_SVG_DEBUG_LOG("Found handle, reusing: %s, (%d, %d), %s, %#x", source_id.c_str(), dimensions.x, dimensions.y,
|
|
|
crop_to_content ? "crop_to_content" : "crop_none", *reinterpret_cast<const uint32_t*>(&colour[0]));
|
|
crop_to_content ? "crop_to_content" : "crop_none", *reinterpret_cast<const uint32_t*>(&colour[0]));
|
|
|
SharedPtr<SVGData> result = it_handle->second.lock();
|
|
SharedPtr<SVGData> result = it_handle->second.lock();
|
|
|
RMLUI_ASSERTMSG(result, "Failed to lock handle in SVG cache");
|
|
RMLUI_ASSERTMSG(result, "Failed to lock handle in SVG cache");
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- RMLUI_SVG_DEBUG_LOG("Making new handle: %s, (%d, %d), %s, %#x", path.c_str(), dimensions.x, dimensions.y,
|
|
|
|
|
|
|
+ RMLUI_SVG_DEBUG_LOG("Making new handle: %s, (%d, %d), %s, %#x", source_id.c_str(), dimensions.x, dimensions.y,
|
|
|
crop_to_content ? "crop_to_content" : "crop_none", *reinterpret_cast<const uint32_t*>(&colour[0]));
|
|
crop_to_content ? "crop_to_content" : "crop_none", *reinterpret_cast<const uint32_t*>(&colour[0]));
|
|
|
|
|
|
|
|
// Find or create a document
|
|
// Find or create a document
|
|
|
- auto it_svg_document = documents.find(path);
|
|
|
|
|
|
|
+ auto it_svg_document = documents.find(source_id);
|
|
|
if (it_svg_document == documents.cend())
|
|
if (it_svg_document == documents.cend())
|
|
|
{
|
|
{
|
|
|
- RMLUI_SVG_DEBUG_LOG("Loading SVG document from file %s", path.c_str());
|
|
|
|
|
SVGDocument doc;
|
|
SVGDocument doc;
|
|
|
|
|
+ if (source_type == SVGCache::SourceType::File)
|
|
|
|
|
+ {
|
|
|
|
|
+ RMLUI_SVG_DEBUG_LOG("Loading SVG document from file %s", source.c_str());
|
|
|
|
|
+ String svg_data;
|
|
|
|
|
+ if (source.empty() || !GetFileInterface()->LoadFile(source, svg_data))
|
|
|
|
|
+ {
|
|
|
|
|
+ Log::Message(Rml::Log::Type::LT_WARNING, "Could not load SVG file %s", source.c_str());
|
|
|
|
|
+ return {};
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- String svg_data;
|
|
|
|
|
- if (path.empty() || !GetFileInterface()->LoadFile(path, svg_data))
|
|
|
|
|
|
|
+ // We use a reset-release approach here in case clients use a non-std unique_ptr (lunasvg uses std::unique_ptr)
|
|
|
|
|
+ doc.svg_document.reset(lunasvg::Document::loadFromData(svg_data).release());
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
{
|
|
{
|
|
|
- Log::Message(Rml::Log::Type::LT_WARNING, "Could not load SVG file %s", path.c_str());
|
|
|
|
|
- return {};
|
|
|
|
|
|
|
+ RMLUI_SVG_DEBUG_LOG("Loading SVG document from element %s contents", source_id.c_str());
|
|
|
|
|
+ // We use a reset-release approach here in case clients use a non-std unique_ptr (lunasvg uses std::unique_ptr)
|
|
|
|
|
+ doc.svg_document.reset(lunasvg::Document::loadFromData(source).release());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // We use a reset-release approach here in case clients use a non-std unique_ptr (lunasvg uses std::unique_ptr)
|
|
|
|
|
- doc.svg_document.reset(lunasvg::Document::loadFromData(svg_data.data(), svg_data.size()).release());
|
|
|
|
|
-
|
|
|
|
|
if (!doc.svg_document)
|
|
if (!doc.svg_document)
|
|
|
{
|
|
{
|
|
|
- Log::Message(Rml::Log::Type::LT_WARNING, "Could not load SVG data from file %s", path.c_str());
|
|
|
|
|
|
|
+ Log::Message(Rml::Log::Type::LT_WARNING, "Could not load SVG data for item %s", source_id.c_str());
|
|
|
return {};
|
|
return {};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
doc.intrinsic_dimensions.x = Math::Max(float(doc.svg_document->width()), 1.0f);
|
|
doc.intrinsic_dimensions.x = Math::Max(float(doc.svg_document->width()), 1.0f);
|
|
|
doc.intrinsic_dimensions.y = Math::Max(float(doc.svg_document->height()), 1.0f);
|
|
doc.intrinsic_dimensions.y = Math::Max(float(doc.svg_document->height()), 1.0f);
|
|
|
|
|
|
|
|
- const auto it_inserted = documents.insert_or_assign(path, std::move(doc));
|
|
|
|
|
|
|
+ const auto it_inserted = documents.insert_or_assign(source_id, std::move(doc));
|
|
|
RMLUI_ASSERT(it_inserted.second);
|
|
RMLUI_ASSERT(it_inserted.second);
|
|
|
|
|
|
|
|
it_svg_document = it_inserted.first;
|
|
it_svg_document = it_inserted.first;
|
|
@@ -317,7 +326,7 @@ namespace SVG {
|
|
|
auto it_handle = handles.find(key);
|
|
auto it_handle = handles.find(key);
|
|
|
RMLUI_ASSERT(it_handle != handles.cend());
|
|
RMLUI_ASSERT(it_handle != handles.cend());
|
|
|
|
|
|
|
|
- const auto it_document = documents.find(key.path);
|
|
|
|
|
|
|
+ const auto it_document = documents.find(key.source_id);
|
|
|
RMLUI_ASSERT(it_document != documents.cend());
|
|
RMLUI_ASSERT(it_document != documents.cend());
|
|
|
SVGDocument& svg_document = it_document->second;
|
|
SVGDocument& svg_document = it_document->second;
|
|
|
|
|
|
|
@@ -376,7 +385,8 @@ namespace SVG {
|
|
|
svg_cache_data.Shutdown();
|
|
svg_cache_data.Shutdown();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- SharedPtr<SVGData> SVGCache::GetHandle(const String& source, Element* element, const bool crop_to_content, const BoxArea area)
|
|
|
|
|
|
|
+ SharedPtr<SVGData> SVGCache::GetHandle(const String& source_id, const String& source, SourceType source_type, Element* element,
|
|
|
|
|
+ const bool crop_to_content, const BoxArea area)
|
|
|
{
|
|
{
|
|
|
RenderManager* render_manager = element->GetRenderManager();
|
|
RenderManager* render_manager = element->GetRenderManager();
|
|
|
if (!render_manager)
|
|
if (!render_manager)
|
|
@@ -388,14 +398,18 @@ namespace SVG {
|
|
|
if (dimensions.x == 0 || dimensions.y == 0)
|
|
if (dimensions.x == 0 || dimensions.y == 0)
|
|
|
dimensions = {0, 0};
|
|
dimensions = {0, 0};
|
|
|
|
|
|
|
|
- String path;
|
|
|
|
|
- if (ElementDocument* document = element->GetOwnerDocument())
|
|
|
|
|
|
|
+ if (source_type == File)
|
|
|
{
|
|
{
|
|
|
- const String document_source_url = StringUtilities::Replace(document->GetSourceURL(), '|', ':');
|
|
|
|
|
- GetSystemInterface()->JoinPath(path, document_source_url, source);
|
|
|
|
|
|
|
+ String path;
|
|
|
|
|
+ if (ElementDocument* document = element->GetOwnerDocument())
|
|
|
|
|
+ {
|
|
|
|
|
+ const String document_source_url = StringUtilities::Replace(document->GetSourceURL(), '|', ':');
|
|
|
|
|
+ GetSystemInterface()->JoinPath(path, document_source_url, source_id);
|
|
|
|
|
+ }
|
|
|
|
|
+ return Rml::SVG::GetHandle(*render_manager, path, path, source_type, dimensions, crop_to_content, colour);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return Rml::SVG::GetHandle(*render_manager, std::move(path), dimensions, crop_to_content, colour);
|
|
|
|
|
|
|
+ return Rml::SVG::GetHandle(*render_manager, source_id, source, source_type, dimensions, crop_to_content, colour);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} // namespace SVG
|
|
} // namespace SVG
|