Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Include/RmlUi/Core/DecorationTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "NumericValue.h"
#include "Types.h"
#include "Utilities.h"

namespace Rml {

Expand Down Expand Up @@ -65,4 +66,24 @@ inline bool operator!=(const BoxShadow& a, const BoxShadow& b)
}

} // namespace Rml

namespace std {
template <>
struct hash<::Rml::BoxShadow> {
size_t operator()(const ::Rml::BoxShadow& s) const noexcept
{
using namespace ::Rml;
using namespace ::Rml::Utilities;
size_t seed = std::hash<ColourbPremultiplied>{}(s.color);

HashCombine(seed, s.offset_x);
HashCombine(seed, s.offset_y);
HashCombine(seed, s.blur_radius);
HashCombine(seed, s.spread_distance);
HashCombine(seed, s.inset);
return seed;
}
};

} // namespace std
#endif
15 changes: 14 additions & 1 deletion Include/RmlUi/Core/NumericValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,18 @@ inline bool operator!=(const NumericValue& a, const NumericValue& b)
}

} // namespace Rml

namespace std {
template <>
struct hash<::Rml::NumericValue> {
// FIXME: should the hash function NumericValue not care about unit (as long as resolved unit is the same?)
// Or should it be a regular hash combine?
size_t operator()(const ::Rml::NumericValue& v) const noexcept
{
using namespace ::Rml;
size_t h1 = hash<float>{}(v.number);
size_t h2 = hash<Unit>{}(v.unit);
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
}
};
} // namespace std
#endif
36 changes: 35 additions & 1 deletion Include/RmlUi/Core/RenderBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#define RMLUI_CORE_RENDERBOX_H

#include "Types.h"
#include "Utilities.h"

namespace Rml {

Expand Down Expand Up @@ -76,6 +77,39 @@ class RenderBox {
EdgeSizes border_widths;
CornerSizes border_radius;
};

inline bool operator==(const RenderBox& a, const RenderBox& b)
{
return a.GetFillSize() == b.GetFillSize() && a.GetBorderOffset() == b.GetBorderOffset() && a.GetBorderWidths() == b.GetBorderWidths() &&
a.GetBorderRadius() == b.GetBorderRadius();
}
inline bool operator!=(const RenderBox& a, const RenderBox& b)
{
return !(a == b);
}
} // namespace Rml

namespace std {
template <>
struct hash<::Rml::RenderBox> {

size_t operator()(const ::Rml::RenderBox& box) const noexcept
{
using namespace ::Rml::Utilities;
static auto HashArray4 = [](const ::Rml::Array<float, 4>& arr) -> size_t {
size_t seed = 0;
for (const auto& v : arr)
HashCombine(seed, v);
return seed;
};

size_t seed = 0;
HashCombine(seed, box.GetFillSize());
HashCombine(seed, box.GetBorderOffset());
HashCombine(seed, HashArray4(box.GetBorderRadius()));
HashCombine(seed, HashArray4(box.GetBorderWidths()));
return seed;
}
};
} // namespace std

#endif
10 changes: 6 additions & 4 deletions Include/RmlUi/Core/RenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@
#define RMLUI_CORE_RENDERMANAGER_H

#include "CallbackTexture.h"
#include "DecorationTypes.h"
#include "Mesh.h"
#include "RenderBox.h"
#include "RenderInterface.h"
#include "StableVector.h"
#include "Types.h"
#include "Utilities.h"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some remnant includes and unnecessary changes now. I'm just making a note here to remember to revert these files that no longer have meaningful changes.


