mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 23:55:38 +00:00
Added cover fit cropping support to ImageComponent.
This commit is contained in:
parent
f0e3addee6
commit
c6981084e0
|
@ -22,6 +22,7 @@ ImageComponent::ImageComponent(bool forceLoad, bool dynamic)
|
|||
, mFlipX {false}
|
||||
, mFlipY {false}
|
||||
, mTargetIsMax {false}
|
||||
, mTargetIsCrop {false}
|
||||
, mTileWidth {0.0f}
|
||||
, mTileHeight {0.0f}
|
||||
, mColorShift {0xFFFFFFFF}
|
||||
|
@ -93,6 +94,8 @@ void ImageComponent::setImage(const std::string& path, bool tile)
|
|||
mMipmapping, static_cast<size_t>(mSize.x),
|
||||
static_cast<size_t>(mSize.y), mTileWidth, mTileHeight);
|
||||
mTexture->rasterizeAt(mSize.x, mSize.y);
|
||||
if (mTargetIsCrop)
|
||||
coverFitCrop();
|
||||
onSizeChanged();
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +130,7 @@ void ImageComponent::setResize(const float width, const float height)
|
|||
{
|
||||
mTargetSize = glm::vec2 {width, height};
|
||||
mTargetIsMax = false;
|
||||
mTargetIsCrop = false;
|
||||
resize();
|
||||
}
|
||||
|
||||
|
@ -134,6 +138,7 @@ void ImageComponent::setResize(const glm::vec2& size, bool rasterize)
|
|||
{
|
||||
mTargetSize = size;
|
||||
mTargetIsMax = false;
|
||||
mTargetIsCrop = false;
|
||||
resize(rasterize);
|
||||
}
|
||||
|
||||
|
@ -141,39 +146,48 @@ void ImageComponent::setMaxSize(const float width, const float height)
|
|||
{
|
||||
mTargetSize = glm::vec2 {width, height};
|
||||
mTargetIsMax = true;
|
||||
mTargetIsCrop = false;
|
||||
resize();
|
||||
}
|
||||
|
||||
void ImageComponent::cropLeft(const float percent)
|
||||
void ImageComponent::setCroppedSize(const glm::vec2& size)
|
||||
{
|
||||
assert(percent >= 0.0f && percent <= 1.0f);
|
||||
mTopLeftCrop.x = percent;
|
||||
mTargetSize = size;
|
||||
mTargetIsMax = false;
|
||||
mTargetIsCrop = true;
|
||||
resize();
|
||||
}
|
||||
|
||||
void ImageComponent::cropTop(const float percent)
|
||||
void ImageComponent::cropLeft(const float value)
|
||||
{
|
||||
assert(percent >= 0.0f && percent <= 1.0f);
|
||||
mTopLeftCrop.y = percent;
|
||||
assert(value >= 0.0f && value <= 1.0f);
|
||||
mTopLeftCrop.x = value;
|
||||
}
|
||||
|
||||
void ImageComponent::cropRight(const float percent)
|
||||
void ImageComponent::cropTop(const float value)
|
||||
{
|
||||
assert(percent >= 0.0f && percent <= 1.0f);
|
||||
mBottomRightCrop.x = 1.0f - percent;
|
||||
assert(value >= 0.0f && value <= 1.0f);
|
||||
mTopLeftCrop.y = value;
|
||||
}
|
||||
|
||||
void ImageComponent::cropBot(const float percent)
|
||||
void ImageComponent::cropRight(const float value)
|
||||
{
|
||||
assert(percent >= 0.0f && percent <= 1.0f);
|
||||
mBottomRightCrop.y = 1.0f - percent;
|
||||
assert(value >= 0.0f && value <= 1.0f);
|
||||
mBottomRightCrop.x = 1.0f - value;
|
||||
}
|
||||
|
||||
void ImageComponent::crop(const float left, const float top, const float right, const float bot)
|
||||
void ImageComponent::cropBottom(const float value)
|
||||
{
|
||||
assert(value >= 0.0f && value <= 1.0f);
|
||||
mBottomRightCrop.y = 1.0f - value;
|
||||
}
|
||||
|
||||
void ImageComponent::crop(const float left, const float top, const float right, const float bottom)
|
||||
{
|
||||
cropLeft(left);
|
||||
cropTop(top);
|
||||
cropRight(right);
|
||||
cropBot(bot);
|
||||
cropBottom(bottom);
|
||||
}
|
||||
|
||||
void ImageComponent::uncrop()
|
||||
|
@ -182,6 +196,24 @@ void ImageComponent::uncrop()
|
|||
crop(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void ImageComponent::coverFitCrop()
|
||||
{
|
||||
assert(mTargetIsCrop);
|
||||
|
||||
if (std::round(mSize.y) > std::round(mTargetSize.y)) {
|
||||
const float cropSize {1.0f - (mTargetSize.y / mSize.y)};
|
||||
cropTop(cropSize / 2.0f);
|
||||
cropBottom(cropSize / 2.0f);
|
||||
mSize.y = mSize.y - (mSize.y * cropSize);
|
||||
}
|
||||
else {
|
||||
const float cropSize {1.0f - (mTargetSize.x / mSize.x)};
|
||||
cropLeft(cropSize / 2.0f);
|
||||
cropRight(cropSize / 2.0f);
|
||||
mSize.x = mSize.x - (mSize.x * cropSize);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageComponent::cropTransparentPadding(const float maxSizeX, const float maxSizeY)
|
||||
{
|
||||
if (mSize == glm::vec2 {0.0f, 0.0f})
|
||||
|
@ -562,7 +594,7 @@ void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
|||
if (elem->has("colorEnd"))
|
||||
setColorShiftEnd(elem->get<unsigned int>("colorEnd"));
|
||||
if (elem->has("gradientType")) {
|
||||
const std::string gradientType {elem->get<std::string>("gradientType")};
|
||||
const std::string& gradientType {elem->get<std::string>("gradientType")};
|
||||
if (gradientType == "horizontal") {
|
||||
setColorGradientHorizontal(true);
|
||||
}
|
||||
|
@ -617,6 +649,12 @@ void ImageComponent::resize(bool rasterize)
|
|||
mSize.x = std::min((mSize.y / textureSize.y) * textureSize.x, mTargetSize.x);
|
||||
}
|
||||
}
|
||||
else if (mTargetIsCrop) {
|
||||
// Size texture to allow for cropped image to fill the entire area.
|
||||
const float cropFactor {
|
||||
std::max(mTargetSize.x / textureSize.x, mTargetSize.y / textureSize.y)};
|
||||
mSize = textureSize * cropFactor;
|
||||
}
|
||||
else {
|
||||
// If both axes are set we just stretch or squash, if no axes are set we do nothing.
|
||||
mSize = mTargetSize == glm::vec2 {0.0f, 0.0f} ? textureSize : mTargetSize;
|
||||
|
@ -640,6 +678,8 @@ void ImageComponent::resize(bool rasterize)
|
|||
|
||||
if (rasterize) {
|
||||
mTexture->rasterizeAt(mSize.x, mSize.y);
|
||||
if (mTargetIsCrop)
|
||||
coverFitCrop();
|
||||
onSizeChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ public:
|
|||
void setMaxSize(const float width, const float height);
|
||||
void setMaxSize(const glm::vec2& size) { setMaxSize(size.x, size.y); }
|
||||
|
||||
// Resize and crop image so it fills the entire area defined by the size parameter.
|
||||
void setCroppedSize(const glm::vec2& size);
|
||||
|
||||
void setTileSize(const float width, const float height)
|
||||
{
|
||||
mTileWidth = width;
|
||||
|
@ -55,14 +58,16 @@ public:
|
|||
|
||||
glm::vec2 getRotationSize() const override { return mRotateByTargetSize ? mTargetSize : mSize; }
|
||||
|
||||
// Applied AFTER image positioning and sizing.
|
||||
// cropTop(0.2) will crop 20% of the top of the image.
|
||||
void cropLeft(const float percent);
|
||||
void cropTop(const float percent);
|
||||
void cropRight(const float percent);
|
||||
void cropBot(const float percent);
|
||||
void crop(const float left, const float top, const float right, const float bot);
|
||||
// Applied after image positioning and sizing.
|
||||
void cropLeft(const float value);
|
||||
void cropTop(const float value);
|
||||
void cropRight(const float value);
|
||||
void cropBottom(const float value);
|
||||
void crop(const float left, const float top, const float right, const float bottom);
|
||||
void uncrop();
|
||||
// This essentially implements CSS "object-fit: cover" and has nothing to do with the
|
||||
// cover image type (as the name may seem to imply).
|
||||
void coverFitCrop();
|
||||
|
||||
// This crops any entirely transparent areas around the actual image.
|
||||
// The arguments restrict how much the end result is allowed to be scaled.
|
||||
|
@ -115,6 +120,7 @@ private:
|
|||
bool mFlipX;
|
||||
bool mFlipY;
|
||||
bool mTargetIsMax;
|
||||
bool mTargetIsCrop;
|
||||
|
||||
float mTileWidth;
|
||||
float mTileHeight;
|
||||
|
|
Loading…
Reference in a new issue