Browse Source

Add natural display dimensions to decorators based on spritesheet source scaling and dp-ratio.

This means that when applying a dp-ratio on a context, tiles (eg. corners of a ninepatch or tiled box decorator) will scale accordingly. Tiles will also respect the 'resolution' property in a spritesheet which defines the scale the image is meant to be displayed at, effectively the reverse of the effect of dp-ratio.

The old hack of scaling the edges of the ninepatch decorator by 1.0 to make it respond to the dp-ratio no longer has any effect, this is now effectively the default.
Michael Ragazzon 4 years ago
parent
commit
8aeb207f9c

+ 3 - 3
Include/RmlUi/Core/Spritesheet.h

@@ -56,12 +56,12 @@ struct Spritesheet {
 	String image_source;
 	String image_source;
 	String definition_source;
 	String definition_source;
 	int definition_line_number;
 	int definition_line_number;
-	float image_inv_scale;
+	float display_scale; // The inverse of the 'resolution' spritesheet property.
 	Texture texture;
 	Texture texture;
 	StringList sprite_names;
 	StringList sprite_names;
 
 
 	Spritesheet(const String& name, const String& image_source, const String& definition_source,
 	Spritesheet(const String& name, const String& image_source, const String& definition_source,
-		int definition_line_number, float image_inv_scale, const Texture& texture);
+		int definition_line_number, float display_scale, const Texture& texture);
 };
 };
 
 
 using SpritesheetMap = SmallUnorderedMap<String, SharedPtr<const Spritesheet>>; // key: spritesheet name (as given in @spritesheet)
 using SpritesheetMap = SmallUnorderedMap<String, SharedPtr<const Spritesheet>>; // key: spritesheet name (as given in @spritesheet)
