Browse Source

Added VH and VW units (#162)

Maximilian Stark 4 years ago
parent
commit
48eda79d2c

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

@@ -591,7 +591,7 @@ public:
 	const ComputedValues& GetComputedValues() const;
 
 protected:
-	void Update(float dp_ratio);
+	void Update(float dp_ratio, Vector2f vp_dimensions);
 	void Render();
 
 	/// Updates definition, computed values, and runs OnPropertyChange on this element.

+ 4 - 1
Include/RmlUi/Core/ElementDocument.h

@@ -155,9 +155,12 @@ private:
 	/// Returns true if the document has been marked as needing a re-layout.
 	bool IsLayoutDirty() override;
 
-	/// Updates all sizes defined by the 'lp' unit.
+	/// Updates all sizes defined by the 'dp' unit.
 	void DirtyDpProperties();
 
+	/// Updates all sizes defined by the 'vw' and the 'vh' units.
+	void DirtyVwAndVhProperties();
+
 	/// Updates the layout if necessary.
 	void UpdateLayout();
 

+ 18 - 16
Include/RmlUi/Core/Property.h

@@ -66,32 +66,34 @@ public:
 		RAD = 1 << 6,               // number suffixed by 'rad'; fetch as < float >
 		COLOUR = 1 << 7,            // colour; fetch as < Colourb >
 		DP = 1 << 8,                // density-independent pixel; number suffixed by 'dp'; fetch as < float >
-		ABSOLUTE_UNIT = NUMBER | PX | DP | DEG | RAD | COLOUR,
+		VW = 1 << 9,                // viewport-width percentage; number suffixed by 'vw'; fetch as < float >
+		VH = 1 << 10,               // viewport-height percentage; number suffixed by 'vh'; fetch as < float >
+		ABSOLUTE_UNIT = NUMBER | PX | DP | DEG | RAD | COLOUR | VW | VH,
 
 		// Relative values.
-		EM = 1 << 9,                // number suffixed by 'em'; fetch as < float >
-		PERCENT = 1 << 10,          // number suffixed by '%'; fetch as < float >
-		REM = 1 << 11,              // number suffixed by 'rem'; fetch as < float >
+		EM = 1 << 11,               // number suffixed by 'em'; fetch as < float >
+		PERCENT = 1 << 12,          // number suffixed by '%'; fetch as < float >
+		REM = 1 << 13,              // number suffixed by 'rem'; fetch as < float >
 		RELATIVE_UNIT = EM | REM | PERCENT,
 
 		// Values based on pixels-per-inch.
-		INCH = 1 << 12,             // number suffixed by 'in'; fetch as < float >
-		CM = 1 << 13,               // number suffixed by 'cm'; fetch as < float >
-		MM = 1 << 14,               // number suffixed by 'mm'; fetch as < float >
-		PT = 1 << 15,               // number suffixed by 'pt'; fetch as < float >
-		PC = 1 << 16,               // number suffixed by 'pc'; fetch as < float >
+		INCH = 1 << 14,             // number suffixed by 'in'; fetch as < float >
+		CM = 1 << 15,               // number suffixed by 'cm'; fetch as < float >
+		MM = 1 << 16,               // number suffixed by 'mm'; fetch as < float >
+		PT = 1 << 17,               // number suffixed by 'pt'; fetch as < float >
+		PC = 1 << 18,               // number suffixed by 'pc'; fetch as < float >
 		PPI_UNIT = INCH | CM | MM | PT | PC,
 
-		TRANSFORM = 1 << 17,        // transform; fetch as < TransformPtr >, may be empty
-		TRANSITION = 1 << 18,       // transition; fetch as < TransitionList >
-		ANIMATION = 1 << 19,        // animation; fetch as < AnimationList >
-		DECORATOR = 1 << 20,        // decorator; fetch as < DecoratorsPtr >
-		FONTEFFECT = 1 << 21,       // font-effect; fetch as < FontEffectsPtr >
+		TRANSFORM = 1 << 19,        // transform; fetch as < TransformPtr >, may be empty
+		TRANSITION = 1 << 20,       // transition; fetch as < TransitionList >
+		ANIMATION = 1 << 21,        // animation; fetch as < AnimationList >
+		DECORATOR = 1 << 22,        // decorator; fetch as < DecoratorsPtr >
+		FONTEFFECT = 1 << 23,       // font-effect; fetch as < FontEffectsPtr >
 
-		LENGTH = PX | DP | PPI_UNIT | EM | REM,
+		LENGTH = PX | DP | PPI_UNIT | EM | REM | VW | VH,
 		LENGTH_PERCENT = LENGTH | PERCENT,
 		NUMBER_LENGTH_PERCENT = NUMBER | LENGTH | PERCENT,
-		ABSOLUTE_LENGTH = PX | DP | PPI_UNIT,
+		ABSOLUTE_LENGTH = PX | DP | PPI_UNIT | VH | VW,
 		ANGLE = DEG | RAD
 	};
 

