diff --git a/es-core/src/components/ImageComponent.cpp b/es-core/src/components/ImageComponent.cpp index 0743005a0..6da5f3d1a 100644 --- a/es-core/src/components/ImageComponent.cpp +++ b/es-core/src/components/ImageComponent.cpp @@ -63,11 +63,8 @@ void ImageComponent::resize() else { // SVG rasterization is determined by height 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). - // It's important to use floorf rather than round for this, as we never want to round up - // since that can lead to the cutoff just described. + // ratios), it can cause cutoff when the aspect ratio breaks. So we always make sure to + // round accordingly to avoid such issues. if (mTargetIsMax) { mSize = textureSize; @@ -77,13 +74,11 @@ void ImageComponent::resize() // This will be mTargetSize.x. We can't exceed it, nor be lower than it. mSize.x *= resizeScale.x; // We need to make sure we're not creating an image larger than max size. - mSize.y = std::min(floorf(mSize.y * resizeScale.x), mTargetSize.y); + mSize.y = floorf(std::min(mSize.y * resizeScale.x, mTargetSize.y)); } else { // This will be mTargetSize.y(). We can't exceed it. - mSize.y = floorf(mSize.y * resizeScale.y); - // For SVG rasterization, always calculate width from rounded height (see comment - // above). We need to make sure we're not creating an image larger than max size. + mSize.y *= resizeScale.y; mSize.x = std::min((mSize.y / textureSize.y) * textureSize.x, mTargetSize.x); } } @@ -106,9 +101,7 @@ void ImageComponent::resize() float cropPercent = (mSize.x - mTargetSize.x) / (mSize.x * 2.0f); crop(cropPercent, 0.0f, cropPercent, 0.0f); } - // For SVG rasterization, always calculate width from rounded height (see comment - // above). We need to make sure we're not creating an image smaller than min size. - mSize.y = std::max(floorf(mSize.y), mTargetSize.y); + mSize.y = std::max(mSize.y, mTargetSize.y); mSize.x = std::max((mSize.y / textureSize.y) * textureSize.x, mTargetSize.x); } else { @@ -117,23 +110,24 @@ void ImageComponent::resize() mSize = mTargetSize == glm::vec2{} ? 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.y = floorf(mTargetSize.y); + mSize.y = mTargetSize.y; mSize.x = (mSize.y / textureSize.y) * textureSize.x; } else if (mTargetSize.x && !mTargetSize.y) { - mSize.y = floorf((mTargetSize.x / textureSize.x) * textureSize.y); + mSize.y = (mTargetSize.x / textureSize.x) * textureSize.y; mSize.x = (mSize.y / textureSize.y) * textureSize.x; } } } - mSize.x = ceilf(mSize.x); - mSize.y = ceilf(mSize.y); + // Make sure sub-pixel values are not rounded to zero. + if (mSize.x < 1.0f) + mSize.x = ceilf(mSize.x); + if (mSize.y < 1.0f) + mSize.y = ceilf(mSize.y); - mTexture->rasterizeAt(static_cast(mSize.x), static_cast(mSize.y)); + mTexture->rasterizeAt(mSize.x, mSize.y); onSizeChanged(); } diff --git a/es-core/src/resources/TextureData.cpp b/es-core/src/resources/TextureData.cpp index 70375c5b3..8e1eba5c5 100644 --- a/es-core/src/resources/TextureData.cpp +++ b/es-core/src/resources/TextureData.cpp @@ -73,8 +73,8 @@ bool TextureData::initSVGFromMemory(const std::string& fileData) mSourceHeight = svgImage->height; } - mWidth = static_cast(floorf(floorf(mSourceWidth) * mScaleDuringLoad)); - mHeight = static_cast(floorf(floorf(mSourceHeight) * mScaleDuringLoad)); + mWidth = static_cast(std::round(mSourceWidth * mScaleDuringLoad)); + mHeight = static_cast(std::round(mSourceHeight * mScaleDuringLoad)); if (mWidth == 0) { // Auto scale width to keep aspect ratio. @@ -92,9 +92,8 @@ bool TextureData::initSVGFromMemory(const std::string& fileData) NSVGrasterizer* rast = nsvgCreateRasterizer(); - nsvgRasterize(rast, svgImage, 0, 0, mHeight / svgImage->height, tempVector.data(), - static_cast(mWidth), static_cast(mHeight), - static_cast(mWidth) * 4); + nsvgRasterize(rast, svgImage, 0, 0, mHeight / svgImage->height, tempVector.data(), mWidth, + mHeight, mWidth * 4); // This is important in order to avoid memory leaks. nsvgDeleteRasterizer(rast); diff --git a/es-core/src/resources/TextureData.h b/es-core/src/resources/TextureData.h index c50cd19d3..0e76d8159 100644 --- a/es-core/src/resources/TextureData.h +++ b/es-core/src/resources/TextureData.h @@ -72,8 +72,8 @@ private: std::string mPath; unsigned int mTextureID; std::vector mDataRGBA; - size_t mWidth; - size_t mHeight; + int mWidth; + int mHeight; float mSourceWidth; float mSourceHeight; float mScaleDuringLoad; diff --git a/es-core/src/resources/TextureResource.cpp b/es-core/src/resources/TextureResource.cpp index 74e5d5bfe..b6f7b8d8a 100644 --- a/es-core/src/resources/TextureResource.cpp +++ b/es-core/src/resources/TextureResource.cpp @@ -194,7 +194,7 @@ std::shared_ptr TextureResource::get(const std::string& path, return tex; } -void TextureResource::rasterizeAt(size_t width, size_t height) +void TextureResource::rasterizeAt(float width, float height) { if (mTextureData != nullptr) { glm::vec2 textureSize = mTextureData.get()->getSize(); diff --git a/es-core/src/resources/TextureResource.h b/es-core/src/resources/TextureResource.h index 223d60fcc..91ba5ef7e 100644 --- a/es-core/src/resources/TextureResource.h +++ b/es-core/src/resources/TextureResource.h @@ -44,7 +44,7 @@ public: // It does unload and re-rasterize the texture though which may cause flickering in some // situations. An alternative is to set a scaling factor directly when loading the texture // using get(), by using the scaleDuringLoad parameter (which also works for raster graphics). - void rasterizeAt(size_t width, size_t height); + void rasterizeAt(float width, float height); glm::vec2 getSourceImageSize() const { return mSourceSize; } virtual ~TextureResource();