@@ -74,7 +74,7 @@ using SpriteDefinitionList = Vector<Pair<String, Rectangle>>; // Sprite name and
 class SpritesheetList {
 class SpritesheetList {
 public:
 public:
 	/// Adds a new sprite sheet to the list and inserts all sprites with unique names into the global list.
 	/// Adds a new sprite sheet to the list and inserts all sprites with unique names into the global list.
-	bool AddSpriteSheet(const String& name, const String& image_source, const String& definition_source, int definition_line_number, float image_inv_scale, const SpriteDefinitionList& sprite_definitions);
+	bool AddSpriteSheet(const String& name, const String& image_source, const String& definition_source, int definition_line_number, float display_scale, const SpriteDefinitionList& sprite_definitions);
 
 
 	/// Get a sprite from its name if it exists.
 	/// Get a sprite from its name if it exists.
 	/// Note: The pointer is invalidated whenever another sprite is added. Do not store it around.
 	/// Note: The pointer is invalidated whenever another sprite is added. Do not store it around.

+ 19 - 11
Source/Core/DecoratorNinePatch.cpp

@@ -42,10 +42,12 @@ DecoratorNinePatch::~DecoratorNinePatch()
 {
 {
 }
 }
 
 
-bool DecoratorNinePatch::Initialise(const Rectangle& _rect_outer, const Rectangle& _rect_inner, const Array<Property, 4>* _edges, const Texture& _texture)
+bool DecoratorNinePatch::Initialise(const Rectangle& _rect_outer, const Rectangle& _rect_inner, const Array<Property, 4>* _edges, const Texture& _texture, float _display_scale)
 {
 {
 	rect_outer = _rect_outer;
 	rect_outer = _rect_outer;
 	rect_inner = _rect_inner;
 	rect_inner = _rect_inner;
+	
+	display_scale = _display_scale;
 
 
 	if (_edges)
 	if (_edges)
 		edges = MakeUnique< Array<Property, 4> >(*_edges);
 		edges = MakeUnique< Array<Property, 4> >(*_edges);
@@ -87,23 +89,26 @@ DecoratorDataHandle DecoratorNinePatch::GenerateElementData(Element* element) co
 	for (int i = 0; i < 4; i++)
 	for (int i = 0; i < 4; i++)
 		tex_coords[i] = tex_pos[i] / texture_dimensions;
 		tex_coords[i] = tex_pos[i] / texture_dimensions;
 
 
-	// Surface position [0, surface_dimensions]
-	// Need to keep the corner patches at their native pixel size, but stretch the inner patches.
+	// Natural size is determined from the raw pixel size multiplied by the dp-ratio and the sprite's
+	// display scale (determined by eg. the inverse of spritesheet's 'src-scale').
+	const float scale_raw_to_natural_dimensions = ElementUtilities::GetDensityIndependentPixelRatio(element) * display_scale;
+
+	// Surface position in pixels [0, surface_dimensions]
+	// Need to keep the corner patches at their natural size, but stretch the inner patches.
 	Vector2f surface_pos[4];
 	Vector2f surface_pos[4];
 	surface_pos[0] = { 0, 0 };
 	surface_pos[0] = { 0, 0 };
-	surface_pos[1] = tex_pos[1] - tex_pos[0];
-	surface_pos[2] = surface_dimensions - (tex_pos[3] - tex_pos[2]);
+	surface_pos[1] = (tex_pos[1] - tex_pos[0]) * scale_raw_to_natural_dimensions;
+	surface_pos[2] = surface_dimensions - (tex_pos[3] - tex_pos[2]) * scale_raw_to_natural_dimensions;
 	surface_pos[3] = surface_dimensions;
 	surface_pos[3] = surface_dimensions;
 
 
 	// Change the size of the edges if specified.
 	// Change the size of the edges if specified.
 	if (edges)
 	if (edges)
 	{
 	{
-		const float dp_ratio = ElementUtilities::GetDensityIndependentPixelRatio(element);
 		float lengths[4]; // top, right, bottom, left
 		float lengths[4]; // top, right, bottom, left
-		lengths[0] = element->ResolveNumericProperty(&(*edges)[0], dp_ratio * (surface_pos[1].y - surface_pos[0].y));
-		lengths[1] = element->ResolveNumericProperty(&(*edges)[1], dp_ratio * (surface_pos[3].x - surface_pos[2].x));
-		lengths[2] = element->ResolveNumericProperty(&(*edges)[2], dp_ratio * (surface_pos[3].y - surface_pos[2].y));
-		lengths[3] = element->ResolveNumericProperty(&(*edges)[3], dp_ratio * (surface_pos[1].x - surface_pos[0].x));
+		lengths[0] = element->ResolveNumericProperty(&(*edges)[0], (surface_pos[1].y - surface_pos[0].y));
+		lengths[1] = element->ResolveNumericProperty(&(*edges)[1], (surface_pos[3].x - surface_pos[2].x));
+		lengths[2] = element->ResolveNumericProperty(&(*edges)[2], (surface_pos[3].y - surface_pos[2].y));
+		lengths[3] = element->ResolveNumericProperty(&(*edges)[3], (surface_pos[1].x - surface_pos[0].x));
 
 
 		surface_pos[1].y = lengths[0];
 		surface_pos[1].y = lengths[0];
 		surface_pos[2].x = surface_dimensions.x - lengths[1];
 		surface_pos[2].x = surface_dimensions.x - lengths[1];
@@ -244,8 +249,11 @@ SharedPtr<Decorator> DecoratorNinePatchInstancer::InstanceDecorator(const String
 
 
 	auto decorator = MakeShared<DecoratorNinePatch>();
 	auto decorator = MakeShared<DecoratorNinePatch>();
 
 
-	if (!decorator->Initialise(sprite_outer->rectangle, sprite_inner->rectangle, (edges_set ? &edges : nullptr), sprite_outer->sprite_sheet->texture))
+	if (!decorator->Initialise(sprite_outer->rectangle, sprite_inner->rectangle, (edges_set ? &edges : nullptr),
+		sprite_outer->sprite_sheet->texture, sprite_outer->sprite_sheet->display_scale))
+	{
 		return nullptr;
 		return nullptr;
+	}
 
 
 	return decorator;
 	return decorator;
 }
 }

+ 2 - 1
Source/Core/DecoratorNinePatch.h

@@ -42,7 +42,7 @@ public:
 	DecoratorNinePatch();
 	DecoratorNinePatch();
 	virtual ~DecoratorNinePatch();
 	virtual ~DecoratorNinePatch();
 
 
-	bool Initialise(const Rectangle& rect_outer, const Rectangle& rect_inner, const Array<Property, 4>* _edges, const Texture& texture);
+	bool Initialise(const Rectangle& rect_outer, const Rectangle& rect_inner, const Array<Property, 4>* _edges, const Texture& texture, float display_scale);
 
 
 	DecoratorDataHandle GenerateElementData(Element* element) const override;
 	DecoratorDataHandle GenerateElementData(Element* element) const override;
 	void ReleaseElementData(DecoratorDataHandle element_data) const override;
 	void ReleaseElementData(DecoratorDataHandle element_data) const override;
@@ -51,6 +51,7 @@ public:
 
 
 private:
 private:
 	Rectangle rect_outer, rect_inner;
 	Rectangle rect_outer, rect_inner;
+	float display_scale = 1;
 	UniquePtr<Array<Property,4>> edges;
 	UniquePtr<Array<Property,4>> edges;
 };
 };
 
 

+ 10 - 5
Source/Core/DecoratorTiled.cpp

@@ -30,6 +30,7 @@
 #include "../../Include/RmlUi/Core/Element.h"
 #include "../../Include/RmlUi/Core/Element.h"
 #include "../../Include/RmlUi/Core/Math.h"
 #include "../../Include/RmlUi/Core/Math.h"
 #include "../../Include/RmlUi/Core/GeometryUtilities.h"
 #include "../../Include/RmlUi/Core/GeometryUtilities.h"
+#include "../../Include/RmlUi/Core/ElementUtilities.h"
 #include <algorithm>
 #include <algorithm>
 
 
 namespace Rml {
 namespace Rml {
@@ -49,7 +50,7 @@ static const Vector2f oriented_texcoords[4][2] = {
 	{Vector2f(1, 1), Vector2f(0, 0)}    // ROTATE_180
 	{Vector2f(1, 1), Vector2f(0, 0)}    // ROTATE_180
 };
 };
 
 
-DecoratorTiled::Tile::Tile() : position(0, 0), size(0, 0)
+DecoratorTiled::Tile::Tile() : display_scale(1), position(0, 0), size(0, 0)
 {
 {
 	texture_index = -1;
 	texture_index = -1;
 	fit_mode = FILL;
 	fit_mode = FILL;
@@ -81,7 +82,7 @@ void DecoratorTiled::Tile::CalculateDimensions(Element* element, const Texture&
 			else
 			else
 				new_data.size = size;
 				new_data.size = size;
 			
 			
-			Vector2f size_relative = new_data.size / texture_dimensions;
+			const Vector2f size_relative = new_data.size / texture_dimensions;
 
 
 			new_data.size = Vector2f(Math::AbsoluteValue(new_data.size.x), Math::AbsoluteValue(new_data.size.y));
 			new_data.size = Vector2f(Math::AbsoluteValue(new_data.size.x), Math::AbsoluteValue(new_data.size.y));
 
 
@@ -94,14 +95,17 @@ void DecoratorTiled::Tile::CalculateDimensions(Element* element, const Texture&
 }
 }
 
 
 // Get this tile's dimensions.
 // Get this tile's dimensions.
-Vector2f DecoratorTiled::Tile::GetDimensions(Element* element) const
+Vector2f DecoratorTiled::Tile::GetNaturalDimensions(Element* element) const
 {
 {
 	RenderInterface* render_interface = element->GetRenderInterface();
 	RenderInterface* render_interface = element->GetRenderInterface();
 	auto data_iterator = data.find(render_interface);
 	auto data_iterator = data.find(render_interface);
 	if (data_iterator == data.end())
 	if (data_iterator == data.end())
 		return Vector2f(0, 0);
 		return Vector2f(0, 0);
 
 
-	return data_iterator->second.size;
+	const float scale_raw_to_natural_dimensions = ElementUtilities::GetDensityIndependentPixelRatio(element) * display_scale;
+	const Vector2f raw_dimensions = data_iterator->second.size;
+
+	return raw_dimensions * scale_raw_to_natural_dimensions;
 }
 }
 
 
 // Generates geometry to render this tile across a surface.
 // Generates geometry to render this tile across a surface.
@@ -237,8 +241,9 @@ void DecoratorTiled::Tile::GenerateGeometry(Vector< Vertex >& vertices, Vector<
 }
 }
 
 
 // Scales a tile dimensions by a fixed value along one axis.
 // Scales a tile dimensions by a fixed value along one axis.
-void DecoratorTiled::ScaleTileDimensions(Vector2f& tile_dimensions, float axis_value, int axis) const
+void DecoratorTiled::ScaleTileDimensions(Vector2f& tile_dimensions, float axis_value, Axis axis_enum) const
 {
 {
+	int axis = static_cast<int>(axis_enum);
 	if (tile_dimensions[axis] != axis_value)
 	if (tile_dimensions[axis] != axis_value)
 	{
 	{
 		tile_dimensions[1 - axis] = tile_dimensions[1 - axis] * (axis_value / tile_dimensions[axis]);
 		tile_dimensions[1 - axis] = tile_dimensions[1 - axis] * (axis_value / tile_dimensions[axis]);

+ 10 - 4
Source/Core/DecoratorTiled.h

@@ -84,8 +84,9 @@ public:
 
 
 		/// Calculates the tile's dimensions from the texture and texture coordinates.
 		/// Calculates the tile's dimensions from the texture and texture coordinates.
 		void CalculateDimensions(Element* element, const Texture& texture) const;
 		void CalculateDimensions(Element* element, const Texture& texture) const;
-		/// Get this tile's dimensions.
-		Vector2f GetDimensions(Element* element) const;
+		/// Get the dimensions (in px) that this tile is ideally displayed as.
+		/// Uses the dp-ratio of the current element and 'display_scale' to calculate the dimensions.
+		Vector2f GetNaturalDimensions(Element* element) const;
 
 
 		/// Generates geometry to render this tile across a surface.
 		/// Generates geometry to render this tile across a surface.
 		/// @param[out] vertices The array to store the generated vertex data.
 		/// @param[out] vertices The array to store the generated vertex data.
@@ -106,6 +107,9 @@ public:
 
 
 		int texture_index;
 		int texture_index;
 
 
+		// Scales the desired displayed size of the tile from raw pixel size. Eg. the 'display_scale' in a sprite sheet.
+		float display_scale;
+
 		// Position and size within the texture, absolute units (px)
 		// Position and size within the texture, absolute units (px)
 		Vector2f position, size;
 		Vector2f position, size;
 
 
@@ -119,11 +123,13 @@ public:
 	};
 	};
 
 
 protected:
 protected:
+	enum class Axis { Horizontal, Vertical };
+
 	/// Scales a tile dimensions by a fixed value along one axis.
 	/// Scales a tile dimensions by a fixed value along one axis.
 	/// @param tile_dimensions[in, out] The tile dimensions to scale.
 	/// @param tile_dimensions[in, out] The tile dimensions to scale.
 	/// @param axis_value[in] The fixed value to scale against.
 	/// @param axis_value[in] The fixed value to scale against.
-	/// @param axis[in] The axis to scale against; either 0 (for x) or 1 (for y).
-	void ScaleTileDimensions(Vector2f& tile_dimensions, float axis_value, int axis) const;
+	/// @param axis[in] The axis to scale against.
+	void ScaleTileDimensions(Vector2f& tile_dimensions, float axis_value, Axis axis) const;
 };
 };
 
 
 } // namespace Rml
 } // namespace Rml

+ 81 - 70
Source/Core/DecoratorTiledBox.cpp

@@ -121,78 +121,89 @@ DecoratorDataHandle DecoratorTiledBox::GenerateElementData(Element* element) con
 
 
 	Vector2f padded_size = element->GetBox().GetSize(Box::PADDING);
 	Vector2f padded_size = element->GetBox().GetSize(Box::PADDING);
 
 
-	// Calculate the size for the top row of tiles.
-	Vector2f top_left_dimensions = tiles[TOP_LEFT_CORNER].GetDimensions(element);
-	Vector2f top_dimensions = tiles[TOP_EDGE].GetDimensions(element);
-	Vector2f top_right_dimensions = tiles[TOP_RIGHT_CORNER].GetDimensions(element);
 
 
-	// Calculate the size for the bottom row of tiles.
-	Vector2f bottom_left_dimensions = tiles[BOTTOM_LEFT_CORNER].GetDimensions(element);
-	Vector2f bottom_dimensions = tiles[BOTTOM_EDGE].GetDimensions(element);
-	Vector2f bottom_right_dimensions = tiles[BOTTOM_RIGHT_CORNER].GetDimensions(element);
+	// Calculate the natural dimensions of tile corners and edges.
+	const Vector2f natural_top_left = tiles[TOP_LEFT_CORNER].GetNaturalDimensions(element);
+	const Vector2f natural_top = tiles[TOP_EDGE].GetNaturalDimensions(element);
+	const Vector2f natural_top_right = tiles[TOP_RIGHT_CORNER].GetNaturalDimensions(element);
 
 
-	// The size of the left and right tiles.
-	Vector2f left_dimensions = tiles[LEFT_EDGE].GetDimensions(element);
-	Vector2f right_dimensions = tiles[RIGHT_EDGE].GetDimensions(element);
+	const Vector2f natural_bottom_left = tiles[BOTTOM_LEFT_CORNER].GetNaturalDimensions(element);
+	const Vector2f natural_bottom = tiles[BOTTOM_EDGE].GetNaturalDimensions(element);
+	const Vector2f natural_bottom_right = tiles[BOTTOM_RIGHT_CORNER].GetNaturalDimensions(element);
+
+	const Vector2f natural_left = tiles[LEFT_EDGE].GetNaturalDimensions(element);
+	const Vector2f natural_right = tiles[RIGHT_EDGE].GetNaturalDimensions(element);
+
+	// Initialize the to-be-determined dimensions of the tiles.
+	Vector2f top_left = natural_top_left;
+	Vector2f top = natural_top;
+	Vector2f top_right = natural_top_right;
+
+	Vector2f bottom_left = natural_bottom_left;
+	Vector2f bottom = natural_bottom;
+	Vector2f bottom_right = natural_bottom_right;
+	
+	Vector2f left = natural_left;
+	Vector2f right = natural_right;
 
 
 	// Scale the top corners down if appropriate. If they are scaled, then the left and right edges are also scaled
 	// Scale the top corners down if appropriate. If they are scaled, then the left and right edges are also scaled
 	// if they shared a width with their corner. Best solution? Don't know.
 	// if they shared a width with their corner. Best solution? Don't know.
-	if (padded_size.x < top_left_dimensions.x + top_right_dimensions.x)
+	if (padded_size.x < top_left.x + top_right.x)
 	{
 	{
-		float minimum_width = top_left_dimensions.x + top_right_dimensions.x;
+		float minimum_width = top_left.x + top_right.x;
 
 
-		top_left_dimensions.x = padded_size.x * (top_left_dimensions.x / minimum_width);
-		if (tiles[TOP_LEFT_CORNER].GetDimensions(element).x == tiles[LEFT_EDGE].GetDimensions(element).x)
-			left_dimensions.x = top_left_dimensions.x;
+		top_left.x = padded_size.x * (top_left.x / minimum_width);
+		if (natural_top_left.x == natural_left.x)
+			left.x = top_left.x;
 
 
-		top_right_dimensions.x = padded_size.x * (top_right_dimensions.x / minimum_width);
-		if (tiles[TOP_RIGHT_CORNER].GetDimensions(element).x == tiles[RIGHT_EDGE].GetDimensions(element).x)
-			right_dimensions.x = top_right_dimensions.x;
+		top_right.x = padded_size.x * (top_right.x / minimum_width);
+		if (natural_top_right.x == natural_right.x)
+			right.x = top_right.x;
 	}
 	}
 
 
 	// Scale the bottom corners down if appropriate. If they are scaled, then the left and right edges are also scaled
 	// Scale the bottom corners down if appropriate. If they are scaled, then the left and right edges are also scaled
 	// if they shared a width with their corner. Best solution? Don't know.
 	// if they shared a width with their corner. Best solution? Don't know.
-	if (padded_size.x < bottom_left_dimensions.x + bottom_right_dimensions.x)
+	if (padded_size.x < bottom_left.x + bottom_right.x)
 	{
 	{
-		float minimum_width = bottom_left_dimensions.x + bottom_right_dimensions.x;
+		float minimum_width = bottom_left.x + bottom_right.x;
 
 
-		bottom_left_dimensions.x = padded_size.x * (bottom_left_dimensions.x / minimum_width);
-		if (tiles[BOTTOM_LEFT_CORNER].GetDimensions(element).x == tiles[LEFT_EDGE].GetDimensions(element).x)
-			left_dimensions.x = bottom_left_dimensions.x;
+		bottom_left.x = padded_size.x * (bottom_left.x / minimum_width);
+		if (natural_bottom_left.x == natural_left.x)
+			left.x = bottom_left.x;
 
 
-		bottom_right_dimensions.x = padded_size.x * (bottom_right_dimensions.x / minimum_width);
-		if (tiles[BOTTOM_RIGHT_CORNER].GetDimensions(element).x == tiles[RIGHT_EDGE].GetDimensions(element).x)
-			right_dimensions.x = bottom_right_dimensions.x;
+		bottom_right.x = padded_size.x * (bottom_right.x / minimum_width);
+		if (natural_bottom_right.x == natural_right.x)
+			right.x = bottom_right.x;
 	}
 	}
 
 
 	// Scale the left corners down if appropriate. If they are scaled, then the top and bottom edges are also scaled
 	// Scale the left corners down if appropriate. If they are scaled, then the top and bottom edges are also scaled
 	// if they shared a width with their corner. Best solution? Don't know.
 	// if they shared a width with their corner. Best solution? Don't know.
-	if (padded_size.y < top_left_dimensions.y + bottom_left_dimensions.y)
+	if (padded_size.y < top_left.y + bottom_left.y)
 	{
 	{
-		float minimum_height = top_left_dimensions.y + bottom_left_dimensions.y;
+		float minimum_height = top_left.y + bottom_left.y;
 
 
-		top_left_dimensions.y = padded_size.y * (top_left_dimensions.y / minimum_height);
-		if (tiles[TOP_LEFT_CORNER].GetDimensions(element).y == tiles[TOP_EDGE].GetDimensions(element).y)
-			top_dimensions.y = top_left_dimensions.y;
+		top_left.y = padded_size.y * (top_left.y / minimum_height);
+		if (natural_top_left.y == natural_top.y)
+			top.y = top_left.y;
 
 
-		bottom_left_dimensions.y = padded_size.y * (bottom_left_dimensions.y / minimum_height);
-		if (tiles[BOTTOM_LEFT_CORNER].GetDimensions(element).y == tiles[BOTTOM_EDGE].GetDimensions(element).y)
-			bottom_dimensions.y = bottom_left_dimensions.y;
+		bottom_left.y = padded_size.y * (bottom_left.y / minimum_height);
+		if (natural_bottom_left.y == natural_bottom.y)
+			bottom.y = bottom_left.y;
 	}
 	}
 
 
 	// Scale the right corners down if appropriate. If they are scaled, then the top and bottom edges are also scaled
 	// Scale the right corners down if appropriate. If they are scaled, then the top and bottom edges are also scaled
 	// if they shared a width with their corner. Best solution? Don't know.
 	// if they shared a width with their corner. Best solution? Don't know.
-	if (padded_size.y < top_right_dimensions.y + bottom_right_dimensions.y)
+	if (padded_size.y < top_right.y + bottom_right.y)
 	{
 	{
-		float minimum_height = top_right_dimensions.y + bottom_right_dimensions.y;
+		float minimum_height = top_right.y + bottom_right.y;
 
 
-		top_right_dimensions.y = padded_size.y * (top_right_dimensions.y / minimum_height);
-		if (tiles[TOP_RIGHT_CORNER].GetDimensions(element).y == tiles[TOP_EDGE].GetDimensions(element).y)
-			top_dimensions.y = top_right_dimensions.y;
+		top_right.y = padded_size.y * (top_right.y / minimum_height);
+		if (natural_top_right.y == natural_top.y)
+			top.y = top_right.y;
 
 
-		bottom_right_dimensions.y = padded_size.y * (bottom_right_dimensions.y / minimum_height);
-		if (tiles[BOTTOM_RIGHT_CORNER].GetDimensions(element).y == tiles[BOTTOM_EDGE].GetDimensions(element).y)
-			bottom_dimensions.y = bottom_right_dimensions.y;
+		bottom_right.y = padded_size.y * (bottom_right.y / minimum_height);
+		if (natural_bottom_right.y == natural_bottom.y)
+			bottom.y = bottom_right.y;
 	}
 	}
 
 
 	const int num_textures = GetNumTextures();
 	const int num_textures = GetNumTextures();
@@ -203,70 +214,70 @@ DecoratorDataHandle DecoratorTiledBox::GenerateElementData(Element* element) con
 											data->geometry[tiles[TOP_LEFT_CORNER].texture_index].GetIndices(),
 											data->geometry[tiles[TOP_LEFT_CORNER].texture_index].GetIndices(),
 											element,
 											element,
 											Vector2f(0, 0),
 											Vector2f(0, 0),
-											top_left_dimensions,
-											top_left_dimensions);
+											top_left,
+											top_left);
 	// Generate the geometry for the top edge tiles.
 	// Generate the geometry for the top edge tiles.
 	tiles[TOP_EDGE].GenerateGeometry(data->geometry[tiles[TOP_EDGE].texture_index].GetVertices(),
 	tiles[TOP_EDGE].GenerateGeometry(data->geometry[tiles[TOP_EDGE].texture_index].GetVertices(),
 									 data->geometry[tiles[TOP_EDGE].texture_index].GetIndices(),
 									 data->geometry[tiles[TOP_EDGE].texture_index].GetIndices(),
 									 element,
 									 element,
-									 Vector2f(top_left_dimensions.x, 0),
-									 Vector2f(padded_size.x - (top_left_dimensions.x + top_right_dimensions.x), top_dimensions.y),
-									 top_dimensions);
+									 Vector2f(top_left.x, 0),
+									 Vector2f(padded_size.x - (top_left.x + top_right.x), top.y),
+									 top);
 	// Generate the geometry for the top-right tile.
 	// Generate the geometry for the top-right tile.
 	tiles[TOP_RIGHT_CORNER].GenerateGeometry(data->geometry[tiles[TOP_RIGHT_CORNER].texture_index].GetVertices(),
 	tiles[TOP_RIGHT_CORNER].GenerateGeometry(data->geometry[tiles[TOP_RIGHT_CORNER].texture_index].GetVertices(),
 											 data->geometry[tiles[TOP_RIGHT_CORNER].texture_index].GetIndices(),
 											 data->geometry[tiles[TOP_RIGHT_CORNER].texture_index].GetIndices(),
 											 element,
 											 element,
-											 Vector2f(padded_size.x - top_right_dimensions.x, 0),
-											 top_right_dimensions,
-											 top_right_dimensions);
+											 Vector2f(padded_size.x - top_right.x, 0),
+											 top_right,
+											 top_right);
 
 
 	// Generate the geometry for the left side.
 	// Generate the geometry for the left side.
 	tiles[LEFT_EDGE].GenerateGeometry(data->geometry[tiles[LEFT_EDGE].texture_index].GetVertices(),
 	tiles[LEFT_EDGE].GenerateGeometry(data->geometry[tiles[LEFT_EDGE].texture_index].GetVertices(),
 									  data->geometry[tiles[LEFT_EDGE].texture_index].GetIndices(),
 									  data->geometry[tiles[LEFT_EDGE].texture_index].GetIndices(),
 									  element,
 									  element,
-									  Vector2f(0, top_left_dimensions.y),
-									  Vector2f(left_dimensions.x, padded_size.y - (top_left_dimensions.y + bottom_left_dimensions.y)),
-									  left_dimensions);
+									  Vector2f(0, top_left.y),
+									  Vector2f(left.x, padded_size.y - (top_left.y + bottom_left.y)),
+									  left);
 
 
 	// Generate the geometry for the right side.
 	// Generate the geometry for the right side.
 	tiles[RIGHT_EDGE].GenerateGeometry(data->geometry[tiles[RIGHT_EDGE].texture_index].GetVertices(),
 	tiles[RIGHT_EDGE].GenerateGeometry(data->geometry[tiles[RIGHT_EDGE].texture_index].GetVertices(),
 									   data->geometry[tiles[RIGHT_EDGE].texture_index].GetIndices(),
 									   data->geometry[tiles[RIGHT_EDGE].texture_index].GetIndices(),
 									   element,
 									   element,
-									   Vector2f((padded_size.x - right_dimensions.x), top_right_dimensions.y),
-									   Vector2f(right_dimensions.x, padded_size.y - (top_right_dimensions.y + bottom_right_dimensions.y)),
-									   right_dimensions);
+									   Vector2f((padded_size.x - right.x), top_right.y),
+									   Vector2f(right.x, padded_size.y - (top_right.y + bottom_right.y)),
+									   right);
 
 
 	// Generate the geometry for the bottom-left tile.
 	// Generate the geometry for the bottom-left tile.
 	tiles[BOTTOM_LEFT_CORNER].GenerateGeometry(data->geometry[tiles[BOTTOM_LEFT_CORNER].texture_index].GetVertices(),
 	tiles[BOTTOM_LEFT_CORNER].GenerateGeometry(data->geometry[tiles[BOTTOM_LEFT_CORNER].texture_index].GetVertices(),
 											   data->geometry[tiles[BOTTOM_LEFT_CORNER].texture_index].GetIndices(),
 											   data->geometry[tiles[BOTTOM_LEFT_CORNER].texture_index].GetIndices(),
 											   element,
 											   element,
-											   Vector2f(0, padded_size.y - bottom_left_dimensions.y),
-											   bottom_left_dimensions,
-											   bottom_left_dimensions);
+											   Vector2f(0, padded_size.y - bottom_left.y),
+											   bottom_left,
+											   bottom_left);
 	// Generate the geometry for the bottom edge tiles.
 	// Generate the geometry for the bottom edge tiles.
 	tiles[BOTTOM_EDGE].GenerateGeometry(data->geometry[tiles[BOTTOM_EDGE].texture_index].GetVertices(),
 	tiles[BOTTOM_EDGE].GenerateGeometry(data->geometry[tiles[BOTTOM_EDGE].texture_index].GetVertices(),
 										data->geometry[tiles[BOTTOM_EDGE].texture_index].GetIndices(),
 										data->geometry[tiles[BOTTOM_EDGE].texture_index].GetIndices(),
 										element,
 										element,
-										Vector2f(bottom_left_dimensions.x, padded_size.y - bottom_dimensions.y),
-										Vector2f(padded_size.x - (bottom_left_dimensions.x + bottom_right_dimensions.x), bottom_dimensions.y),
-										bottom_dimensions);
+										Vector2f(bottom_left.x, padded_size.y - bottom.y),
+										Vector2f(padded_size.x - (bottom_left.x + bottom_right.x), bottom.y),
+										bottom);
 	// Generate the geometry for the bottom-right tile.
 	// Generate the geometry for the bottom-right tile.
 	tiles[BOTTOM_RIGHT_CORNER].GenerateGeometry(data->geometry[tiles[BOTTOM_RIGHT_CORNER].texture_index].GetVertices(),
 	tiles[BOTTOM_RIGHT_CORNER].GenerateGeometry(data->geometry[tiles[BOTTOM_RIGHT_CORNER].texture_index].GetVertices(),
 												data->geometry[tiles[BOTTOM_RIGHT_CORNER].texture_index].GetIndices(),
 												data->geometry[tiles[BOTTOM_RIGHT_CORNER].texture_index].GetIndices(),
 												element,
 												element,
-												Vector2f(padded_size.x - bottom_right_dimensions.x, padded_size.y - bottom_right_dimensions.y),
-												bottom_right_dimensions,
-												bottom_right_dimensions);
+												Vector2f(padded_size.x - bottom_right.x, padded_size.y - bottom_right.y),
+												bottom_right,
+												bottom_right);
 
 
 	// Generate the centre geometry.
 	// Generate the centre geometry.
-	Vector2f centre_dimensions = tiles[CENTRE].GetDimensions(element);
-	Vector2f centre_surface_dimensions(padded_size.x - (left_dimensions.x + right_dimensions.x),
-											padded_size.y - (top_dimensions.y + bottom_dimensions.y));
+	Vector2f centre_dimensions = tiles[CENTRE].GetNaturalDimensions(element);
+	Vector2f centre_surface_dimensions(padded_size.x - (left.x + right.x),
+											padded_size.y - (top.y + bottom.y));
 
 
 	tiles[CENTRE].GenerateGeometry(data->geometry[tiles[CENTRE].texture_index].GetVertices(),
 	tiles[CENTRE].GenerateGeometry(data->geometry[tiles[CENTRE].texture_index].GetVertices(),
 									data->geometry[tiles[CENTRE].texture_index].GetIndices(),
 									data->geometry[tiles[CENTRE].texture_index].GetIndices(),
 									element,
 									element,
-									Vector2f(left_dimensions.x, top_dimensions.y),
+									Vector2f(left.x, top.y),
 									centre_surface_dimensions,
 									centre_surface_dimensions,
 									centre_dimensions);
 									centre_dimensions);
 
 

+ 6 - 6
Source/Core/DecoratorTiledHorizontal.cpp

@@ -101,14 +101,14 @@ DecoratorDataHandle DecoratorTiledHorizontal::GenerateElementData(Element* eleme
 
 
 	Vector2f padded_size = element->GetBox().GetSize(Box::PADDING);
 	Vector2f padded_size = element->GetBox().GetSize(Box::PADDING);
 
 
-	Vector2f left_dimensions = tiles[LEFT].GetDimensions(element);
-	Vector2f right_dimensions = tiles[RIGHT].GetDimensions(element);
-	Vector2f centre_dimensions = tiles[CENTRE].GetDimensions(element);
+	Vector2f left_dimensions = tiles[LEFT].GetNaturalDimensions(element);
+	Vector2f right_dimensions = tiles[RIGHT].GetNaturalDimensions(element);
+	Vector2f centre_dimensions = tiles[CENTRE].GetNaturalDimensions(element);
 
 
 	// Scale the tile sizes by the height scale.
 	// Scale the tile sizes by the height scale.
-	ScaleTileDimensions(left_dimensions, padded_size.y, 1);
-	ScaleTileDimensions(right_dimensions, padded_size.y, 1);
-	ScaleTileDimensions(centre_dimensions, padded_size.y, 1);
+	ScaleTileDimensions(left_dimensions, padded_size.y, Axis::Vertical);
+	ScaleTileDimensions(right_dimensions, padded_size.y, Axis::Vertical);
+	ScaleTileDimensions(centre_dimensions, padded_size.y, Axis::Vertical);
 
 
 	// Round the outer tile widths now so that we don't get gaps when rounding again in GenerateGeometry.
 	// Round the outer tile widths now so that we don't get gaps when rounding again in GenerateGeometry.
 	left_dimensions.x = Math::RoundFloat(left_dimensions.x);
 	left_dimensions.x = Math::RoundFloat(left_dimensions.x);

+ 1 - 1
Source/Core/DecoratorTiledImage.cpp

@@ -58,7 +58,7 @@ DecoratorDataHandle DecoratorTiledImage::GenerateElementData(Element* element) c
 	data->SetTexture(GetTexture());
 	data->SetTexture(GetTexture());
 
 
 	// Generate the geometry for the tile.
 	// Generate the geometry for the tile.
-	tile.GenerateGeometry(data->GetVertices(), data->GetIndices(), element, Vector2f(0, 0), element->GetBox().GetSize(Box::PADDING), tile.GetDimensions(element));
+	tile.GenerateGeometry(data->GetVertices(), data->GetIndices(), element, Vector2f(0, 0), element->GetBox().GetSize(Box::PADDING), tile.GetNaturalDimensions(element));
 
 
 	return reinterpret_cast<DecoratorDataHandle>(data);
 	return reinterpret_cast<DecoratorDataHandle>(data);
 }
 }

