Skip to content

Commit

Permalink
Merge pull request RetroPie#412 from Koerty/crop-image-and-minsize
Browse files Browse the repository at this point in the history
Add cropping and minSize to ImageComponent
  • Loading branch information
jrassa authored Apr 13, 2018
2 parents 48187d2 + d23d5db commit c7c828e
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 17 deletions.
2 changes: 1 addition & 1 deletion es-core/src/GuiComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class GuiComponent
void setRotationOrigin(float originX, float originY);
inline void setRotationOrigin(Vector2f origin) { setRotationOrigin(origin.x(), origin.y()); }

Vector2f getSize() const;
virtual Vector2f getSize() const;
inline void setSize(const Vector2f& size) { setSize(size.x(), size.y()); }
void setSize(float w, float h);
virtual void onSizeChanged() {};
Expand Down
105 changes: 93 additions & 12 deletions es-core/src/components/ImageComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ Vector2i ImageComponent::getTextureSize() const
return Vector2i::Zero();
}

Vector2f ImageComponent::getSize() const
{
return GuiComponent::getSize() * (mBottomRightCrop - mTopLeftCrop);
}

ImageComponent::ImageComponent(Window* window, bool forceLoad, bool dynamic) : GuiComponent(window),
mTargetIsMax(false), mFlipX(false), mFlipY(false), mTargetSize(0, 0), mColorShift(0xFFFFFFFF),
mForceLoad(forceLoad), mDynamic(dynamic), mFadeOpacity(0), mFading(false), mRotateByTargetSize(false)
mTargetIsMax(false), mTargetIsMin(false), mFlipX(false), mFlipY(false), mTargetSize(0, 0), mColorShift(0xFFFFFFFF),
mForceLoad(forceLoad), mDynamic(dynamic), mFadeOpacity(0), mFading(false), mRotateByTargetSize(false),
mTopLeftCrop(0.0f, 0.0f), mBottomRightCrop(1.0f, 1.0f)
{
updateColors();
}
Expand Down Expand Up @@ -63,6 +69,31 @@ void ImageComponent::resize()
mSize[1] = Math::round(mSize[1]);
mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x();

}else if(mTargetIsMin)
{
mSize = textureSize;

Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y()));

if(resizeScale.x() > resizeScale.y())
{
mSize[0] *= resizeScale.x();
mSize[1] *= resizeScale.x();

float cropPercent = (mSize.y() - mTargetSize.y()) / (mSize.y() * 2);
crop(0, cropPercent, 0, cropPercent);
}else{
mSize[0] *= resizeScale.y();
mSize[1] *= resizeScale.y();

float cropPercent = (mSize.x() - mTargetSize.x()) / (mSize.x() * 2);
crop(cropPercent, 0, cropPercent, 0);
}

// for SVG rasterization, always calculate width from rounded height (see comment above)
mSize[1] = Math::round(mSize[1]);
mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x();

}else{
// if both components are set, we just stretch
// if no components are set, we don't resize at all
Expand Down Expand Up @@ -132,13 +163,23 @@ void ImageComponent::setResize(float width, float height)
{
mTargetSize = Vector2f(width, height);
mTargetIsMax = false;
mTargetIsMin = false;
resize();
}

void ImageComponent::setMaxSize(float width, float height)
{
mTargetSize = Vector2f(width, height);
mTargetIsMax = true;
mTargetIsMin = false;
resize();
}

void ImageComponent::setMinSize(float width, float height)
{
mTargetSize = Vector2f(width, height);
mTargetIsMax = false;
mTargetIsMin = true;
resize();
}

Expand All @@ -152,6 +193,43 @@ void ImageComponent::setRotateByTargetSize(bool rotate)
mRotateByTargetSize = rotate;
}

void ImageComponent::cropLeft(float percent)
{
assert(percent >= 0.0f && percent <= 1.0f);
mTopLeftCrop.x() = percent;
}

void ImageComponent::cropTop(float percent)
{
assert(percent >= 0.0f && percent <= 1.0f);
mTopLeftCrop.y() = percent;
}

void ImageComponent::cropRight(float percent)
{
assert(percent >= 0.0f && percent <= 1.0f);
mBottomRightCrop.x() = 1.0f - percent;
}

void ImageComponent::cropBot(float percent)
{
assert(percent >= 0.0f && percent <= 1.0f);
mBottomRightCrop.y() = 1.0f - percent;
}

void ImageComponent::crop(float left, float top, float right, float bot)
{
cropLeft(left);
cropTop(top);
cropRight(right);
cropBot(bot);
}

void ImageComponent::uncrop()
{
crop(0, 0, 0, 0);
}

