Browse Source

Add a fingerprint to the font effect

Michael Ragazzon 6 years ago
parent
commit
b00b7612f8

+ 1 - 0
Cmake/FileList.cmake

@@ -92,6 +92,7 @@ set(Core_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/TextureLayoutTexture.h
     ${PROJECT_SOURCE_DIR}/Source/Core/TextureResource.h
     ${PROJECT_SOURCE_DIR}/Source/Core/UnicodeRange.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/Utilities.h
     ${PROJECT_SOURCE_DIR}/Source/Core/WidgetSlider.h
     ${PROJECT_SOURCE_DIR}/Source/Core/WidgetSliderScroll.h
     ${PROJECT_SOURCE_DIR}/Source/Core/XMLNodeHandlerBody.h

+ 6 - 6
Include/RmlUi/Core/FontEffect.h

@@ -77,10 +77,10 @@ public:
 	Layer GetLayer() const;
 	void SetLayer(Layer layer);
 
-	/// Returns the font effect's generation key.
-	/// @return A hash of the effect's properties used to generate the geometry and texture data.
-	// TODO: Always empty.
-	const String& GetGenerationKey() const;
+	/// Returns the font effect's fingerprint.
+	/// @return A hash of the effect's type and properties used to generate the geometry and texture data.
+	size_t GetFingerprint() const;
+	void SetFingerprint(size_t fingerprint);
 
 private:
 	Layer layer;
@@ -88,8 +88,8 @@ private:
 	// The colour of the effect's geometry.
 	Colourb colour;
 
-	// A string identifying the properties that affected the generation of the effect's geometry and texture data.
-	String generation_key;
+	// A hash value identifying the properties that affected the generation of the effect's geometry and texture data.
+	size_t fingerprint;
 };
 
 }

+ 2 - 4
Source/Core/FontDatabase.cpp

@@ -161,11 +161,9 @@ FontDatabase::FontProviderType FontDatabase::GetFontProviderType(const String& f
 // Returns a handle to a font face that can be used to position and render text.
 FontFaceHandle* FontDatabase::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size)
 {
-    size_t provider_index, provider_count;
+    size_t provider_count = font_provider_table.size();
 
-    provider_count = font_provider_table.size();
-
-    for(provider_index = 0; provider_index < provider_count; ++provider_index)
+    for(size_t provider_index = 0; provider_index < provider_count; ++provider_index)
     {
         FontFaceHandle * face_handle = font_provider_table[ provider_index ]->GetFontFaceHandle(family, charset, style, weight, size);
 

+ 7 - 3
Source/Core/FontEffect.cpp

@@ -90,10 +90,14 @@ void FontEffect::SetLayer(Layer _layer)
 	layer = _layer;
 }
 
-// Returns the font effect's geometry / texture generation key.
-const String& FontEffect::GetGenerationKey() const
+size_t FontEffect::GetFingerprint() const
 {
-	return generation_key;
+	return fingerprint;
+}
+
+void FontEffect::SetFingerprint(size_t _fingerprint)
+{
+	fingerprint = _fingerprint;
 }
 
 }

+ 3 - 5
Source/Core/FontFaceHandle.cpp