+ 1 - 0
Source/Core/DecoratorTiledInstancer.cpp

@@ -114,6 +114,7 @@ bool DecoratorTiledInstancer::GetTileProperties(DecoratorTiled::Tile* tiles, Tex
 			tile.position.y = sprite->rectangle.y;
 			tile.position.y = sprite->rectangle.y;
 			tile.size.x = sprite->rectangle.width;
 			tile.size.x = sprite->rectangle.width;
 			tile.size.y = sprite->rectangle.height;
 			tile.size.y = sprite->rectangle.height;
+			tile.display_scale = sprite->sprite_sheet->display_scale;
 
 
 			texture = sprite->sprite_sheet->texture;
 			texture = sprite->sprite_sheet->texture;
 		}
 		}

+ 6 - 6
Source/Core/DecoratorTiledVertical.cpp

@@ -102,14 +102,14 @@ DecoratorDataHandle DecoratorTiledVertical::GenerateElementData(Element* element
 
 
 	Vector2f padded_size = element->GetBox().GetSize(Box::PADDING);
 	Vector2f padded_size = element->GetBox().GetSize(Box::PADDING);
 
 
-	Vector2f top_dimensions = tiles[TOP].GetDimensions(element);
-	Vector2f bottom_dimensions = tiles[BOTTOM].GetDimensions(element);
-	Vector2f centre_dimensions = tiles[CENTRE].GetDimensions(element);
+	Vector2f top_dimensions = tiles[TOP].GetNaturalDimensions(element);
+	Vector2f bottom_dimensions = tiles[BOTTOM].GetNaturalDimensions(element);
+	Vector2f centre_dimensions = tiles[CENTRE].GetNaturalDimensions(element);
 
 
 	// Scale the tile sizes by the width scale.
 	// Scale the tile sizes by the width scale.
-	ScaleTileDimensions(top_dimensions, padded_size.x, 0);
-	ScaleTileDimensions(bottom_dimensions, padded_size.x, 0);
-	ScaleTileDimensions(centre_dimensions, padded_size.x, 0);
+	ScaleTileDimensions(top_dimensions, padded_size.x, Axis::Horizontal);
+	ScaleTileDimensions(bottom_dimensions, padded_size.x, Axis::Horizontal);
+	ScaleTileDimensions(centre_dimensions, padded_size.x, Axis::Horizontal);
 
 
 	// Round the outer tile heights now so that we don't get gaps when rounding again in GenerateGeometry.
 	// Round the outer tile heights now so that we don't get gaps when rounding again in GenerateGeometry.
 	top_dimensions.y = Math::RoundFloat(top_dimensions.y);
 	top_dimensions.y = Math::RoundFloat(top_dimensions.y);

+ 4 - 2
Source/Core/Elements/ElementImage.cpp

@@ -215,6 +215,8 @@ bool ElementImage::LoadTexture()
 	geometry_dirty = true;
 	geometry_dirty = true;
 	dimensions_scale = 1.0f;
 	dimensions_scale = 1.0f;
 
 
+	const float dp_ratio = ElementUtilities::GetDensityIndependentPixelRatio(this);
+
 	// Check for a sprite first, this takes precedence.
 	// Check for a sprite first, this takes precedence.
 	const String sprite_name = GetAttribute< String >("sprite", "");
 	const String sprite_name = GetAttribute< String >("sprite", "");
 	if (!sprite_name.empty())
 	if (!sprite_name.empty())
@@ -231,7 +233,7 @@ bool ElementImage::LoadTexture()
 					rect = sprite->rectangle;
 					rect = sprite->rectangle;
 					rect_source = RectSource::Sprite;
 					rect_source = RectSource::Sprite;
 					texture = sprite->sprite_sheet->texture;
 					texture = sprite->sprite_sheet->texture;
-					dimensions_scale = sprite->sprite_sheet->image_inv_scale * ElementUtilities::GetDensityIndependentPixelRatio(this);
+					dimensions_scale = sprite->sprite_sheet->display_scale * dp_ratio;
 					valid_sprite = true;
 					valid_sprite = true;
 				}
 				}
 			}
 			}