namespace Rml {

class Geometry;
class CompiledFilter;
class CompiledShader;
Expand Down Expand Up @@ -67,10 +69,10 @@ struct RenderState {
};

/**
A wrapper over the render interface, which tracks its state and resources.
A wrapper over the render interface, which tracks its state and resources.

All operations to be submitted to the render interface should go through this class.
*/
All operations to be submitted to the render interface should go through this class.
*/
class RMLUICORE_API RenderManager : NonCopyMoveable {
public:
RenderManager(RenderInterface* render_interface);
Expand Down
33 changes: 33 additions & 0 deletions Include/RmlUi/Core/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,39 @@ struct hash<::Rml::FamilyId> {
return h(static_cast<utype>(t));
}
};
template <>
struct hash<::Rml::Vector2i> {
size_t operator()(const ::Rml::Vector2i& v) const noexcept
{
size_t h1 = std::hash<int>{}(v.x);
size_t h2 = std::hash<int>{}(v.y);
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
}
};
template <>
struct hash<::Rml::Vector2f> {
size_t operator()(const ::Rml::Vector2f& v) const noexcept
{
size_t h1 = hash<float>{}(v.x);
size_t h2 = hash<float>{}(v.y);
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
}
};
template <>
struct hash<::Rml::Colourb> {
size_t operator()(const ::Rml::Colourb& v) const noexcept
{
return static_cast<size_t>(hash<uint32_t>{}(reinterpret_cast<const uint32_t&>(v)));
}
};
template <>
struct hash<::Rml::ColourbPremultiplied> {
size_t operator()(const ::Rml::ColourbPremultiplied& v) const noexcept
{
return static_cast<size_t>(hash<uint32_t>{}(reinterpret_cast<const uint32_t&>(v)));
}
};

} // namespace std

#endif
12 changes: 12 additions & 0 deletions Include/RmlUi/Core/Unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,16 @@ inline bool Any(Units units)
}

} // namespace Rml
namespace std {
// Hash specialization for enum class types (required on some older compilers)
template <>
struct hash<::Rml::Unit> {
using utype = ::std::underlying_type_t<::Rml::Unit>;
size_t operator()(const ::Rml::Unit& t) const noexcept
{
::std::hash<utype> h;
return h(static_cast<utype>(t));
}
};
} // namespace std
#endif
144 changes: 144 additions & 0 deletions Source/Core/BoxShadowCache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* This source file is part of RmlUi, the HTML/CSS Interface Middleware
*
* For the latest information, see http://github.com/mikke89/RmlUi
*
* Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
* Copyright (c) 2019-2023 The RmlUi Team, and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/

#include "BoxShadowCache.h"
#include "../../Include/RmlUi/Core/Box.h"
#include "../../Include/RmlUi/Core/CallbackTexture.h"
#include "../../Include/RmlUi/Core/ComputedValues.h"
#include "../../Include/RmlUi/Core/Core.h"
#include "../../Include/RmlUi/Core/DecorationTypes.h"
#include "../../Include/RmlUi/Core/Element.h"
#include "../../Include/RmlUi/Core/ElementDocument.h"
#include "../../Include/RmlUi/Core/FileInterface.h"
#include "../../Include/RmlUi/Core/Geometry.h"
#include "../../Include/RmlUi/Core/Math.h"
#include "../../Include/RmlUi/Core/MeshUtilities.h"
#include "../../Include/RmlUi/Core/RenderManager.h"
#include "../../Include/RmlUi/Core/Texture.h"
#include "../../Include/RmlUi/Core/Utilities.h"
#include "../Core/ControlledLifetimeResource.h"
#include "ElementBackgroundBorder.h"
#include "GeometryBoxShadow.h"
#include <algorithm>

