summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-03-24 21:24:19 +0100
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-03-24 21:24:19 +0100
commit2739d3cface75a5477918ce03bd2f85b3244fe1a (patch)
treee3972d9a6c5eb1d0ddfdb73038055547b9291233 /src
parentc600e0fae271ed25d066b01149fbc148295edde8 (diff)
downloadmana-2739d3cface75a5477918ce03bd2f85b3244fe1a.tar.gz
mana-2739d3cface75a5477918ce03bd2f85b3244fe1a.tar.bz2
mana-2739d3cface75a5477918ce03bd2f85b3244fe1a.tar.xz
mana-2739d3cface75a5477918ce03bd2f85b3244fe1a.zip
Added fill mode parameter to ImageRect
ImageRect now stretches the sides and center images by default because this is more efficient these days. FilMode::Repeat can be specified when repetition is desired. Added 'fill' attribute to allow the fill mode to be specified for the GUI theme images.
Diffstat (limited to 'src')
-rw-r--r--src/graphics.cpp124
-rw-r--r--src/graphics.h15
-rw-r--r--src/resources/theme.cpp11
3 files changed, 113 insertions, 37 deletions
diff --git a/src/graphics.cpp b/src/graphics.cpp
index e9ccfc49..72101069 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -81,6 +81,14 @@ bool Graphics::drawImageF(const Image *image, float x, float y)
return drawImageF(image, 0, 0, x, y, image->getWidth(), image->getHeight());
}
+bool Graphics::drawRescaledImage(const Image *image, int x, int y, int width, int height)
+{
+ if (!image)
+ return false;
+
+ return drawRescaledImage(image, 0, 0, x, y, image->getWidth(), image->getHeight(), width, height);
+}
+
bool Graphics::drawRescaledImageF(const Image *image, int srcX, int srcY, float dstX, float dstY, int width, int height, float desiredWidth, float desiredHeight, bool useColor)
{
return drawRescaledImage(image,
@@ -129,51 +137,95 @@ void Graphics::drawImageRect(int x, int y, int w, int h,
const Image *bottomLeft, const Image *bottomRight,
const Image *top, const Image *right,
const Image *bottom, const Image *left,
- const Image *center)
-{
- pushClipArea(gcn::Rectangle(x, y, w, h));
-
- // Draw the center area
- drawImagePattern(center,
- topLeft->getWidth(), topLeft->getHeight(),
- w - topLeft->getWidth() - topRight->getWidth(),
- h - topLeft->getHeight() - bottomLeft->getHeight());
-
- // Draw the sides
- drawImagePattern(top,
- left->getWidth(), 0,
- w - left->getWidth() - right->getWidth(), top->getHeight());
- drawImagePattern(bottom,
- left->getWidth(), h - bottom->getHeight(),
- w - left->getWidth() - right->getWidth(),
- bottom->getHeight());
- drawImagePattern(left,
- 0, top->getHeight(),
- left->getWidth(),
- h - top->getHeight() - bottom->getHeight());
- drawImagePattern(right,
- w - right->getWidth(), top->getHeight(),
- right->getWidth(),
- h - top->getHeight() - bottom->getHeight());
+ const Image *center,
+ FillMode fillMode)
+{
+ switch (fillMode) {
+ case FillMode::Stretch:
+ // Draw the center area
+ drawRescaledImage(center,
+ x + topLeft->getWidth(),
+ y + topLeft->getHeight(),
+ w - topLeft->getWidth() - topRight->getWidth(),
+ h - topLeft->getHeight() - bottomLeft->getHeight());
+
+ // Draw the sides
+ drawRescaledImage(top,
+ x + left->getWidth(),
+ y,
+ w - left->getWidth() - right->getWidth(),
+ top->getHeight());
+
+ drawRescaledImage(bottom,
+ x + left->getWidth(),
+ y + h - bottom->getHeight(),
+ w - left->getWidth() - right->getWidth(),
+ bottom->getHeight());
+
+ drawRescaledImage(left,
+ x,
+ y + top->getHeight(),
+ left->getWidth(),
+ h - top->getHeight() - bottom->getHeight());
+
+ drawRescaledImage(right,
+ x + w - right->getWidth(),
+ y + top->getHeight(),
+ right->getWidth(),
+ h - top->getHeight() - bottom->getHeight());
+ break;
+ case FillMode::Repeat:
+ // Draw the center area
+ drawImagePattern(center,
+ x + topLeft->getWidth(),
+ y + topLeft->getHeight(),
+ w - topLeft->getWidth() - topRight->getWidth(),
+ h - topLeft->getHeight() - bottomLeft->getHeight());
+
+ // Draw the sides
+ drawImagePattern(top,
+ x + left->getWidth(),
+ y,
+ w - left->getWidth() - right->getWidth(),
+ top->getHeight());
+
+ drawImagePattern(bottom,
+ x + left->getWidth(),
+ y + h - bottom->getHeight(),
+ w - left->getWidth() - right->getWidth(),
+ bottom->getHeight());
+
+ drawImagePattern(left,
+ x,
+ y + top->getHeight(),
+ left->getWidth(),
+ h - top->getHeight() - bottom->getHeight());
+
+ drawImagePattern(right,
+ x + w - right->getWidth(),
+ y + top->getHeight(),
+ right->getWidth(),
+ h - top->getHeight() - bottom->getHeight());
+ break;
+ }
// Draw the corners
- drawImage(topLeft, 0, 0);
- drawImage(topRight, w - topRight->getWidth(), 0);
- drawImage(bottomLeft, 0, h - bottomLeft->getHeight());
+ drawImage(topLeft, x, y);
+ drawImage(topRight, x + w - topRight->getWidth(), y);
+ drawImage(bottomLeft, x, y + h - bottomLeft->getHeight());
drawImage(bottomRight,
- w - bottomRight->getWidth(),
- h - bottomRight->getHeight());
-
- popClipArea();
+ x + w - bottomRight->getWidth(),
+ y + h - bottomRight->getHeight());
}
void Graphics::drawImageRect(int x, int y, int w, int h,
const ImageRect &imgRect)
{
drawImageRect(x, y, w, h,
- imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8],
- imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3],
- imgRect.grid[4]);
+ imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8],
+ imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3],
+ imgRect.grid[4],
+ imgRect.fillMode);
}
void Graphics::_beginDraw()
diff --git a/src/graphics.h b/src/graphics.h
index 085ad5d4..4df63932 100644
--- a/src/graphics.h
+++ b/src/graphics.h
@@ -28,6 +28,12 @@
class Image;
+enum class FillMode
+{
+ Stretch,
+ Repeat,
+};
+
/**
* 9 images defining a rectangle. 4 corners, 4 sides and a middle area. The
* topology is as follows:
@@ -70,6 +76,7 @@ public:
ImageRect &operator=(ImageRect &&r) = delete;
Image *grid[9];
+ FillMode fillMode = FillMode::Stretch;
void setAlpha(float alpha);
int minWidth() const;
@@ -115,6 +122,11 @@ class Graphics : public gcn::Graphics
/**
* Draws a rescaled version of the image.
*/
+ bool drawRescaledImage(const Image *image, int x, int y, int width, int height);
+
+ /**
+ * Draws a rescaled version of the image.
+ */
virtual bool drawRescaledImage(const Image *image, int srcX, int srcY,
int dstX, int dstY,
int width, int height,
@@ -176,7 +188,8 @@ class Graphics : public gcn::Graphics
const Image *bottomLeft, const Image *bottomRight,
const Image *top, const Image *right,
const Image *bottom, const Image *left,
- const Image *center);
+ const Image *center,
+ FillMode fillMode = FillMode::Stretch);
/**
* Draws a rectangle using images. 4 corner images, 4 side images and 1
diff --git a/src/resources/theme.cpp b/src/resources/theme.cpp
index 995d347f..70aaff83 100644
--- a/src/resources/theme.cpp
+++ b/src/resources/theme.cpp
@@ -503,6 +503,15 @@ void Theme::readSkinStateNode(XML::Node node, Skin &skin) const
skin.addState(std::move(state));
}
+template<>
+inline void fromString(const char *str, FillMode &value)
+{
+ if (strcmp(str, "repeat") == 0)
+ value = FillMode::Repeat;
+ else if (strcmp(str, "stretch") == 0)
+ value = FillMode::Stretch;
+}
+
void Theme::readSkinStateImgNode(XML::Node node, SkinState &state) const
{
const std::string src = node.getProperty("src", std::string());
@@ -549,6 +558,8 @@ void Theme::readSkinStateImgNode(XML::Node node, SkinState &state) const
{
auto &border = part.data.emplace<ImageRect>();
+ node.attribute("fill", border.fillMode);
+
const int gridx[4] = {x, x + left, x + width - right, x + width};
const int gridy[4] = {y, y + top, y + height - bottom, y + height};
unsigned a = 0;