+ 22 - 14
Source/Core/ComputeProperty.cpp

@@ -56,7 +56,7 @@ float ResolveValue(Style::LengthPercentage length, float base_value)
 }
 
 
-float ComputeLength(const Property* property, float font_size, float document_font_size, float dp_ratio)
+float ComputeLength(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions)
 {
 	RMLUI_ASSERT(property);
 	
@@ -75,6 +75,10 @@ float ComputeLength(const Property* property, float font_size, float document_fo
 		return value * document_font_size;
 	case Property::DP:
 		return value * dp_ratio;
+	case Property::VW:
+		return value * vp_dimensions.x * 0.01f;
+	case Property::VH:
+		return value * vp_dimensions.y * 0.01f;
 
 	case Property::DEG:
 		return Math::DegreesToRadians(value);
@@ -108,7 +112,7 @@ float ComputeLength(const Property* property, float font_size, float document_fo
 	return 0.0f;
 }
 
-float ComputeAbsoluteLength(const Property& property, float dp_ratio)
+float ComputeAbsoluteLength(const Property& property, float dp_ratio, Vector2f vp_dimensions)
 {
 	RMLUI_ASSERT(property.unit & Property::ABSOLUTE_LENGTH);
 
@@ -118,6 +122,10 @@ float ComputeAbsoluteLength(const Property& property, float dp_ratio)
 		return property.value.Get< float >();
 	case Property::DP:
 		return property.value.Get< float >()* dp_ratio;
+	case Property::VW:
+		return property.value.Get< float >()* vp_dimensions.x * 0.01f;
+	case Property::VH:
+		return property.value.Get< float >()* vp_dimensions.y * 0.01f;
 	default:
 		// Values based on pixels-per-inch.
 		if (property.unit & Property::PPI_UNIT)
@@ -165,7 +173,7 @@ float ComputeAngle(const Property& property)
 	return 0.0f;
 }
 
-float ComputeFontsize(const Property& property, const Style::ComputedValues& values, const Style::ComputedValues* parent_values, const Style::ComputedValues* document_values, float dp_ratio)
+float ComputeFontsize(const Property& property, const Style::ComputedValues& values, const Style::ComputedValues* parent_values, const Style::ComputedValues* document_values, float dp_ratio, Vector2f vp_dimensions)
 {
 	// The calculated value of the font-size property is inherited, so we need to check if this
 	// is an inherited property. If so, then we return our parent's font size instead.
@@ -196,7 +204,7 @@ float ComputeFontsize(const Property& property, const Style::ComputedValues& val
 		}
 	}
 
-	return ComputeAbsoluteLength(property, dp_ratio);
+	return ComputeAbsoluteLength(property, dp_ratio, vp_dimensions);
 }
 
 Style::Clip ComputeClip(const Property* property)
@@ -210,11 +218,11 @@ Style::Clip ComputeClip(const Property* property)
 	return Style::Clip();
 }
 
