Przeglądaj źródła

Precalculate font-effects after mergin style sheets

Michael Ragazzon 6 lat temu
rodzic
commit
3b8b8fcd05

+ 1 - 1
Include/RmlUi/Core/ComputedValues.h

@@ -200,7 +200,7 @@ struct ComputedValues
 	AnimationList animation;
 
 	DecoratorList decorator;
-	FontEffectList font_effect; // Sorted by layer first (back then front), then by declaration order.
+	FontEffectListPtr font_effect; // Sorted by layer first (back then front), then by declaration order.
 };
 }
 

+ 1 - 0
Include/RmlUi/Core/Property.h

@@ -79,6 +79,7 @@ public:
 		TRANSITION = 1 << 18,           // transition; fetch as < TransitionList >
 		ANIMATION = 1 << 19,            // animation; fetch as < AnimationList >
 		DECORATOR = 1 << 20,            // decorator; fetch as < DecoratorList >
+		FONTEFFECT = 1 << 21,           // font-effect; fetch as < FontEffectListPtr >
 
 		LENGTH = PX | DP | PPI_UNIT | EM | REM,
 		LENGTH_PERCENT = LENGTH | PERCENT,

+ 1 - 11
Include/RmlUi/Core/StyleSheet.h

@@ -63,14 +63,6 @@ struct DecoratorSpecification {
 };
 using DecoratorSpecificationMap = UnorderedMap<String, DecoratorSpecification>;
 
