implement maxSize for videos

implement maxSize for videos
This commit is contained in:
jrassa 2017-02-23 20:42:35 -05:00
parent e95eb4eea6
commit 44f886c961
3 changed files with 108 additions and 10 deletions

View file

@ -86,6 +86,7 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
("video", makeMap(boost::assign::map_list_of
("pos", NORMALIZED_PAIR)
("size", NORMALIZED_PAIR)
("maxSize", NORMALIZED_PAIR)
("origin", NORMALIZED_PAIR)
("default", PATH)
("delay", FLOAT)

View file

@ -39,7 +39,10 @@ VideoComponent::VideoComponent(Window* window) :
mVideoWidth(0),
mStartDelayed(false),
mIsPlaying(false),
mShowing(false)
mShowing(false),
mTargetIsMax(false),
mOrigin(0, 0),
mTargetSize(0, 0)
{
memset(&mContext, 0, sizeof(mContext));
@ -69,12 +72,89 @@ void VideoComponent::setOrigin(float originX, float originY)
mStaticImage.setOrigin(originX, originY);
}
void VideoComponent::setResize(float width, float height)
{
mTargetSize << width, height;
mTargetIsMax = false;
mStaticImage.setResize(width, height);
resize();
}
void VideoComponent::setMaxSize(float width, float height)
{
mTargetSize << width, height;
mTargetIsMax = true;
mStaticImage.setMaxSize(width, height);
resize();
}
Eigen::Vector2f VideoComponent::getCenter() const
{
return Eigen::Vector2f(mPosition.x() - (getSize().x() * mOrigin.x()) + getSize().x() / 2,
mPosition.y() - (getSize().y() * mOrigin.y()) + getSize().y() / 2);
}
void VideoComponent::resize()
{
if(!mTexture)
return;
const Eigen::Vector2f textureSize(mVideoWidth, mVideoHeight);
if(textureSize.isZero())
return;
// SVG rasterization is determined by height (see SVGResource.cpp), and rasterization is done in terms of pixels
// if rounding is off enough in the rasterization step (for images with extreme aspect ratios), it can cause cutoff when the aspect ratio breaks
// so, we always make sure the resultant height is an integer to make sure cutoff doesn't happen, and scale width from that
// (you'll see this scattered throughout the function)
// this is probably not the best way, so if you're familiar with this problem and have a better solution, please make a pull request!
if(mTargetIsMax)
{
mSize = textureSize;
Eigen::Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y()));
if(resizeScale.x() < resizeScale.y())
{
mSize[0] *= resizeScale.x();
mSize[1] *= resizeScale.x();
}else{
mSize[0] *= resizeScale.y();
mSize[1] *= resizeScale.y();
}
// for SVG rasterization, always calculate width from rounded height (see comment above)
mSize[1] = 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
mSize = mTargetSize.isZero() ? textureSize : mTargetSize;
// if only one component is set, we resize in a way that maintains aspect ratio
// for SVG rasterization, we always calculate width from rounded height (see comment above)
if(!mTargetSize.x() && mTargetSize.y())
{
mSize[1] = round(mTargetSize.y());
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
}else if(mTargetSize.x() && !mTargetSize.y())
{
mSize[1] = round((mTargetSize.x() / textureSize.x()) * textureSize.y());
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
}
}
// mSize.y() should already be rounded
mTexture->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y()));
onSizeChanged();
}
void VideoComponent::onSizeChanged()
{
// Update the embeded static image
@ -111,8 +191,6 @@ void VideoComponent::setImage(std::string path)
return;
mStaticImage.setImage(path);
// Make the image stretch to fill the video region
mStaticImage.setSize(getSize());
mFadeIn = 0.0f;
mStaticImagePath = path;
}
@ -243,11 +321,15 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
{
Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
mStaticImage.setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
}
if ((properties & ThemeFlags::SIZE) && elem->has("size"))
if(properties & ThemeFlags::SIZE)
{
setSize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale));
if(elem->has("size"))
setResize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale));
else if(elem->has("maxSize"))
setMaxSize(elem->get<Eigen::Vector2f>("maxSize").cwiseProduct(scale));
}
// position + size also implies origin
@ -265,11 +347,6 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
if (elem->has("showSnapshotDelay"))
mConfig.showSnapshotDelay = elem->get<bool>("showSnapshotDelay");
// Update the embeded static image
mStaticImage.setPosition(getPosition());
mStaticImage.setMaxSize(getSize());
mStaticImage.setSize(getSize());
}
std::vector<HelpPrompt> VideoComponent::getHelpPrompts()
@ -287,6 +364,7 @@ void VideoComponent::setupContext()
mContext.surface = SDL_CreateRGBSurface(SDL_SWSURFACE, (int)mVideoWidth, (int)mVideoHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
mContext.mutex = SDL_CreateMutex();
mContext.valid = true;
resize();
}
}

View file

@ -55,6 +55,19 @@ public:
void onSizeChanged() override;
void setOpacity(unsigned char opacity) override;
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
// Can be set before or after a video is loaded.
// setMaxSize() and setResize() are mutually exclusive.
void setResize(float width, float height);
inline void setResize(const Eigen::Vector2f& size) { setResize(size.x(), size.y()); }
// Resize the video to be as large as possible but fit within a box of this size.
// Can be set before or after a video is loaded.
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
void setMaxSize(float width, float height);
inline void setMaxSize(const Eigen::Vector2f& size) { setMaxSize(size.x(), size.y()); }
void render(const Eigen::Affine3f& parentTrans) override;
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
@ -67,6 +80,10 @@ public:
virtual void update(int deltaTime);
private:
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
// Used internally whenever the resizing parameters or texture change.
void resize();
// Start the video Immediately
void startVideo();
// Start the video after any configured delay
@ -94,6 +111,7 @@ private:
unsigned mVideoWidth;
unsigned mVideoHeight;
Eigen::Vector2f mOrigin;
Eigen::Vector2f mTargetSize;
std::shared_ptr<TextureResource> mTexture;
float mFadeIn;
std::string mStaticImagePath;
@ -105,6 +123,7 @@ private:
unsigned mStartTime;
bool mIsPlaying;
bool mShowing;
bool mTargetIsMax;
Configuration mConfig;
};