@@ -264,7 +266,7 @@ bool ElementImage::LoadTexture()
 
 
 		texture.Set(source_name, source_url.GetPath());
 		texture.Set(source_name, source_url.GetPath());
 
 
-		dimensions_scale = ElementUtilities::GetDensityIndependentPixelRatio(this);
+		dimensions_scale = dp_ratio;
 	}
 	}
 
 
 	// Set the texture onto our geometry object.
 	// Set the texture onto our geometry object.

+ 4 - 4
Source/Core/Spritesheet.cpp

@@ -34,18 +34,18 @@ namespace Rml {
 
 
 
 
 Spritesheet::Spritesheet(const String& name, const String& image_source, const String& definition_source,
 Spritesheet::Spritesheet(const String& name, const String& image_source, const String& definition_source,
-	int definition_line_number, float image_inv_scale, const Texture& texture)
+	int definition_line_number, float display_scale, const Texture& texture)
 	: name(name), image_source(image_source), definition_source(definition_source),
 	: name(name), image_source(image_source), definition_source(definition_source),
-	definition_line_number(definition_line_number), image_inv_scale(image_inv_scale), texture(texture)
+	definition_line_number(definition_line_number), display_scale(display_scale), texture(texture)
 {}
 {}
 
 
-bool SpritesheetList::AddSpriteSheet(const String& name, const String& image_source, const String& definition_source, int definition_line_number, float image_inv_scale, const SpriteDefinitionList& sprite_definitions)
+bool SpritesheetList::AddSpriteSheet(const String& name, const String& image_source, const String& definition_source, int definition_line_number, float display_scale, const SpriteDefinitionList& sprite_definitions)
 {
 {
 	// Load the texture
 	// Load the texture
 	Texture texture;
 	Texture texture;
 	texture.Set(image_source, definition_source);
 	texture.Set(image_source, definition_source);
 
 
-	auto sprite_sheet = MakeShared<Spritesheet>(name, image_source, definition_source, definition_line_number, image_inv_scale, texture);
+	auto sprite_sheet = MakeShared<Spritesheet>(name, image_source, definition_source, definition_line_number, display_scale, texture);
 	auto result = spritesheet_map.emplace(name, sprite_sheet);
 	auto result = spritesheet_map.emplace(name, sprite_sheet);
 	if (!result.second)
 	if (!result.second)
 	{
 	{

+ 2 - 2
Source/Core/StyleSheetParser.cpp

@@ -641,8 +641,8 @@ int StyleSheetParser::Parse(MediaBlockList& style_sheets, Stream* _stream, int b
 						}
 						}
 						else
 						else
 						{
 						{
-							const float image_inv_scale = 1.0f / image_resolution_factor;
-							current_block.stylesheet->spritesheet_list.AddSpriteSheet(at_rule_name, image_source, stream_file_name, (int)line_number, image_inv_scale, sprite_definitions);
+							const float display_scale = 1.0f / image_resolution_factor;
+							current_block.stylesheet->spritesheet_list.AddSpriteSheet(at_rule_name, image_source, stream_file_name, (int)line_number, display_scale, sprite_definitions);
 						}
 						}
 
 
 						spritesheet_property_parser->Clear();
 						spritesheet_property_parser->Clear();