-Style::LineHeight ComputeLineHeight(const Property* property, float font_size, float document_font_size, float dp_ratio)
+Style::LineHeight ComputeLineHeight(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions)
 {
 	if (property->unit & Property::LENGTH)
 	{
-		float value = ComputeLength(property, font_size, document_font_size, dp_ratio);
+		float value = ComputeLength(property, font_size, document_font_size, dp_ratio, vp_dimensions);
 		return Style::LineHeight(value, Style::LineHeight::Length, value);
 	}
 
@@ -236,11 +244,11 @@ Style::LineHeight ComputeLineHeight(const Property* property, float font_size, f
 	return Style::LineHeight(value, Style::LineHeight::Number, scale_factor);
 }
 
-Style::VerticalAlign ComputeVerticalAlign(const Property* property, float line_height, float font_size, float document_font_size, float dp_ratio)
+Style::VerticalAlign ComputeVerticalAlign(const Property* property, float line_height, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions)
 {
 	if (property->unit & Property::LENGTH)
 	{
-		float value = ComputeLength(property, font_size, document_font_size, dp_ratio);
+		float value = ComputeLength(property, font_size, document_font_size, dp_ratio, vp_dimensions);
 		return Style::VerticalAlign(value);
 	}
 	else if (property->unit & Property::PERCENT)
@@ -252,17 +260,17 @@ Style::VerticalAlign ComputeVerticalAlign(const Property* property, float line_h
 	return Style::VerticalAlign((Style::VerticalAlign::Type)property->Get<int>());
 }
 
-Style::LengthPercentage ComputeLengthPercentage(const Property* property, float font_size, float document_font_size, float dp_ratio)
+Style::LengthPercentage ComputeLengthPercentage(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions)
 {
 	using namespace Style;
 	if (property->unit & Property::PERCENT)
 		return LengthPercentage(LengthPercentage::Percentage, property->Get<float>());
 
-	return LengthPercentage(LengthPercentage::Length, ComputeLength(property, font_size, document_font_size, dp_ratio));
+	return LengthPercentage(LengthPercentage::Length, ComputeLength(property, font_size, document_font_size, dp_ratio, vp_dimensions));
 }
 
 
-Style::LengthPercentageAuto ComputeLengthPercentageAuto(const Property* property, float font_size, float document_font_size, float dp_ratio)
+Style::LengthPercentageAuto ComputeLengthPercentageAuto(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions)
 {
 	using namespace Style;
 	// Assuming here that 'auto' is the only possible keyword
@@ -271,10 +279,10 @@ Style::LengthPercentageAuto ComputeLengthPercentageAuto(const Property* property
 	else if (property->unit & Property::KEYWORD)
 		return LengthPercentageAuto(LengthPercentageAuto::Auto);
 
-	return LengthPercentageAuto(LengthPercentageAuto::Length, ComputeLength(property, font_size, document_font_size, dp_ratio));
+	return LengthPercentageAuto(LengthPercentageAuto::Length, ComputeLength(property, font_size, document_font_size, dp_ratio, vp_dimensions));
 }
 
-Style::LengthPercentage ComputeOrigin(const Property* property, float font_size, float document_font_size, float dp_ratio)
+Style::LengthPercentage ComputeOrigin(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions)
 {
 	using namespace Style;
 	static_assert((int)OriginX::Left == (int)OriginY::Top && (int)OriginX::Center == (int)OriginY::Center && (int)OriginX::Right == (int)OriginY::Bottom, "");
@@ -294,7 +302,7 @@ Style::LengthPercentage ComputeOrigin(const Property* property, float font_size,
 	else if (property->unit & Property::PERCENT)
 		return LengthPercentage(LengthPercentage::Percentage, property->Get<float>());
 
-	return LengthPercentage(LengthPercentage::Length, ComputeLength(property, font_size, document_font_size, dp_ratio));
+	return LengthPercentage(LengthPercentage::Length, ComputeLength(property, font_size, document_font_size, dp_ratio, vp_dimensions));
 }
 
 

+ 8 - 8
Source/Core/ComputeProperty.h

@@ -36,25 +36,25 @@ namespace Rml {
 class Property;
 
 // Note that percentages are not lengths! They have to be resolved elsewhere.
-float ComputeLength(const Property* property, float font_size, float document_font_size, float dp_ratio);
+float ComputeLength(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions);
 
-float ComputeAbsoluteLength(const Property& property, float dp_ratio);
+float ComputeAbsoluteLength(const Property& property, float dp_ratio, Vector2f vp_dimensions);
 
 float ComputeAngle(const Property& property);
 
-float ComputeFontsize(const Property& property, const Style::ComputedValues& values, const Style::ComputedValues* parent_values, const Style::ComputedValues* document_values, float dp_ratio);
+float ComputeFontsize(const Property& property, const Style::ComputedValues& values, const Style::ComputedValues* parent_values, const Style::ComputedValues* document_values, float dp_ratio, Vector2f vp_dimensions);
 
 Style::Clip ComputeClip(const Property* property);
 
-Style::LineHeight ComputeLineHeight(const Property* property, float font_size, float document_font_size, float dp_ratio);
+Style::LineHeight ComputeLineHeight(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions);
 
-Style::VerticalAlign ComputeVerticalAlign(const Property* property, float line_height, float font_size, float document_font_size, float dp_ratio);
+Style::VerticalAlign ComputeVerticalAlign(const Property* property, float line_height, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions);
 
-Style::LengthPercentage ComputeLengthPercentage(const Property* property, float font_size, float document_font_size, float dp_ratio);
+Style::LengthPercentage ComputeLengthPercentage(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions);
 
-Style::LengthPercentageAuto ComputeLengthPercentageAuto(const Property* property, float font_size, float document_font_size, float dp_ratio);
+Style::LengthPercentageAuto ComputeLengthPercentageAuto(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions);
 
-Style::LengthPercentage ComputeOrigin(const Property* property, float font_size, float document_font_size, float dp_ratio);
+Style::LengthPercentage ComputeOrigin(const Property* property, float font_size, float document_font_size, float dp_ratio, Vector2f vp_dimensions);
 
 extern const Style::ComputedValues DefaultComputedValues;
 

+ 4 - 1
Source/Core/Context.cpp

@@ -125,6 +125,7 @@ void Context::SetDimensions(const Vector2i& _dimensions)
 			ElementDocument* document = root->GetChild(i)->GetOwnerDocument();
 			if (document != nullptr)
 			{
+				document->DirtyVwAndVhProperties();
 				document->DirtyLayout();
 				document->DirtyPosition();
 				document->DispatchEvent(EventId::Resize, Dictionary());
@@ -172,7 +173,9 @@ bool Context::Update()
 	for (auto& data_model : data_models)
 		data_model.second->Update(true);
 
-	root->Update(density_independent_pixel_ratio);
+	Vector2f vp_dimensions((float)dimensions.x, (float)dimensions.y);
+
+	root->Update(density_independent_pixel_ratio, vp_dimensions);
 
 	for (int i = 0; i < root->GetNumChildren(); ++i)
 		if (auto doc = root->GetChild(i)->GetOwnerDocument())

+ 10 - 3
Source/Core/Element.cpp

@@ -143,7 +143,7 @@ Element::~Element()
 	element_meta_chunk_pool.DestroyAndDeallocate(meta);
 }
 
-void Element::Update(float dp_ratio)
+void Element::Update(float dp_ratio, Vector2f vp_dimensions)
 {
 #ifdef RMLUI_ENABLE_PROFILING
 	auto name = GetAddress(false, false);
@@ -172,7 +172,7 @@ void Element::Update(float dp_ratio)
 	}
 
 	for (size_t i = 0; i < children.size(); i++)
-		children[i]->Update(dp_ratio);
+		children[i]->Update(dp_ratio, vp_dimensions);
 }
 
 
@@ -188,15 +188,22 @@ void Element::UpdateProperties()
 
 		const ComputedValues* document_values = nullptr;
 		float dp_ratio = 1.0f;
+		Vector2f vp_dimensions(1.0f);
 		if (auto doc = GetOwnerDocument())
 		{
 			document_values = &doc->GetComputedValues();
 			if (Context * context = doc->GetContext())
+			{
 				dp_ratio = context->GetDensityIndependentPixelRatio();
+				Vector2i dimensions = context->GetDimensions();
+				vp_dimensions.x = (float)dimensions.x;
+				vp_dimensions.y = (float)dimensions.y;
+
+			}
 		}
 
 		// Compute values and clear dirty properties
-		PropertyIdSet dirty_properties = meta->style.ComputeValues(meta->computed_values, parent_values, document_values, computed_values_are_default_initialized, dp_ratio);
+		PropertyIdSet dirty_properties = meta->style.ComputeValues(meta->computed_values, parent_values, document_values, computed_values_are_default_initialized, dp_ratio, vp_dimensions);
 
 		computed_values_are_default_initialized = false;
 

+ 9 - 1
Source/Core/ElementDocument.cpp

@@ -397,7 +397,9 @@ void ElementDocument::LoadExternalScript(const String& RMLUI_UNUSED_PARAMETER(so
 void ElementDocument::UpdateDocument()
 {
 	const float dp_ratio = (context ? context->GetDensityIndependentPixelRatio() : 1.0f);
-	Update(dp_ratio);
+	const Vector2i dimensions = (context ? context->GetDimensions() : Vector2i(1));
+	const Vector2f vp_dimensions((float)dimensions.x, (float)dimensions.y);
+	Update(dp_ratio, vp_dimensions);
 	UpdateLayout();
 	UpdatePosition();
 }
@@ -483,6 +485,12 @@ void ElementDocument::DirtyDpProperties()
 	GetStyle()->DirtyPropertiesWithUnitRecursive(Property::DP);
 }
 
+void ElementDocument::DirtyVwAndVhProperties()
+{
+	GetStyle()->DirtyPropertiesWithUnitRecursive(Property::VW);
+	GetStyle()->DirtyPropertiesWithUnitRecursive(Property::VH);
+}
+
 // Repositions the document if necessary.
 void ElementDocument::OnPropertyChange(const PropertyIdSet& changed_properties)
 {

+ 5 - 1
Source/Core/ElementScroll.cpp

@@ -228,7 +228,11 @@ bool ElementScroll::CreateScrollbar(Orientation orientation)
 
 	// The construction of scrollbars can occur during layouting, then we need some properties and computed values straight away.
 	Context* context = element->GetContext();
-	child->Update(context ? context->GetDensityIndependentPixelRatio() : 1.0f);
+	
+	const float dp_ratio = (context ? context->GetDensityIndependentPixelRatio() : 1.0f);
+	const Vector2i dimensions = (context ? context->GetDimensions() : Vector2i(1));
+	const Vector2f vp_dimensions((float)dimensions.x, (float)dimensions.y);
+	child->Update(dp_ratio, vp_dimensions);
 
 	return true;
 }

+ 46 - 42
Source/Core/ElementStyle.cpp

@@ -27,6 +27,7 @@
  */
 
 #include "ElementStyle.h"
+#include "../../Include/RmlUi/Core/Context.h"
 #include "../../Include/RmlUi/Core/Core.h"
 #include "../../Include/RmlUi/Core/ElementDocument.h"
 #include "../../Include/RmlUi/Core/ElementUtilities.h"
@@ -358,12 +359,14 @@ float ElementStyle::ResolveNumericProperty(const Property* property, float base_
 		return ComputeAngle(*property);
 
 	const float dp_ratio = ElementUtilities::GetDensityIndependentPixelRatio(element);
+	Vector2i dimensions = (element->GetContext() ? element->GetContext()->GetDimensions() : Vector2i(1));
+	Vector2f vp_dimensions((float)dimensions.x, (float)dimensions.y);
 	const float font_size = element->GetComputedValues().font_size;
 
 	auto doc = element->GetOwnerDocument();
 	const float doc_font_size = (doc ? doc->GetComputedValues().font_size : DefaultComputedValues.font_size);
 
-	float result = ComputeLength(property, font_size, doc_font_size, dp_ratio);
+	float result = ComputeLength(property, font_size, doc_font_size, dp_ratio, vp_dimensions);
 
 	return result;
 }
@@ -377,8 +380,9 @@ float ElementStyle::ResolveLength(const Property* property, RelativeTarget relat
 	{
 		auto doc = element->GetOwnerDocument();
 		const float doc_font_size = (doc ? doc->GetComputedValues().font_size : DefaultComputedValues.font_size);
-
-		float result = ComputeLength(property, element->GetComputedValues().font_size, doc_font_size, ElementUtilities::GetDensityIndependentPixelRatio(element));
+		Vector2i dimensions = (element->GetContext() ? element->GetContext()->GetDimensions() : Vector2i(1));
+		Vector2f vp_dimensions((float)dimensions.x, (float)dimensions.y);
+		float result = ComputeLength(property, element->GetComputedValues().font_size, doc_font_size, ElementUtilities::GetDensityIndependentPixelRatio(element), vp_dimensions);
 
 		return result;
 	}
@@ -504,7 +508,7 @@ void ElementStyle::DirtyProperties(const PropertyIdSet& properties)
 	dirty_properties |= properties;
 }
 
-PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const Style::ComputedValues* parent_values, const Style::ComputedValues* document_values, bool values_are_default_initialized, float dp_ratio)
+PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const Style::ComputedValues* parent_values, const Style::ComputedValues* document_values, bool values_are_default_initialized, float dp_ratio, Vector2f vp_dimensions)
 {
 	if (dirty_properties.Empty())
 		return PropertyIdSet();
@@ -536,7 +540,7 @@ PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const S
 	if(dirty_properties.Contains(PropertyId::FontSize))
 	{
 		if (auto p = GetLocalProperty(PropertyId::FontSize))
-			values.font_size = ComputeFontsize(*p, values, parent_values, document_values, dp_ratio);
+			values.font_size = ComputeFontsize(*p, values, parent_values, document_values, dp_ratio, vp_dimensions);
 		else if (parent_values)
 			values.font_size = parent_values->font_size;
 		
@@ -560,7 +564,7 @@ PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const S
 	{
 		if (auto p = GetLocalProperty(PropertyId::LineHeight))
 		{
-			values.line_height = ComputeLineHeight(p, font_size, document_font_size, dp_ratio);
+			values.line_height = ComputeLineHeight(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 		}
 		else if (parent_values)
 		{
@@ -624,42 +628,42 @@ PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const S
 		switch (id)
 		{
 		case PropertyId::MarginTop:
-			values.margin_top = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.margin_top = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::MarginRight:
-			values.margin_right = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.margin_right = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::MarginBottom:
-			values.margin_bottom = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.margin_bottom = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::MarginLeft:
-			values.margin_left = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.margin_left = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::PaddingTop:
-			values.padding_top = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.padding_top = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::PaddingRight:
-			values.padding_right = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.padding_right = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::PaddingBottom:
-			values.padding_bottom = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.padding_bottom = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::PaddingLeft:
-			values.padding_left = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.padding_left = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::BorderTopWidth:
-			values.border_top_width = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.border_top_width = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::BorderRightWidth:
-			values.border_right_width = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.border_right_width = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::BorderBottomWidth:
-			values.border_bottom_width = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.border_bottom_width = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::BorderLeftWidth:
-			values.border_left_width = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.border_left_width = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::BorderTopColor:
@@ -676,16 +680,16 @@ PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const S
 			break;
 
 		case PropertyId::BorderTopLeftRadius:
-			values.border_top_left_radius = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.border_top_left_radius = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::BorderTopRightRadius:
-			values.border_top_right_radius = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.border_top_right_radius = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::BorderBottomRightRadius:
-			values.border_bottom_right_radius = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.border_bottom_right_radius = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::BorderBottomLeftRadius:
-			values.border_bottom_left_radius = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.border_bottom_left_radius = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::Display:
@@ -696,16 +700,16 @@ PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const S
 			break;
 
 		case PropertyId::Top:
-			values.top = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.top = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::Right:
-			values.right = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.right = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::Bottom:
-			values.bottom = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.bottom = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::Left:
-			values.left = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.left = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::Float:
@@ -723,30 +727,30 @@ PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const S
 			break;
 
 		case PropertyId::Width:
-			values.width = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.width = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::MinWidth:
-			values.min_width = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.min_width = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::MaxWidth:
-			values.max_width = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.max_width = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::Height:
-			values.height = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio);
+			values.height = ComputeLengthPercentageAuto(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::MinHeight:
-			values.min_height = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.min_height = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::MaxHeight:
-			values.max_height = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.max_height = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::LineHeight:
 			// (Line-height computed above)
 			break;
 		case PropertyId::VerticalAlign:
-			values.vertical_align = ComputeVerticalAlign(p, values.line_height.value, font_size, document_font_size, dp_ratio);
+			values.vertical_align = ComputeVerticalAlign(p, values.line_height.value, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::OverflowX:
@@ -809,10 +813,10 @@ PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const S
 			break;
 
 		case PropertyId::RowGap:
-			values.row_gap = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.row_gap = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::ColumnGap:
-			values.column_gap = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio);
+			values.column_gap = ComputeLengthPercentage(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::Cursor:
@@ -829,33 +833,33 @@ PropertyIdSet ElementStyle::ComputeValues(Style::ComputedValues& values, const S
 			values.focus = (Focus)p->Get<int>();
 			break;
 		case PropertyId::ScrollbarMargin:
-			values.scrollbar_margin = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.scrollbar_margin = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::PointerEvents:
 			values.pointer_events = (PointerEvents)p->Get<int>();
 			break;
 
 		case PropertyId::Perspective:
-			values.perspective = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.perspective = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::PerspectiveOriginX:
-			values.perspective_origin_x = ComputeOrigin(p, font_size, document_font_size, dp_ratio);
+			values.perspective_origin_x = ComputeOrigin(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::PerspectiveOriginY:
-			values.perspective_origin_y = ComputeOrigin(p, font_size, document_font_size, dp_ratio);
+			values.perspective_origin_y = ComputeOrigin(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::Transform:
 			values.transform = p->Get<TransformPtr>();
 			break;
 		case PropertyId::TransformOriginX:
-			values.transform_origin_x = ComputeOrigin(p, font_size, document_font_size, dp_ratio);
+			values.transform_origin_x = ComputeOrigin(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::TransformOriginY:
-			values.transform_origin_y = ComputeOrigin(p, font_size, document_font_size, dp_ratio);
+			values.transform_origin_y = ComputeOrigin(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 		case PropertyId::TransformOriginZ:
-			values.transform_origin_z = ComputeLength(p, font_size, document_font_size, dp_ratio);
+			values.transform_origin_z = ComputeLength(p, font_size, document_font_size, dp_ratio, vp_dimensions);
 			break;
 
 		case PropertyId::Transition:

+ 1 - 1
Source/Core/ElementStyle.h

@@ -130,7 +130,7 @@ public:
 
 	/// Turns the local and inherited properties into computed values for this element. These values can in turn be used during the layout procedure.
 	/// Must be called in correct order, always parent before its children.
-	PropertyIdSet ComputeValues(Style::ComputedValues& values, const Style::ComputedValues* parent_values, const Style::ComputedValues* document_values, bool values_are_default_initialized, float dp_ratio);
+	PropertyIdSet ComputeValues(Style::ComputedValues& values, const Style::ComputedValues* parent_values, const Style::ComputedValues* document_values, bool values_are_default_initialized, float dp_ratio, Vector2f vp_dimensions);
 
 	/// Returns an iterator for iterating the local properties of this element.
 	/// Note: Modifying the element's style invalidates its iterator.

+ 2 - 0
Source/Core/PropertyDefinition.cpp

@@ -153,6 +153,8 @@ bool PropertyDefinition::GetValue(String& value, const Property& property) const
 		break;
 
 		case Property::PX:		value += "px"; break;
+		case Property::VW:		value += "vw"; break;
+		case Property::VH:		value += "vh"; break;
 		case Property::DEG:		value += "deg"; break;
 		case Property::RAD:		value += "rad"; break;
 		case Property::DP:		value += "dp"; break;

+ 2 - 0
Source/Core/PropertyParserNumber.cpp

@@ -37,6 +37,8 @@ static const UnorderedMap<String, Property::Unit> g_property_unit_string_map =
 	{"%", Property::PERCENT},
 	{"px", Property::PX},
 	{"dp", Property::DP},
+	{"vw", Property::VW},
+	{"vh", Property::VH},
 	{"em", Property::EM},
 	{"rem", Property::REM},
 	{"in", Property::INCH},

+ 4 - 4
Source/Core/StyleSheetParser.cpp

@@ -122,13 +122,13 @@ public:
 
 			Rectangle rectangle;
 			if (auto property = properties.GetProperty(id_rx))
-				rectangle.x = ComputeAbsoluteLength(*property, 1.f);
+				rectangle.x = ComputeAbsoluteLength(*property, 1.f, Vector2f(1.f));
 			if (auto property = properties.GetProperty(id_ry))
-				rectangle.y = ComputeAbsoluteLength(*property, 1.f);
+				rectangle.y = ComputeAbsoluteLength(*property, 1.f, Vector2f(1.f));
 			if (auto property = properties.GetProperty(id_rw))
-				rectangle.width = ComputeAbsoluteLength(*property, 1.f);
+				rectangle.width = ComputeAbsoluteLength(*property, 1.f, Vector2f(1.f));
 			if (auto property = properties.GetProperty(id_rh))
-				rectangle.height = ComputeAbsoluteLength(*property, 1.f);
+				rectangle.height = ComputeAbsoluteLength(*property, 1.f, Vector2f(1.f));
 
 			sprite_definitions.emplace_back(name, rectangle);
 		}