diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index 368a4c60d..8b60d9f1e 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -339,17 +339,29 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* const bool hasCssHeight = imgStyle.hasImageHeight(); const bool hasCssWidth = imgStyle.hasImageWidth(); + // Compute effective container width for percentage-based image sizes. + // If the image is inside a block with horizontal margins/padding (e.g. + //
), percentage widths like width:100% + // should resolve against the container width, not the full viewport. + int containerWidth = self->viewportWidth; + if (self->currentTextBlock) { + const int inset = self->currentTextBlock->getBlockStyle().totalHorizontalInset(); + if (inset > 0 && inset < self->viewportWidth) { + containerWidth = self->viewportWidth - inset; + } + } + if (hasCssHeight && hasCssWidth && dims.width > 0 && dims.height > 0) { // Both CSS height and width set: resolve both, then clamp to viewport preserving requested ratio displayHeight = static_cast( imgStyle.imageHeight.toPixels(emSize, static_cast(self->viewportHeight)) + 0.5f); displayWidth = static_cast( - imgStyle.imageWidth.toPixels(emSize, static_cast(self->viewportWidth)) + 0.5f); + imgStyle.imageWidth.toPixels(emSize, static_cast(containerWidth)) + 0.5f); if (displayHeight < 1) displayHeight = 1; if (displayWidth < 1) displayWidth = 1; - if (displayWidth > self->viewportWidth || displayHeight > self->viewportHeight) { - float scaleX = (displayWidth > self->viewportWidth) - ? static_cast(self->viewportWidth) / displayWidth + if (displayWidth > containerWidth || displayHeight > self->viewportHeight) { + float scaleX = (displayWidth > containerWidth) + ? static_cast(containerWidth) / displayWidth : 1.0f; float scaleY = (displayHeight > self->viewportHeight) ? static_cast(self->viewportHeight) / displayHeight @@ -375,8 +387,8 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* static_cast(displayHeight * (static_cast(dims.width) / dims.height) + 0.5f); if (displayWidth < 1) displayWidth = 1; } - if (displayWidth > self->viewportWidth) { - displayWidth = self->viewportWidth; + if (displayWidth > containerWidth) { + displayWidth = containerWidth; // Rescale height to preserve aspect ratio when width is clamped displayHeight = static_cast(displayWidth * (static_cast(dims.height) / dims.width) + 0.5f); @@ -385,10 +397,10 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* if (displayWidth < 1) displayWidth = 1; LOG_DBG("EHP", "Display size from CSS height: %dx%d", displayWidth, displayHeight); } else if (hasCssWidth && !hasCssHeight && dims.width > 0 && dims.height > 0) { - // Use CSS width (resolve % against viewport width) and derive height from aspect ratio + // Use CSS width (resolve % against container width) and derive height from aspect ratio displayWidth = static_cast( - imgStyle.imageWidth.toPixels(emSize, static_cast(self->viewportWidth)) + 0.5f); - if (displayWidth > self->viewportWidth) displayWidth = self->viewportWidth; + imgStyle.imageWidth.toPixels(emSize, static_cast(containerWidth)) + 0.5f); + if (displayWidth > containerWidth) displayWidth = containerWidth; if (displayWidth < 1) displayWidth = 1; displayHeight = static_cast(displayWidth * (static_cast(dims.height) / dims.width) + 0.5f); @@ -402,8 +414,8 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* if (displayHeight < 1) displayHeight = 1; LOG_DBG("EHP", "Display size from CSS width: %dx%d", displayWidth, displayHeight); } else { - // Scale to fit viewport while maintaining aspect ratio - int maxWidth = self->viewportWidth; + // Scale to fit container while maintaining aspect ratio + int maxWidth = containerWidth; int maxHeight = self->viewportHeight; float scaleX = (dims.width > maxWidth) ? (float)maxWidth / dims.width : 1.0f; float scaleY = (dims.height > maxHeight) ? (float)maxHeight / dims.height : 1.0f;