@@ -326,6 +326,7 @@ FontFaceLayer* FontFaceHandle::GenerateLayer(const std::shared_ptr<const FontEff
 		FontFaceLayer* clone = nullptr;
 		bool deep_clone = true;
 		String generation_key;
+		size_t fingerprint = font_effect->GetFingerprint();
 
 		if (!font_effect->HasUniqueTexture())
 		{
@@ -334,10 +335,7 @@ FontFaceLayer* FontFaceHandle::GenerateLayer(const std::shared_ptr<const FontEff
 		}
 		else
 		{
-			// TODO: Add font effect name here
-			String name = "xyz"; // font_effect->GetName()
-			generation_key = name + ";" + font_effect->GetGenerationKey();
-			FontLayerCache::iterator cache_iterator = layer_cache.find(generation_key);
+			FontLayerCache::iterator cache_iterator = layer_cache.find(fingerprint);
 			if (cache_iterator != layer_cache.end())
 				clone = cache_iterator->second;
 		}
@@ -347,7 +345,7 @@ FontFaceLayer* FontFaceHandle::GenerateLayer(const std::shared_ptr<const FontEff
 
 		// Cache the layer in the layer cache if it generated its own textures (ie, didn't clone).
 		if (!clone)
-			layer_cache[generation_key] = layer;
+			layer_cache[fingerprint] = layer;
 	}
 
 	return layer;

+ 2 - 2
Source/Core/FontFaceHandle.h

@@ -128,8 +128,8 @@ protected:
 	FontGlyphList glyphs;
 	FontKerningList kerning;
 
-	typedef UnorderedMap< const FontEffect*, FontFaceLayer* > FontLayerMap;
-	typedef UnorderedMap< String, FontFaceLayer* > FontLayerCache;
+	typedef SmallUnorderedMap< const FontEffect*, FontFaceLayer* > FontLayerMap;
+	typedef SmallUnorderedMap< size_t, FontFaceLayer* > FontLayerCache;
 	typedef std::vector< FontFaceLayer* > LayerConfiguration;
 	typedef std::vector< LayerConfiguration > LayerConfigurationList;
 

+ 12 - 9
Source/Core/StyleSheet.cpp

@@ -33,6 +33,7 @@
 #include "StyleSheetFactory.h"
 #include "StyleSheetNode.h"
 #include "StyleSheetParser.h"
+#include "Utilities.h"
 #include "../../Include/RmlUi/Core/Element.h"
 #include "../../Include/RmlUi/Core/PropertyDefinition.h"
 #include "../../Include/RmlUi/Core/StyleSheetSpecification.h"
@@ -41,13 +42,6 @@
 namespace Rml {
 namespace Core {
 
-template <class T>
-static inline void hash_combine(std::size_t& seed, const T& v)
-{
-	std::hash<T> hasher;
-	seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
-}
-
 // Sorts style nodes based on specificity.
 static bool StyleSheetNodeSort(const StyleSheetNode* lhs, const StyleSheetNode* rhs)
 {
@@ -286,7 +280,16 @@ FontEffectList StyleSheet::InstanceFontEffectsFromString(const String& font_effe
 			std::shared_ptr<FontEffect> font_effect = instancer->InstanceFontEffect(type, properties);
 
 			if (font_effect)
+			{
+				// Create a unique hash value for the given type and values
+				size_t fingerprint = std::hash<String>{}(type);
+				for (const auto& id_value : properties.GetProperties())
+					Utilities::HashCombine(fingerprint, id_value.second.Get<String>());
+
+				font_effect->SetFingerprint(fingerprint);
+
 				font_effect_list.emplace_back(std::move(font_effect));
+			}
 			else
 			{
 				Log::Message(Log::LT_WARNING, "Font-effect '%s' could not be instanced, declared at %s:%d", font_effect_string.c_str(), source_file.c_str(), source_line_number);
@@ -344,8 +347,8 @@ ElementDefinition* StyleSheet::GetElementDefinition(const Element* element) cons
 	// Check if this puppy has already been cached in the node index; it may be that it has already been created by an
 	// element with a different address but an identical output definition.
 	size_t seed = 0;
-	for (const auto* node : applicable_nodes)
-		hash_combine(seed, node);
+	for (const StyleSheetNode* node : applicable_nodes)
+		Utilities::HashCombine(seed, node);
 
 	auto cache_iterator = node_cache.find(seed);
 	if (cache_iterator != node_cache.end())

+ 47 - 0
Source/Core/Utilities.h

@@ -0,0 +1,47 @@
+/*
+ * 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 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 RMLUICOREUTILITIES_H
+#define RMLUICOREUTILITIES_H
+
+namespace Rml {
+namespace Core {
+namespace Utilities {
+
+template <class T>
+inline void HashCombine(std::size_t& seed, const T& v)
+{
+	std::hash<T> hasher;
+	seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
+
+}
+}
+}
+
+#endif