void ImageComponent::setFlipX(bool flip)
{
mFlipX = flip;
Expand Down Expand Up @@ -187,8 +265,9 @@ void ImageComponent::updateVertices()

// we go through this mess to make sure everything is properly rounded
// if we just round vertices at the end, edge cases occur near sizes of 0.5
Vector2f topLeft(0.0, 0.0);
Vector2f bottomRight(Math::round(mSize.x()), Math::round(mSize.y()));
Vector2f size(Math::round(mSize.x()), Math::round(mSize.y()));
Vector2f topLeft(size * mTopLeftCrop);
Vector2f bottomRight(size * mBottomRightCrop);

mVertices[0].pos = Vector2f(topLeft.x(), topLeft.y());
mVertices[1].pos = Vector2f(topLeft.x(), bottomRight.y());
Expand All @@ -208,23 +287,23 @@ void ImageComponent::updateVertices()
py = 1;
}

mVertices[0].tex = Vector2f(0, py);
mVertices[1].tex = Vector2f(0, 0);
mVertices[2].tex = Vector2f(px, py);
mVertices[0].tex = Vector2f(mTopLeftCrop.x(), py - mTopLeftCrop.y());
mVertices[1].tex = Vector2f(mTopLeftCrop.x(), 1 - mBottomRightCrop.y());
mVertices[2].tex = Vector2f(px * mBottomRightCrop.x(), py - mTopLeftCrop.y());

mVertices[3].tex = Vector2f(px, py);
mVertices[4].tex = Vector2f(0, 0);
mVertices[5].tex = Vector2f(px, 0);
mVertices[3].tex = Vector2f(px * mBottomRightCrop.x(), py - mTopLeftCrop.y());
mVertices[4].tex = Vector2f(mTopLeftCrop.x(), 1 - mBottomRightCrop.y());
mVertices[5].tex = Vector2f(px * mBottomRightCrop.x(), 1 - mBottomRightCrop.y());

if(mFlipX)
{
for(int i = 0; i < 6; i++)
mVertices[i].tex[0] = mVertices[i].tex[0] == px ? 0 : px;
mVertices[i].tex[0] = px - mVertices[i].tex[0];
}
if(mFlipY)
{
for(int i = 0; i < 6; i++)
mVertices[i].tex[1] = mVertices[i].tex[1] == py ? 0 : py;
mVertices[i].tex[1] = py - mVertices[i].tex[1];
}
}

Expand Down Expand Up @@ -352,6 +431,8 @@ void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
setResize(elem->get<Vector2f>("size") * scale);
else if(elem->has("maxSize"))
setMaxSize(elem->get<Vector2f>("maxSize") * scale);
else if(elem->has("minSize"))
setMinSize(elem->get<Vector2f>("minSize") * scale);
}

// position + size also implies origin
Expand Down
25 changes: 21 additions & 4 deletions es-core/src/components/ImageComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,20 @@ class ImageComponent : public GuiComponent
void setMaxSize(float width, float height);
inline void setMaxSize(const Vector2f& size) { setMaxSize(size.x(), size.y()); }

void setMinSize(float width, float height);
inline void setMinSize(const Vector2f& size) { setMinSize(size.x(), size.y()); }

Vector2f getRotationSize() const override;

// Applied AFTER image positioning and sizing
// cropTop(0.2) will crop 20% of the top of the image.
void cropLeft(float percent);
void cropTop(float percent);
void cropRight(float percent);
void cropBot(float percent);
void crop(float left, float top, float right, float bot);
void uncrop();

// Multiply all pixels in the image by this color when rendering.
void setColorShift(unsigned int color);

Expand All @@ -53,6 +65,8 @@ class ImageComponent : public GuiComponent
// Returns the size of the current texture, or (0, 0) if none is loaded. May be different than drawn size (use getSize() for that).
Vector2i getTextureSize() const;

Vector2f getSize() const override;

bool hasImage();

void render(const Transform4x4f& parentTrans) override;
Expand All @@ -63,7 +77,7 @@ class ImageComponent : public GuiComponent
private:
Vector2f mTargetSize;

bool mFlipX, mFlipY, mTargetIsMax;
bool mFlipX, mFlipY, mTargetIsMax, mTargetIsMin;

// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
// Used internally whenever the resizing parameters or texture change.
Expand All @@ -86,11 +100,14 @@ class ImageComponent : public GuiComponent
std::string mDefaultPath;

std::shared_ptr<TextureResource> mTexture;
unsigned char mFadeOpacity;
bool mFading;
bool mForceLoad;
unsigned char mFadeOpacity;
bool mFading;
bool mForceLoad;
bool mDynamic;
bool mRotateByTargetSize;

Vector2f mTopLeftCrop;
Vector2f mBottomRightCrop;
};

#endif // ES_CORE_COMPONENTS_IMAGE_COMPONENT_H

0 comments on commit c7c828e

Please sign in to comment.