Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

max-width / max-height not redering correctly in pdf when height / width set in tag #417

Closed
swarl opened this issue Nov 22, 2019 · 2 comments

Comments

@swarl
Copy link

swarl commented Nov 22, 2019

Version: 1.0.1

When in a html image tag the properties height and width are specified and css styles max-width (and max-height) is added, then the image is not rendered correctly in the pdf.

Reproduce with:

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.LinkedHashMap;

import org.apache.commons.io.FileUtils;
import org.junit.Test;

import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
[...]
   @Test
   public void shouldAnswerWithTrue() throws URISyntaxException, IOException {

      String htmlContent = "<html>\n"
         + "<head>\n"
         + "    <style>\n"
         + "        img {\n"
         + "            max-height: 885px;\n"
         + "            max-width: 690px;\n"
         + "        }\n"
         + "    </style>\n"
         + "</head>\n"
         + "<body>\n"
         + "<div class=\"content\">\n"
         + "    <div>"
         + "        <p><span><span>Inline image:</span></span></p>\n"
         + "        <img height=\"310\" src=\"file:_2019-11-22_11-34-28.png\" width=\"700\"/>\n"
         //         + "        <img height=\"3301\" src=\"file:_2019-11-22_11-34-28.png\" width=\"1462\"/>\n"
         + "    </div>\n"
         + "</div>\n"
         + "</body>\n"
         + "</html>";

      try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
         PdfRendererBuilder builder = new PdfRendererBuilder();
         builder.usePdfAConformance(PdfRendererBuilder.PdfAConformance.PDFA_2_A);

         builder
            .withHtmlContent(htmlContent, "./")
            .useFastMode()
            .toStream(outputStream).run();
         FileUtils.writeByteArrayToFile(new File("test.pdf"), outputStream.toByteArray());
      } catch (Exception e) {
         throw new IllegalStateException(e.getMessage(), e);
      }
   }

_2019-11-22_11-34-28
test.pdf

@swarl
Copy link
Author

swarl commented Jan 12, 2020

To repoduce: https://github.com/swarl/html2pdf.git
Problem seem to be in BlockBox.sizeReplacedElement :

        boolean haveExactDims = cssWidth >= 0 && cssHeight >= 0;
        
        int intrinsicWidth = re.getIntrinsicWidth();
        int intrinsicHeight = re.getIntrinsicHeight();
        
        cssWidth = !getStyle().isMaxWidthNone() && 
                (intrinsicWidth > getCSSMaxWidth(c) || cssWidth > getCSSMaxWidth(c)) ? 
                          getCSSMaxWidth(c) : cssWidth;
        [...]
        
        cssHeight = !getStyle().isMaxHeightNone() &&
                (intrinsicHeight > getCSSMaxHeight(c) || cssHeight > getCSSMaxHeight(c)) ?
                          getCSSMaxHeight(c) : cssHeight;
        [...]

        int nw;
        int nh;
        
        if (cssWidth > 0 && cssHeight > 0) {
            if (haveExactDims) {
                // We only warp the aspect ratio if we have explicit width and height values.
                nw = cssWidth;
                nh = cssHeight;
            } [...]
       }

Here max-width and max-height are applied without any conversion. So this only would work if both values are in the same aspect ratio as the picture...

@swarl
Copy link
Author

swarl commented Jan 13, 2020

This would need to be something like this:

        boolean maxWidthApplied = false;
        if (!getStyle().isMaxWidthNone() &&
                (intrinsicWidth > getCSSMaxWidth(c) || cssWidth > getCSSMaxWidth(c))) {
            maxWidthApplied = true;
            cssWidth = getCSSMaxWidth(c);
            cssHeight = (int) ((double) intrinsicHeight / ((double) intrinsicWidth / (double) getCSSMaxWidth(c)));
        }

        cssWidth = cssWidth >= 0 && getCSSMinWidth(c) > 0 && cssWidth < getCSSMinWidth(c) ?
                getCSSMinWidth(c) : cssWidth;

        if (!getStyle().isMaxHeightNone() &&
                (intrinsicHeight > getCSSMaxHeight(c) && !maxWidthApplied || cssHeight > getCSSMaxHeight(c))) {
            cssWidth = (int) ((double) cssWidth / ((double) cssHeight / (double) getCSSMaxHeight(c)));
            cssHeight = getCSSMaxHeight(c);
        }

        cssHeight = cssHeight >= 0 && getCSSMinHeight(c) > 0 && cssHeight < getCSSMinHeight(c) ?
                getCSSMinHeight(c) : cssHeight;

danfickle added a commit that referenced this issue Jan 14, 2020
This differs from browsers which will warp the aspect ratio in such circumstances (tested with Chrome/Safari). However, nearly all uses need the aspect ratio preserved. We can revisit this if we implement the object-fit property.

Thanks a lot to @swarl who provided code which inspired the test and fix for this issue, as well as reporting the problem.
@swarl swarl closed this as completed Jan 15, 2020
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant