Skip to content

Commit

Permalink
#344 - Pixel perfect sizing for PDF pages embedded from img tag.
Browse files Browse the repository at this point in the history
Turns out the problem was prematurely casting our width and height to ints and thus getting incorrect scale factors. Test now passing.
  • Loading branch information
danfickle committed Jul 16, 2019
1 parent 0887f7f commit f3f5c81
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ public class ReplacedElementScaleHelper {
* @return AffineTransform or null if not available.
*/
public static AffineTransform createScaleTransform(double dotsPerPixel, Rectangle contentBounds, float width, float height) {
int intrinsicWidth = (int) width;
int intrinsicHeight = (int) height;
double intrinsicWidth = width;
double intrinsicHeight = height;

int desiredWidth = (int) (contentBounds.getWidth() / dotsPerPixel);
int desiredHeight = (int) (contentBounds.getHeight() / dotsPerPixel);
double desiredWidth = (contentBounds.getWidth() / dotsPerPixel);
double desiredHeight = (contentBounds.getHeight() / dotsPerPixel);

AffineTransform scale = null;

Expand All @@ -28,15 +28,15 @@ public static AffineTransform createScaleTransform(double dotsPerPixel, Rectangl
else if (desiredWidth > intrinsicWidth ||
desiredHeight > intrinsicHeight) {

double rw = (double) desiredWidth / width;
double rh = (double) desiredHeight / height;
double rw = desiredWidth / width;
double rh = desiredHeight / height;

double factor = Math.min(rw, rh);
scale = AffineTransform.getScaleInstance(factor, factor);
} else if (desiredWidth < intrinsicWidth &&
desiredHeight < intrinsicHeight) {
double rw = (double) desiredWidth / width;
double rh = (double) desiredHeight / height;
double rw = desiredWidth / width;
double rh = desiredHeight / height;

double factor = Math.max(rw, rh);
scale = AffineTransform.getScaleInstance(factor, factor);
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
<head>
<style>
@page {

margin: 0;
}
img {
margin-top: 5px;
display: block;
box-sizing: border-box;
border: 1px solid red;
border: 2px solid red;
}
body {
margin: 0;
padding: 0;
}
</style>
</head>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -838,8 +838,11 @@ public void testSvgLinkedFromImgTag() throws IOException {
assertTrue(vt.runTest("svg-linked-from-img-tag", WITH_SVG));
}

/**
* Tests that we correctly render PDF pages in the img tag at
* the correct CSS specified sizing. Issue 344.
*/
@Test
@Ignore // Still a couple of pixels off with width (noticeable when there is a border).
public void testPdfLinkedFromImgTag() throws IOException {
assertTrue(vt.runTest("pdf-linked-from-img-tag"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -854,17 +854,16 @@ public void drawPdfAsImage(PDFormXObject _srcObject, Rectangle contentBounds, fl
// Then the x and y of this object...
af.translate(contentBounds.getX() / _dotsPerPoint, -(contentBounds.getY() / _dotsPerPoint));

float conversion = 96f / 72f;

// Scale to the desired height and width...
AffineTransform scale = ReplacedElementScaleHelper.createScaleTransform(_dotsPerPoint, contentBounds, intrinsicWidth / _dotsPerPoint * conversion, intrinsicHeight / _dotsPerPoint * conversion);
AffineTransform scale = ReplacedElementScaleHelper.createScaleTransform(_dotsPerPoint, contentBounds, intrinsicWidth / _dotsPerPoint, intrinsicHeight / _dotsPerPoint);

if (scale != null) {
af.concatenate(scale);
}

// And take into account the height of the drawn feature...
// And yes these transforms were all determined by trial and error!
af.translate(0, -((intrinsicHeight / _dotsPerPoint) * conversion));
af.translate(0, -((intrinsicHeight / _dotsPerPoint)));

_cp.saveGraphics();
_cp.applyPdfMatrix(af);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ public static PdfBoxPDFReplacedElement create(PDDocument target, byte[] pdfBytes
}

PDPage page = srcDocument.getPage(pageNo);
float width = page.getMediaBox().getWidth() * shared.getDotsPerPixel();
float height = page.getMediaBox().getHeight() * shared.getDotsPerPixel();
float conversion = 96f / 72f;
float width = page.getMediaBox().getWidth() * shared.getDotsPerPixel() * conversion;
float height = page.getMediaBox().getHeight() * shared.getDotsPerPixel() * conversion;

LayerUtility util = new LayerUtility(target);
PDFormXObject formXObject = util.importPageAsForm(srcDocument, page);
Expand Down

0 comments on commit f3f5c81

Please sign in to comment.