summaryrefslogtreecommitdiffstats
path: root/xbmc/guilib/GUITexture.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
commitc04dcc2e7d834218ef2d4194331e383402495ae1 (patch)
tree7333e38d10d75386e60f336b80c2443c1166031d /xbmc/guilib/GUITexture.cpp
parentInitial commit. (diff)
downloadkodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz
kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/guilib/GUITexture.cpp')
-rw-r--r--xbmc/guilib/GUITexture.cpp714
1 files changed, 714 insertions, 0 deletions
diff --git a/xbmc/guilib/GUITexture.cpp b/xbmc/guilib/GUITexture.cpp
new file mode 100644
index 0000000..7f2f51d
--- /dev/null
+++ b/xbmc/guilib/GUITexture.cpp
@@ -0,0 +1,714 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "GUITexture.h"
+
+#include "GUILargeTextureManager.h"
+#include "TextureManager.h"
+#include "utils/MathUtils.h"
+#include "utils/StringUtils.h"
+#include "windowing/GraphicContext.h"
+
+#include <stdexcept>
+
+CreateGUITextureFunc CGUITexture::m_createGUITextureFunc;
+DrawQuadFunc CGUITexture::m_drawQuadFunc;
+
+CTextureInfo::CTextureInfo()
+{
+ orientation = 0;
+ useLarge = false;
+}
+
+CTextureInfo::CTextureInfo(const std::string &file):
+ filename(file)
+{
+ orientation = 0;
+ useLarge = false;
+}
+
+void CGUITexture::Register(const CreateGUITextureFunc& createFunction,
+ const DrawQuadFunc& drawQuadFunction)
+{
+ m_createGUITextureFunc = createFunction;
+ m_drawQuadFunc = drawQuadFunction;
+}
+
+CGUITexture* CGUITexture::CreateTexture(
+ float posX, float posY, float width, float height, const CTextureInfo& texture)
+{
+ if (!m_createGUITextureFunc)
+ throw std::runtime_error(
+ "No GUITexture Create function available. Did you forget to register?");
+
+ return m_createGUITextureFunc(posX, posY, width, height, texture);
+}
+
+void CGUITexture::DrawQuad(const CRect& coords,
+ UTILS::COLOR::Color color,
+ CTexture* texture,
+ const CRect* texCoords)
+{
+ if (!m_drawQuadFunc)
+ throw std::runtime_error(
+ "No GUITexture DrawQuad function available. Did you forget to register?");
+
+ m_drawQuadFunc(coords, color, texture, texCoords);
+}
+
+CGUITexture::CGUITexture(
+ float posX, float posY, float width, float height, const CTextureInfo& texture)
+ : m_height(height), m_info(texture)
+{
+ m_posX = posX;
+ m_posY = posY;
+ m_width = width;
+
+ // defaults
+ m_visible = true;
+ m_diffuseColor = 0xffffffff;
+ m_alpha = 0xff;
+
+ m_vertex.SetRect(m_posX, m_posY, m_posX + m_width, m_posY + m_height);
+
+ m_frameWidth = 0;
+ m_frameHeight = 0;
+
+ m_texCoordsScaleU = 1.0f;
+ m_texCoordsScaleV = 1.0f;
+ m_diffuseU = 1.0f;
+ m_diffuseV = 1.0f;
+ m_diffuseScaleU = 1.0f;
+ m_diffuseScaleV = 1.0f;
+
+ // anim gifs
+ ResetAnimState();
+
+ m_allocateDynamically = false;
+ m_isAllocated = NO;
+ m_invalid = true;
+ m_use_cache = true;
+}
+
+CGUITexture::CGUITexture(const CGUITexture& right)
+ : m_visible(right.m_visible),
+ m_diffuseColor(right.m_diffuseColor),
+ m_posX(right.m_posX),
+ m_posY(right.m_posY),
+ m_width(right.m_width),
+ m_height(right.m_height),
+ m_use_cache(right.m_use_cache),
+ m_alpha(right.m_alpha),
+ m_allocateDynamically(right.m_allocateDynamically),
+ m_info(right.m_info),
+ m_aspect(right.m_aspect)
+{
+ // defaults
+ m_vertex.SetRect(m_posX, m_posY, m_posX + m_width, m_posY + m_height);
+
+ m_frameWidth = 0;
+ m_frameHeight = 0;
+
+ m_texCoordsScaleU = 1.0f;
+ m_texCoordsScaleV = 1.0f;
+ m_diffuseU = 1.0f;
+ m_diffuseV = 1.0f;
+ m_diffuseScaleU = 1.0f;
+ m_diffuseScaleV = 1.0f;
+
+ ResetAnimState();
+
+ m_isAllocated = NO;
+ m_invalid = true;
+}
+
+bool CGUITexture::AllocateOnDemand()
+{
+ if (m_visible)
+ { // visible, so make sure we're allocated
+ if (!IsAllocated() || (m_isAllocated == LARGE && !m_texture.size()))
+ return AllocResources();
+ }
+ else
+ { // hidden, so deallocate as applicable
+ if (m_allocateDynamically && IsAllocated())
+ FreeResources();
+ // reset animated textures (animgifs)
+ ResetAnimState();
+ }
+
+ return false;
+}
+
+bool CGUITexture::Process(unsigned int currentTime)
+{
+ bool changed = false;
+ // check if we need to allocate our resources
+ changed |= AllocateOnDemand();
+
+ if (m_texture.size() > 1)
+ changed |= UpdateAnimFrame(currentTime);
+
+ if (m_invalid)
+ changed |= CalculateSize();
+
+ if (m_isAllocated)
+ changed |= !ReadyToRender();
+
+ return changed;
+}
+
+void CGUITexture::Render()
+{
+ if (!m_visible || !m_texture.size())
+ return;
+
+ // see if we need to clip the image
+ if (m_vertex.Width() > m_width || m_vertex.Height() > m_height)
+ {
+ if (!CServiceBroker::GetWinSystem()->GetGfxContext().SetClipRegion(m_posX, m_posY, m_width, m_height))
+ return;
+ }
+
+ // set our draw color
+ #define MIX_ALPHA(a,c) (((a * (c >> 24)) / 255) << 24) | (c & 0x00ffffff)
+
+ // diffuse color
+ UTILS::COLOR::Color color =
+ (m_info.diffuseColor) ? (UTILS::COLOR::Color)m_info.diffuseColor : m_diffuseColor;
+ if (m_alpha != 0xFF)
+ color = MIX_ALPHA(m_alpha, color);
+
+ color = CServiceBroker::GetWinSystem()->GetGfxContext().MergeColor(color);
+
+ // setup our renderer
+ Begin(color);
+
+ // compute the texture coordinates
+ float u1, u2, u3, v1, v2, v3;
+ u1 = m_info.border.x1;
+ u2 = m_frameWidth - m_info.border.x2;
+ u3 = m_frameWidth;
+ v1 = m_info.border.y1;
+ v2 = m_frameHeight - m_info.border.y2;
+ v3 = m_frameHeight;
+
+ if (!m_texture.m_texCoordsArePixels)
+ {
+ u1 *= m_texCoordsScaleU;
+ u2 *= m_texCoordsScaleU;
+ u3 *= m_texCoordsScaleU;
+ v1 *= m_texCoordsScaleV;
+ v2 *= m_texCoordsScaleV;
+ v3 *= m_texCoordsScaleV;
+ }
+
+ //! @todo The diffuse coloring applies to all vertices, which will
+ //! look weird for stuff with borders, as will the -ve height/width
+ //! for flipping
+
+ // left segment (0,0,u1,v3)
+ if (m_info.border.x1)
+ {
+ if (m_info.border.y1)
+ Render(m_vertex.x1, m_vertex.y1, m_vertex.x1 + m_info.border.x1, m_vertex.y1 + m_info.border.y1, 0, 0, u1, v1, u3, v3);
+ Render(m_vertex.x1, m_vertex.y1 + m_info.border.y1, m_vertex.x1 + m_info.border.x1, m_vertex.y2 - m_info.border.y2, 0, v1, u1, v2, u3, v3);
+ if (m_info.border.y2)
+ Render(m_vertex.x1, m_vertex.y2 - m_info.border.y2, m_vertex.x1 + m_info.border.x1, m_vertex.y2, 0, v2, u1, v3, u3, v3);
+ }
+ // middle segment (u1,0,u2,v3)
+ if (m_info.border.y1)
+ Render(m_vertex.x1 + m_info.border.x1, m_vertex.y1, m_vertex.x2 - m_info.border.x2, m_vertex.y1 + m_info.border.y1, u1, 0, u2, v1, u3, v3);
+ if (m_info.m_infill)
+ Render(m_vertex.x1 + m_info.border.x1, m_vertex.y1 + m_info.border.y1,
+ m_vertex.x2 - m_info.border.x2, m_vertex.y2 - m_info.border.y2, u1, v1, u2, v2, u3, v3);
+ if (m_info.border.y2)
+ Render(m_vertex.x1 + m_info.border.x1, m_vertex.y2 - m_info.border.y2, m_vertex.x2 - m_info.border.x2, m_vertex.y2, u1, v2, u2, v3, u3, v3);
+ // right segment
+ if (m_info.border.x2)
+ { // have a left border
+ if (m_info.border.y1)
+ Render(m_vertex.x2 - m_info.border.x2, m_vertex.y1, m_vertex.x2, m_vertex.y1 + m_info.border.y1, u2, 0, u3, v1, u3, v3);
+ Render(m_vertex.x2 - m_info.border.x2, m_vertex.y1 + m_info.border.y1, m_vertex.x2, m_vertex.y2 - m_info.border.y2, u2, v1, u3, v2, u3, v3);
+ if (m_info.border.y2)
+ Render(m_vertex.x2 - m_info.border.x2, m_vertex.y2 - m_info.border.y2, m_vertex.x2, m_vertex.y2, u2, v2, u3, v3, u3, v3);
+ }
+
+ // close off our renderer
+ End();
+
+ if (m_vertex.Width() > m_width || m_vertex.Height() > m_height)
+ CServiceBroker::GetWinSystem()->GetGfxContext().RestoreClipRegion();
+}
+
+void CGUITexture::Render(float left,
+ float top,
+ float right,
+ float bottom,
+ float u1,
+ float v1,
+ float u2,
+ float v2,
+ float u3,
+ float v3)
+{
+ CRect diffuse(u1, v1, u2, v2);
+ CRect texture(u1, v1, u2, v2);
+ CRect vertex(left, top, right, bottom);
+ CServiceBroker::GetWinSystem()->GetGfxContext().ClipRect(vertex, texture, m_diffuse.size() ? &diffuse : NULL);
+
+ if (vertex.IsEmpty())
+ return; // nothing to render
+
+ int orientation = GetOrientation();
+ OrientateTexture(texture, u3, v3, orientation);
+
+ if (m_diffuse.size())
+ {
+ // flip the texture as necessary. Diffuse just gets flipped according to m_info.orientation.
+ // Main texture gets flipped according to GetOrientation().
+ diffuse.x1 *= m_diffuseScaleU / u3; diffuse.x2 *= m_diffuseScaleU / u3;
+ diffuse.y1 *= m_diffuseScaleV / v3; diffuse.y2 *= m_diffuseScaleV / v3;
+ diffuse += m_diffuseOffset;
+ OrientateTexture(diffuse, m_diffuseU, m_diffuseV, m_info.orientation);
+ }
+
+ float x[4], y[4], z[4];
+
+#define ROUND_TO_PIXEL(x) static_cast<float>(MathUtils::round_int(static_cast<double>(x)))
+
+ x[0] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalXCoord(vertex.x1, vertex.y1));
+ y[0] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalYCoord(vertex.x1, vertex.y1));
+ z[0] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalZCoord(vertex.x1, vertex.y1));
+ x[1] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalXCoord(vertex.x2, vertex.y1));
+ y[1] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalYCoord(vertex.x2, vertex.y1));
+ z[1] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalZCoord(vertex.x2, vertex.y1));
+ x[2] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalXCoord(vertex.x2, vertex.y2));
+ y[2] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalYCoord(vertex.x2, vertex.y2));
+ z[2] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalZCoord(vertex.x2, vertex.y2));
+ x[3] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalXCoord(vertex.x1, vertex.y2));
+ y[3] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalYCoord(vertex.x1, vertex.y2));
+ z[3] = ROUND_TO_PIXEL(CServiceBroker::GetWinSystem()->GetGfxContext().ScaleFinalZCoord(vertex.x1, vertex.y2));
+
+ if (y[2] == y[0]) y[2] += 1.0f;
+ if (x[2] == x[0]) x[2] += 1.0f;
+ if (y[3] == y[1]) y[3] += 1.0f;
+ if (x[3] == x[1]) x[3] += 1.0f;
+
+ Draw(x, y, z, texture, diffuse, orientation);
+}
+
+bool CGUITexture::AllocResources()
+{
+ if (m_info.filename.empty())
+ return false;
+
+ if (m_texture.size())
+ return false; // already have our texture
+
+ // reset our animstate
+ ResetAnimState();
+
+ bool changed = false;
+ bool useLarge = m_info.useLarge || !CServiceBroker::GetGUI()->GetTextureManager().CanLoad(m_info.filename);
+ if (useLarge)
+ { // we want to use the large image loader, but we first check for bundled textures
+ if (!IsAllocated())
+ {
+ CTextureArray texture;
+ texture = CServiceBroker::GetGUI()->GetTextureManager().Load(m_info.filename, true);
+ if (texture.size())
+ {
+ m_isAllocated = NORMAL;
+ m_texture = texture;
+ changed = true;
+ }
+ }
+ if (m_isAllocated != NORMAL)
+ { // use our large image background loader
+ CTextureArray texture;
+ if (CServiceBroker::GetGUI()->GetLargeTextureManager().GetImage(m_info.filename, texture, !IsAllocated(), m_use_cache))
+ {
+ m_isAllocated = LARGE;
+
+ if (!texture.size()) // not ready as yet
+ return false;
+
+ m_texture = texture;
+
+ changed = true;
+ }
+ else
+ m_isAllocated = LARGE_FAILED;
+ }
+ }
+ else if (!IsAllocated())
+ {
+ CTextureArray texture = CServiceBroker::GetGUI()->GetTextureManager().Load(m_info.filename);
+
+ // set allocated to true even if we couldn't load the image to save
+ // us hitting the disk every frame
+ m_isAllocated = texture.size() ? NORMAL : NORMAL_FAILED;
+ if (!texture.size())
+ return false;
+ m_texture = texture;
+ changed = true;
+ }
+ m_frameWidth = (float)m_texture.m_width;
+ m_frameHeight = (float)m_texture.m_height;
+
+ // load the diffuse texture (if necessary)
+ if (!m_info.diffuse.empty())
+ {
+ m_diffuse = CServiceBroker::GetGUI()->GetTextureManager().Load(m_info.diffuse);
+ }
+
+ CalculateSize();
+
+ // call our implementation
+ Allocate();
+
+ return changed;
+}
+
+bool CGUITexture::CalculateSize()
+{
+ if (m_currentFrame >= m_texture.size())
+ return false;
+
+ m_texCoordsScaleU = 1.0f / m_texture.m_texWidth;
+ m_texCoordsScaleV = 1.0f / m_texture.m_texHeight;
+
+ if (m_width == 0)
+ m_width = m_frameWidth;
+ if (m_height == 0)
+ m_height = m_frameHeight;
+
+ float newPosX = m_posX;
+ float newPosY = m_posY;
+ float newWidth = m_width;
+ float newHeight = m_height;
+
+ if (m_aspect.ratio != CAspectRatio::AR_STRETCH && m_frameWidth && m_frameHeight)
+ {
+ // to get the pixel ratio, we must use the SCALED output sizes
+ float pixelRatio = CServiceBroker::GetWinSystem()->GetGfxContext().GetScalingPixelRatio();
+
+ float fSourceFrameRatio = m_frameWidth / m_frameHeight;
+ if (GetOrientation() & 4)
+ fSourceFrameRatio = m_frameHeight / m_frameWidth;
+ float fOutputFrameRatio = fSourceFrameRatio / pixelRatio;
+
+ // maximize the width
+ newHeight = m_width / fOutputFrameRatio;
+
+ if ((m_aspect.ratio == CAspectRatio::AR_SCALE && newHeight < m_height) ||
+ (m_aspect.ratio == CAspectRatio::AR_KEEP && newHeight > m_height))
+ {
+ newHeight = m_height;
+ newWidth = newHeight * fOutputFrameRatio;
+ }
+ if (m_aspect.ratio == CAspectRatio::AR_CENTER)
+ { // keep original size + center
+ newWidth = m_frameWidth / sqrt(pixelRatio);
+ newHeight = m_frameHeight * sqrt(pixelRatio);
+ }
+
+ if (m_aspect.align & ASPECT_ALIGN_LEFT)
+ newPosX = m_posX;
+ else if (m_aspect.align & ASPECT_ALIGN_RIGHT)
+ newPosX = m_posX + m_width - newWidth;
+ else
+ newPosX = m_posX + (m_width - newWidth) * 0.5f;
+ if (m_aspect.align & ASPECT_ALIGNY_TOP)
+ newPosY = m_posY;
+ else if (m_aspect.align & ASPECT_ALIGNY_BOTTOM)
+ newPosY = m_posY + m_height - newHeight;
+ else
+ newPosY = m_posY + (m_height - newHeight) * 0.5f;
+ }
+
+ m_vertex.SetRect(newPosX, newPosY, newPosX + newWidth, newPosY + newHeight);
+
+ // scale the diffuse coords as well
+ if (m_diffuse.size())
+ { // calculate scaling for the texcoords
+ if (m_diffuse.m_texCoordsArePixels)
+ {
+ m_diffuseU = float(m_diffuse.m_width);
+ m_diffuseV = float(m_diffuse.m_height);
+ }
+ else
+ {
+ m_diffuseU = float(m_diffuse.m_width) / float(m_diffuse.m_texWidth);
+ m_diffuseV = float(m_diffuse.m_height) / float(m_diffuse.m_texHeight);
+ }
+
+ if (m_aspect.scaleDiffuse)
+ {
+ m_diffuseScaleU = m_diffuseU;
+ m_diffuseScaleV = m_diffuseV;
+ m_diffuseOffset = CPoint(0,0);
+ }
+ else // stretching diffuse
+ { // scale diffuse up or down to match output rect size, rather than image size
+ //(m_fX, mfY) -> (m_fX + m_fNW, m_fY + m_fNH)
+ //(0,0) -> (m_fU*m_diffuseScaleU, m_fV*m_diffuseScaleV)
+ // x = u/(m_fU*m_diffuseScaleU)*m_fNW + m_fX
+ // -> u = (m_posX - m_fX) * m_fU * m_diffuseScaleU / m_fNW
+ m_diffuseScaleU = m_diffuseU * m_vertex.Width() / m_width;
+ m_diffuseScaleV = m_diffuseV * m_vertex.Height() / m_height;
+ m_diffuseOffset = CPoint((m_vertex.x1 - m_posX) / m_vertex.Width() * m_diffuseScaleU, (m_vertex.y1 - m_posY) / m_vertex.Height() * m_diffuseScaleV);
+ }
+ }
+
+ m_invalid = false;
+ return true;
+}
+
+void CGUITexture::FreeResources(bool immediately /* = false */)
+{
+ if (m_isAllocated == LARGE || m_isAllocated == LARGE_FAILED)
+ CServiceBroker::GetGUI()->GetLargeTextureManager().ReleaseImage(m_info.filename, immediately || (m_isAllocated == LARGE_FAILED));
+ else if (m_isAllocated == NORMAL && m_texture.size())
+ CServiceBroker::GetGUI()->GetTextureManager().ReleaseTexture(m_info.filename, immediately);
+
+ if (m_diffuse.size())
+ CServiceBroker::GetGUI()->GetTextureManager().ReleaseTexture(m_info.diffuse, immediately);
+ m_diffuse.Reset();
+
+ m_texture.Reset();
+
+ ResetAnimState();
+
+ m_texCoordsScaleU = 1.0f;
+ m_texCoordsScaleV = 1.0f;
+
+ // call our implementation
+ Free();
+
+ m_isAllocated = NO;
+}
+
+void CGUITexture::DynamicResourceAlloc(bool allocateDynamically)
+{
+ m_allocateDynamically = allocateDynamically;
+}
+
+void CGUITexture::SetInvalid()
+{
+ m_invalid = true;
+}
+
+bool CGUITexture::UpdateAnimFrame(unsigned int currentTime)
+{
+ bool changed = false;
+ unsigned int delay = m_texture.m_delays[m_currentFrame];
+
+ if (m_lasttime == 0)
+ {
+ m_lasttime = currentTime;
+ }
+ else
+ {
+ if ((currentTime - m_lasttime) >= delay)
+ {
+ if (m_currentFrame + 1 >= m_texture.size())
+ {
+ if (m_texture.m_loops > 0)
+ {
+ if (m_currentLoop + 1 < m_texture.m_loops)
+ {
+ m_currentLoop++;
+ m_currentFrame = 0;
+ m_lasttime = currentTime;
+ changed = true;
+ }
+ }
+ else
+ {
+ // 0 == loop forever
+ m_currentFrame = 0;
+ m_lasttime = currentTime;
+ changed = true;
+ }
+ }
+ else
+ {
+ m_currentFrame++;
+ m_lasttime = currentTime;
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
+}
+
+bool CGUITexture::SetVisible(bool visible)
+{
+ bool changed = m_visible != visible;
+ m_visible = visible;
+ return changed;
+}
+
+bool CGUITexture::SetAlpha(unsigned char alpha)
+{
+ bool changed = m_alpha != alpha;
+ m_alpha = alpha;
+ return changed;
+}
+
+bool CGUITexture::SetDiffuseColor(UTILS::COLOR::Color color,
+ const CGUIListItem* item /* = nullptr */)
+{
+ bool changed = m_diffuseColor != color;
+ m_diffuseColor = color;
+ changed |= m_info.diffuseColor.Update(item);
+ return changed;
+}
+
+bool CGUITexture::ReadyToRender() const
+{
+ return m_texture.size() > 0;
+}
+
+void CGUITexture::OrientateTexture(CRect& rect, float width, float height, int orientation)
+{
+ switch (orientation & 3)
+ {
+ case 0:
+ // default
+ break;
+ case 1:
+ // flip in X direction
+ rect.x1 = width - rect.x1;
+ rect.x2 = width - rect.x2;
+ break;
+ case 2:
+ // rotate 180 degrees
+ rect.x1 = width - rect.x1;
+ rect.x2 = width - rect.x2;
+ rect.y1 = height - rect.y1;
+ rect.y2 = height - rect.y2;
+ break;
+ case 3:
+ // flip in Y direction
+ rect.y1 = height - rect.y1;
+ rect.y2 = height - rect.y2;
+ break;
+ }
+ if (orientation & 4)
+ {
+ // we need to swap x and y coordinates but only within the width,height block
+ float temp = rect.x1;
+ rect.x1 = rect.y1 * width/height;
+ rect.y1 = temp * height/width;
+ temp = rect.x2;
+ rect.x2 = rect.y2 * width/height;
+ rect.y2 = temp * height/width;
+ }
+}
+
+void CGUITexture::ResetAnimState()
+{
+ m_lasttime = 0;
+ m_currentFrame = 0;
+ m_currentLoop = 0;
+}
+
+bool CGUITexture::SetWidth(float width)
+{
+ if (width < m_info.border.x1 + m_info.border.x2)
+ width = m_info.border.x1 + m_info.border.x2;
+ if (m_width != width)
+ {
+ m_width = width;
+ m_invalid = true;
+ return true;
+ }
+ else
+ return false;
+}
+
+bool CGUITexture::SetHeight(float height)
+{
+ if (height < m_info.border.y1 + m_info.border.y2)
+ height = m_info.border.y1 + m_info.border.y2;
+ if (m_height != height)
+ {
+ m_height = height;
+ m_invalid = true;
+ return true;
+ }
+ else
+ return false;
+}
+
+bool CGUITexture::SetPosition(float posX, float posY)
+{
+ if (m_posX != posX || m_posY != posY)
+ {
+ m_posX = posX;
+ m_posY = posY;
+ m_invalid = true;
+ return true;
+ }
+ else
+ return false;
+}
+
+bool CGUITexture::SetAspectRatio(const CAspectRatio& aspect)
+{
+ if (m_aspect != aspect)
+ {
+ m_aspect = aspect;
+ m_invalid = true;
+ return true;
+ }
+ else
+ return false;
+}
+
+bool CGUITexture::SetFileName(const std::string& filename)
+{
+ if (m_info.filename == filename) return false;
+ // Don't completely free resources here - we may be just changing
+ // filenames mid-animation
+ FreeResources();
+ m_info.filename = filename;
+
+ // disable large loader and cache for gifs
+ if (StringUtils::EndsWithNoCase(m_info.filename, ".gif"))
+ {
+ m_info.useLarge = false;
+ SetUseCache(false);
+ }
+
+ // Don't allocate resources here as this is done at render time
+ return true;
+}
+
+void CGUITexture::SetUseCache(const bool useCache)
+{
+ m_use_cache = useCache;
+}
+
+int CGUITexture::GetOrientation() const
+{
+ // multiply our orientations
+ static char orient_table[] = { 0, 1, 2, 3, 4, 5, 6, 7,
+ 1, 0, 3, 2, 5, 4, 7, 6,
+ 2, 3, 0, 1, 6, 7, 4, 5,
+ 3, 2, 1, 0, 7, 6, 5, 4,
+ 4, 7, 6, 5, 0, 3, 2, 1,
+ 5, 6, 7, 4, 1, 2, 3, 0,
+ 6, 5, 4, 7, 2, 1, 0, 3,
+ 7, 4, 5, 6, 3, 0, 1, 2 };
+ return (int)orient_table[8 * m_info.orientation + m_texture.m_orientation];
+}