From 1e7ced2c6656ee749989114c4d17bf8133ddbcee Mon Sep 17 00:00:00 2001 From: Aloshi Date: Fri, 23 May 2014 16:51:56 -0500 Subject: [PATCH] Two fixes with SVG rasterizing: 1. Original width/height were being returned as integers, even though they can be floats (see SVGResource::getImageSize()). Function also renamed to be more descriptive (renamed to getSourceImageSize()). 2. Now we always round height and scale width from the rounded height when doing scaling, since SVG rasterization scale is determined from height. This seems to fix some 1px cutoff I was seeing, but I'm not sure if it still works for images with extreme aspect ratios that are taller rather than wider. --- src/components/ImageComponent.cpp | 25 +++++++++++++++++++------ src/resources/SVGResource.cpp | 10 +++++++--- src/resources/SVGResource.h | 2 +- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/components/ImageComponent.cpp b/src/components/ImageComponent.cpp index 5f33cd718..9da04aab7 100644 --- a/src/components/ImageComponent.cpp +++ b/src/components/ImageComponent.cpp @@ -37,12 +37,20 @@ void ImageComponent::resize() if(!mTexture) return; - const Eigen::Vector2f textureSize((float)getTextureSize().x(), (float)getTextureSize().y()); + SVGResource* svg = dynamic_cast(mTexture.get()); + + const Eigen::Vector2f textureSize = svg ? svg->getSourceImageSize() : Eigen::Vector2f((float)mTexture->getSize().x(), (float)mTexture->getSize().y()); if(mTexture->isTiled()) { mSize = mTargetSize; }else{ + // 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; @@ -58,27 +66,32 @@ void ImageComponent::resize() 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[0] = (mTargetSize.y() / textureSize.y()) * textureSize.x(); - mSize[1] = mTargetSize.y(); + mSize[1] = round(mTargetSize.y()); + mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x(); }else if(mTargetSize.x() && !mTargetSize.y()) { - mSize[0] = mTargetSize.x(); - mSize[1] = (mTargetSize.x() / textureSize.x()) * textureSize.y(); + mSize[1] = round((mTargetSize.x() / textureSize.x()) * textureSize.y()); + mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x(); } } } - SVGResource* svg = dynamic_cast(mTexture.get()); if(svg) { + // mSize.y() should already be rounded svg->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y())); } diff --git a/src/resources/SVGResource.cpp b/src/resources/SVGResource.cpp index 6dc773a47..1051303f4 100644 --- a/src/resources/SVGResource.cpp +++ b/src/resources/SVGResource.cpp @@ -69,6 +69,10 @@ void SVGResource::rasterizeAt(size_t width, size_t height) mLastHeight = height; } + LOG(LogInfo) << "Rasterizing \"" << mPath << "\"..."; + LOG(LogInfo) << " Original width: " << mSVGImage->width << ", original height: " << mSVGImage->height; + LOG(LogInfo) << " width: " << width << ", height: " << height << ", scale: " << height / mSVGImage->height; + unsigned char* imagePx = (unsigned char*)malloc(width * height * 4); NSVGrasterizer* rast = nsvgCreateRasterizer(); @@ -92,12 +96,12 @@ void SVGResource::rasterizeAt(size_t width, size_t height) free(imagePx); } -Eigen::Vector2i SVGResource::getImageSize() const +Eigen::Vector2f SVGResource::getSourceImageSize() const { if(mSVGImage) - return Eigen::Vector2i((int)round(mSVGImage->width), (int)round(mSVGImage->height)); + return Eigen::Vector2f(mSVGImage->width, mSVGImage->height); - return Eigen::Vector2i::Zero(); + return Eigen::Vector2f::Zero(); } void SVGResource::deinitSVG() diff --git a/src/resources/SVGResource.h b/src/resources/SVGResource.h index c28b29396..c68ae4879 100644 --- a/src/resources/SVGResource.h +++ b/src/resources/SVGResource.h @@ -14,7 +14,7 @@ public: virtual void initFromMemory(const char* image, size_t length) override; void rasterizeAt(size_t width, size_t height); - Eigen::Vector2i getImageSize() const; + Eigen::Vector2f getSourceImageSize() const; protected: friend TextureResource;