namespace Rml {

struct BoxShadowCacheData {
StableUnorderedMap<BoxShadowGeometryInfo, WeakPtr<BoxShadowData>> handles;
};

BoxShadowData::~BoxShadowData()
{
ReleaseHandle(this);
}

static ControlledLifetimeResource<BoxShadowCacheData> shadow_cache_data;

void BoxShadowCache::Initialize()
{
shadow_cache_data.Initialize();
}

void BoxShadowCache::Shutdown()
{
shadow_cache_data.Shutdown();
}

static SharedPtr<BoxShadowData> GetOrCreateBoxShadow(RenderManager& render_manager, const BoxShadowGeometryInfo& info)
{
auto handles = shadow_cache_data->handles;
auto it_handle = std::find(shadow_cache_data->handles.begin(), shadow_cache_data->handles.end(), info);
if (it_handle == shadow_cache_data->handles.end())
{
SharedPtr<BoxShadowData> result = it_handle->second.lock();
RMLUI_ASSERTMSG(result, "Failed to lock handle in SVG cache");
return result;
}
const auto iterator_inserted = handles.emplace(info, WeakPtr<BoxShadowData>());
RMLUI_ASSERTMSG(iterator_inserted.second, "Could not insert entry into the SVG cache handle map, duplicate key.");
const BoxShadowGeometryInfo& inserted_key = iterator_inserted.first->first;
WeakPtr<BoxShadowData>& inserted_weak_data_pointer = iterator_inserted.first->second;

auto shadow_handle = MakeShared<BoxShadowData>(/*TODO*/);
inserted_weak_data_pointer = shadow_handle;
return shadow_handle;
}

static void ReleaseHandle(BoxShadowData* handle)
{
// There are no longer any users of the cache entry uniquely identified by the handle address. Start from the
// tip (i.e. per-color data) and remove that entry from its parent. Move up the cache ancestry and erase any
// entries that no longer have any children.
// auto& handles = shadow_cache_data->handles;
// const BoxShadowGeometryInfo& key = handle->cache_key;
//
// auto it_handle = handles.find(key);
// RMLUI_ASSERT(it_handle != handles.cend());
//
// handles.erase(it_handle);
//
//#ifdef RMLUI_DEBUG
// size_t count_unique_entries = 0;
// /*for (auto& document : documents)
// {
// RMLUI_ASSERT(!document.second.textures.empty());
// for (auto& size_data : document.second.textures)
// {
// RMLUI_ASSERT(!size_data.geometries.empty());
// count_unique_entries += size_data.geometries.size();
// }
// }*/
// RMLUI_ASSERT(count_unique_entries == handles.size());
//#endif
}

SharedPtr<BoxShadowData> BoxShadowCache::GetHandle(Element* element)
{
RenderManager* render_manager = element->GetRenderManager();
if (!render_manager)
return {};

const ComputedValues& computed = element->GetComputedValues();
const ColourbPremultiplied colour = computed.image_color().ToPremultiplied(computed.opacity());

const Property* p_box_shadow = element->GetLocalProperty(PropertyId::BoxShadow);
RMLUI_ASSERT(p_box_shadow->value.GetType() == Variant::BOXSHADOWLIST);
BoxShadowList shadow_list = p_box_shadow->value.Get<BoxShadowList>();

ColourbPremultiplied background_color = computed.background_color().ToPremultiplied();
Array<ColourbPremultiplied, 4> border_colors = {
computed.border_top_color().ToPremultiplied(),
computed.border_right_color().ToPremultiplied(),
computed.border_bottom_color().ToPremultiplied(),
computed.border_left_color().ToPremultiplied(),
};
const CornerSizes border_radius = computed.border_radius();
BoxShadowGeometryInfo geom_info = GeometryBoxShadow::Resolve(element, shadow_list, border_radius, background_color, border_colors);
return GetOrCreateBoxShadow(*render_manager, geom_info);
}
} // namespace Rml
59 changes: 59 additions & 0 deletions Source/Core/BoxShadowCache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* This source file is part of RmlUi, the HTML/CSS Interface Middleware
*
* For the latest information, see http://github.com/mikke89/RmlUi
*
* Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
* Copyright (c) 2019-2023 The RmlUi Team, and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/

#ifndef RMLUI_CORE_BOXSHADOWCACHE_H
#define RMLUI_CORE_BOXSHADOWCACHE_H

#include "../../Include/RmlUi/Core/RenderBox.h"
#include "../../Include/RmlUi/Core/Types.h"

namespace Rml {
struct BoxShadowGeometryInfo;

struct BoxShadowData : NonCopyMoveable {
BoxShadowData();
~BoxShadowData();

Texture texture;
Vector2f intrinsic_dimensions;
const BoxShadowGeometryInfo& cache_key;
};

class BoxShadowCache {
public:
static void Initialize();
static void Shutdown();

/// Returns a handle to BoxShadow data matching the parameters - creates new data if none is found.
/// @param[in] element Element for which to calculate and cache the box shadow
/// @return A handle to the BoxShadow data, with automatic reference counting.
static SharedPtr<BoxShadowData> GetHandle(Element* element);
};

} // namespace Rml
#endif
Loading
Loading