-struct FontEffectSpecification {
-	String font_effect_type;
-	PropertyDictionary properties;
-	std::shared_ptr<FontEffect> decorator;
-};
-using FontEffectSpecificationMap = UnorderedMap<String, FontEffectSpecification >;
-
-
 /**
 	StyleSheet maintains a single stylesheet definition. A stylesheet can be combined with another stylesheet to create
 	a new, merged stylesheet.
@@ -106,7 +98,7 @@ public:
 	DecoratorList InstanceDecoratorsFromString(const String& decorator_string_value, const String& source_file, int source_line_number) const;
 
 	/// Parses the font-effect property from a string and returns a list of instanced font-effects.
-	FontEffectList InstanceFontEffectsFromString(const String& font_effect_string_value, const String& source_file, int source_line_number) const;
+	FontEffectListPtr InstanceFontEffectsFromString(const String& font_effect_string_value, const String& source_file, int source_line_number) const;
 
 	/// Get sprite located in any spritesheet within this stylesheet.
 	const Sprite* GetSprite(const String& name) const;
@@ -136,8 +128,6 @@ private:
 	// Name of every @decorator mapped to their specification
 	DecoratorSpecificationMap decorator_map;
 
-	FontEffectSpecificationMap font_effect_map;
-
 	// Name of every @spritesheet and underlying sprites mapped to their values
 	SpritesheetList spritesheet_list;
 

+ 10 - 0
Include/RmlUi/Core/TypeConverter.h

@@ -96,6 +96,16 @@ public:
 	RMLUICORE_API static bool Convert(const DecoratorList& src, String& dest);
 };
 
+template<> class TypeConverter< FontEffectListPtr, FontEffectListPtr> {
+public:
+	RMLUICORE_API static bool Convert(const FontEffectListPtr& src, FontEffectListPtr& dest);
+};
+template<> class TypeConverter< FontEffectListPtr, String > {
+public:
+	RMLUICORE_API static bool Convert(const FontEffectListPtr& src, String& dest);
+};
+
+
 
 }
 }

+ 1 - 0
Include/RmlUi/Core/Types.h

@@ -149,6 +149,7 @@ struct TransitionList;
 
 using DecoratorList = std::vector<std::shared_ptr<const Decorator>>;
 using FontEffectList = std::vector<std::shared_ptr<const FontEffect>>;
+using FontEffectListPtr = std::shared_ptr<const FontEffectList>;
 using AnimationList = std::vector<Animation>;
 
 }

+ 3 - 0
Include/RmlUi/Core/Variant.h

@@ -69,6 +69,7 @@ public:
 		TRANSITIONLIST = 'T',
 		ANIMATIONLIST = 'A',
 		DECORATORLIST = 'D',
+		FONTEFFECTLISTPTR = 'F',
 		VOIDPTR = '*',
 	};
 
@@ -144,6 +145,8 @@ private:
 	void Set(AnimationList&& value);
 	void Set(const DecoratorList& value);
 	void Set(DecoratorList&& value);
+	void Set(const FontEffectListPtr& value);
+	void Set(FontEffectListPtr&& value);
 	
 	static constexpr size_t LOCAL_DATA_SIZE = sizeof(TransitionList);
 

+ 18 - 15
Include/RmlUi/Core/Variant.inl

@@ -90,6 +90,22 @@ bool Variant::GetInto(T& value) const
 		return TypeConverter< Vector4f, T >::Convert(*(Vector4f*)data, value);
 		break;
 
+	case COLOURF:
+		return TypeConverter< Colourf, T >::Convert(*(Colourf*)data, value);
+		break;
+
+	case COLOURB:
+		return TypeConverter< Colourb, T >::Convert(*(Colourb*)data, value);
+		break;
+
+	case SCRIPTINTERFACE:
+		return TypeConverter< ScriptInterface*, T >::Convert(*(ScriptInterface * *)data, value);
+		break;
+
+	case VOIDPTR:
+		return TypeConverter< void*, T >::Convert(*(void**)data, value);
+		break;
+
 	case TRANSFORMREF:
 		return TypeConverter< TransformRef, T >::Convert(*(TransformRef*)data, value);
 		break;
@@ -106,22 +122,9 @@ bool Variant::GetInto(T& value) const
 		return TypeConverter< DecoratorList, T >::Convert(*(DecoratorList*)data, value);
 		break;
 
-	case COLOURF:
-		return TypeConverter< Colourf, T >::Convert(*(Colourf*)data, value);
-		break;
-
-	case COLOURB:
-		return TypeConverter< Colourb, T >::Convert(*(Colourb*)data, value);
+	case FONTEFFECTLISTPTR:
+		return TypeConverter< FontEffectListPtr, T >::Convert(*(FontEffectListPtr*)data, value);
 		break;
-
-	case SCRIPTINTERFACE:
-		return TypeConverter< ScriptInterface*, T >::Convert(*(ScriptInterface * *)data, value);
-		break;
-
-	case VOIDPTR:
-		return TypeConverter< void*, T >::Convert(*(void**)data, value);
-		break;
-
 	case NONE:
 		break;
 	}

+ 6 - 3
Source/Core/ElementStyle.cpp

@@ -881,9 +881,12 @@ DirtyPropertyList ElementStyle::ComputeValues(Style::ComputedValues& values, con
 			}
 			break;
 		case PropertyId::FontEffect:
-			values.font_effect.clear();
-			// TODO/performance: Add font-effect property type and precache like decorator
-			if (p->unit == Property::STRING)
+			values.font_effect.reset();
+			if (p->unit == Property::FONTEFFECT)
+			{
+				values.font_effect = p->Get<FontEffectListPtr>();
+			}
+			else if (p->unit == Property::STRING)
 			{
 				if (const StyleSheet * style_sheet = GetStyleSheet())
 				{

+ 6 - 2
Source/Core/ElementTextDefault.cpp

@@ -380,12 +380,16 @@ bool ElementTextDefault::UpdateFontConfiguration()
 	if (!parent)
 		return false;
 
+	static const FontEffectList empty_font_effects;
+
 	// Our parent defines the font-effect for this text element
-	const FontEffectList& font_effects = parent->GetComputedValues().font_effect;
+	const FontEffectList* font_effects = parent->GetComputedValues().font_effect.get();
+	if (!font_effects)
+		font_effects = &empty_font_effects;
 
 	// Request a font layer configuration to match this set of effects. If this is different from
 	// our old configuration, then return true to indicate we'll need to regenerate geometry.
-	int new_configuration = GetFontFaceHandle()->GenerateLayerConfiguration(font_effects);
+	int new_configuration = GetFontFaceHandle()->GenerateLayerConfiguration(*font_effects);
 	if (new_configuration != font_configuration)
 	{
 		font_configuration = new_configuration;

+ 5 - 5
Source/Core/StyleSheet.cpp

@@ -221,16 +221,17 @@ DecoratorList StyleSheet::InstanceDecoratorsFromString(const String& decorator_s
 	return decorator_list;
 }
 
-FontEffectList StyleSheet::InstanceFontEffectsFromString(const String& font_effect_string_value, const String& source_file, int source_line_number) const
+FontEffectListPtr StyleSheet::InstanceFontEffectsFromString(const String& font_effect_string_value, const String& source_file, int source_line_number) const
 {	
 	// Font-effects are declared as
 	//   font-effect: <font-effect-value>[, <font-effect-value> ...];
 	// Where <font-effect-value> is declared with inline properties, e.g.
 	//   font-effect: outline( 1px black ), ...;
 
-	FontEffectList font_effect_list;
 	if (font_effect_string_value.empty() || font_effect_string_value == NONE)
-		return font_effect_list;
+		return nullptr;
+
+	FontEffectList font_effect_list;
 
 	// Make sure we don't split inside the parenthesis since they may appear in decorator shorthands.
 	StringList font_effect_string_list;
@@ -278,7 +279,6 @@ FontEffectList StyleSheet::InstanceFontEffectsFromString(const String& font_effe
 			specification.SetPropertyDefaults(properties);
 
 			std::shared_ptr<FontEffect> font_effect = instancer->InstanceFontEffect(type, properties);
-
 			if (font_effect)
 			{
 				// Create a unique hash value for the given type and values
@@ -303,7 +303,7 @@ FontEffectList StyleSheet::InstanceFontEffectsFromString(const String& font_effe
 		[](const std::shared_ptr<const FontEffect>& effect) { return effect->GetLayer() == FontEffect::Layer::Back; }
 	);
 
-	return font_effect_list;
+	return std::make_shared<FontEffectList>(std::move(font_effect_list));
 }
 
 

+ 15 - 0
Source/Core/StyleSheetNode.cpp

@@ -202,6 +202,21 @@ void StyleSheetNode::BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styl
 				properties.SetProperty(PropertyId::Decorator, new_property);
 			}
 		}
+
+		// Turn any font-effect properties from String to FontEffectListPtr. See comments for decorator, they apply here as well.
+		if (const Property * property = properties.GetProperty(PropertyId::FontEffect))
+		{
+			if (property->unit == Property::STRING)
+			{
+				const String string_value = property->Get<String>();
+				FontEffectListPtr font_effects = style_sheet.InstanceFontEffectsFromString(string_value, property->source, property->source_line_number);
+
+				Property new_property = *property;
+				new_property.value = std::move(font_effects);
+				new_property.unit = Property::FONTEFFECT;
+				properties.SetProperty(PropertyId::FontEffect, new_property);
+			}
+		}
 	}
 
 	for (int i = 0; i < NUM_NODE_TYPES; i++)

+ 26 - 2
Source/Core/TypeConverter.cpp

@@ -124,13 +124,37 @@ bool TypeConverter<DecoratorList, DecoratorList>::Convert(const DecoratorList& s
 bool TypeConverter<DecoratorList, String>::Convert(const DecoratorList& src, String& dest)
 {
 	// Todo. For now, we just count the number of decorators
-	if (!TypeConverter<int, String>::Convert((int)src.size(), dest))
+	if (src.empty())
+		dest = "none";
+	else if (TypeConverter<int, String>::Convert((int)src.size(), dest))
+		dest += " decorator(s)";
+	else
 		return false;
-	dest += " decorator(s)";
 	return true;
 }
 
 
+bool TypeConverter<FontEffectListPtr, FontEffectListPtr>::Convert(const FontEffectListPtr& src, FontEffectListPtr& dest)
+{
+	dest = src;
+	return true;
+}
+
+
+bool TypeConverter<FontEffectListPtr, String>::Convert(const FontEffectListPtr& src, String& dest)
+{
+	// Todo. For now, we just count the number of font-effects
+	if (!src || src->empty())
+		dest = "none";
+	else if (TypeConverter<int, String>::Convert((int)src->size(), dest))
+		dest += " font-effect(s)";
+	else	
+		return false;
+	return true;
+}
+
+
+
 
 }
 }

+ 51 - 8
Source/Core/Variant.cpp

@@ -43,6 +43,7 @@ Variant::Variant() : type(NONE)
 	static_assert(sizeof(TransitionList) <= LOCAL_DATA_SIZE, "Local data too small for TransitionList");
 	static_assert(sizeof(AnimationList) <= LOCAL_DATA_SIZE, "Local data too small for AnimationList");
 	static_assert(sizeof(DecoratorList) <= LOCAL_DATA_SIZE, "Local data too small for DecoratorList");
+	static_assert(sizeof(FontEffectListPtr) <= LOCAL_DATA_SIZE, "Local data too small for FontEffectListPtr");
 }
 
 Variant::Variant(const Variant& copy) : type(NONE)
@@ -92,12 +93,19 @@ void Variant::Clear()
 			AnimationList* animation_list = (AnimationList*)data;
 			animation_list->~AnimationList();
 		}
+		break;
 		case DECORATORLIST:
 		{
 			DecoratorList* decorator_list = (DecoratorList*)data;
 			decorator_list->~DecoratorList();
 		}
 		break;
+		case FONTEFFECTLISTPTR:
+		{
+			FontEffectListPtr* font_effects = (FontEffectListPtr*)data;
+			font_effects->~shared_ptr();
+		}
+		break;
 		default:
 		break;
 	}
@@ -136,6 +144,10 @@ void Variant::Set(const Variant& copy)
 		Set(*(DecoratorList*)copy.data);
 		break;
 
+	case FONTEFFECTLISTPTR:
+		Set(*(FontEffectListPtr*)copy.data);
+		break;
+
 	default:
 		memcpy(data, copy.data, LOCAL_DATA_SIZE);
 		type = copy.type;
@@ -168,6 +180,11 @@ void Variant::Set(Variant&& other)
 		Set(std::move(*(DecoratorList*)other.data));
 		break;
 
+	case FONTEFFECTLISTPTR:
+		Set(std::move(*(FontEffectListPtr*)other.data));
+		break;
+
+
 	default:
 		memcpy(data, other.data, LOCAL_DATA_SIZE);
 		type = other.type;
@@ -378,6 +395,30 @@ void Variant::Set(DecoratorList&& value)
 		new(data) DecoratorList(std::move(value));
 	}
 }
+void Variant::Set(const FontEffectListPtr& value)
+{
+	if (type == FONTEFFECTLISTPTR)
+	{
+		*(FontEffectListPtr*)data = value;
+	}
+	else
+	{
+		type = FONTEFFECTLISTPTR;
+		new(data) FontEffectListPtr(value);
+	}
+}
+void Variant::Set(FontEffectListPtr&& value)
+{
+	if (type == FONTEFFECTLISTPTR)
+	{
+		(*(FontEffectListPtr*)data) = std::move(value);
+	}
+	else
+	{
+		type = FONTEFFECTLISTPTR;
+		new(data) FontEffectListPtr(std::move(value));
+	}
+}
 
 Variant& Variant::operator=(const Variant& copy)
 {
@@ -422,14 +463,6 @@ bool Variant::operator==(const Variant & other) const
 		return DEFAULT_VARIANT_COMPARE(Vector3f);
 	case VECTOR4:
 		return DEFAULT_VARIANT_COMPARE(Vector4f);
-	case TRANSFORMREF:
-		return DEFAULT_VARIANT_COMPARE(TransformRef);
-	case TRANSITIONLIST:
-		return DEFAULT_VARIANT_COMPARE(TransitionList);
-	case ANIMATIONLIST:
-		return DEFAULT_VARIANT_COMPARE(AnimationList);
-	case DECORATORLIST:
-		return DEFAULT_VARIANT_COMPARE(DecoratorList);
 	case COLOURF:
 		return DEFAULT_VARIANT_COMPARE(Colourf);
 	case COLOURB:
@@ -438,6 +471,16 @@ bool Variant::operator==(const Variant & other) const
 		return DEFAULT_VARIANT_COMPARE(ScriptInterface*);
 	case VOIDPTR:
 		return DEFAULT_VARIANT_COMPARE(void*);
+	case TRANSFORMREF:
+		return DEFAULT_VARIANT_COMPARE(TransformRef);
+	case TRANSITIONLIST:
+		return DEFAULT_VARIANT_COMPARE(TransitionList);
+	case ANIMATIONLIST:
+		return DEFAULT_VARIANT_COMPARE(AnimationList);
+	case DECORATORLIST:
+		return DEFAULT_VARIANT_COMPARE(DecoratorList);
+	case FONTEFFECTLISTPTR:
+		return DEFAULT_VARIANT_COMPARE(FontEffectListPtr);
 	case NONE:
 		return true;
 		break;