[PDF Ink Signatures] Fix stroke shift from crop box offset
If a page has an optional CropBox which has a different offset compared to its required MediaBox, then this can impact the positioning for Ink strokes applied to the page. Update the transform generation used when applying Ink strokes into the PDF page to account for any offset from the intersection of these two boxes. Fixed: 402043701 Change-Id: I4126dc52ddf3533580a94d2f186a46b043f0985b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6346007 Commit-Queue: Alan Screen <awscreen@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Andy Phan <andyphan@chromium.org> Cr-Commit-Position: refs/heads/main@{#1432426}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
918bb8e03a
commit
3e2ce84c84
@ -200,12 +200,14 @@ gfx::Rect CanonicalInkEnvelopeToInvalidationScreenRect(
|
||||
return gfx::ToEnclosingRect(gfx::RectF(x, y, w, h));
|
||||
}
|
||||
|
||||
gfx::AxisTransform2d GetCanonicalToPdfTransform(float page_height) {
|
||||
gfx::AxisTransform2d GetCanonicalToPdfTransform(
|
||||
float page_height,
|
||||
const gfx::Vector2dF& translate) {
|
||||
CHECK_GE(page_height, 0);
|
||||
return gfx::AxisTransform2d::FromScaleAndTranslation(
|
||||
{kUnitConversionFactorPixelsToPoints,
|
||||
-kUnitConversionFactorPixelsToPoints},
|
||||
{0, page_height});
|
||||
{translate.x(), page_height + translate.y()});
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -131,13 +131,17 @@ gfx::Rect CanonicalInkEnvelopeToInvalidationScreenRect(
|
||||
|
||||
// Returns a transform that converts from canonical coordinates (which has a
|
||||
// top-left origin and a different DPI), to PDF coordinates (which has a
|
||||
// bottom-left origin).
|
||||
// bottom-left origin). The translation accounts for any difference from the
|
||||
// defined physical page size to the cropped, visible portion of the PDF page.
|
||||
//
|
||||
// `page_height` is in points. It must not be negative.
|
||||
// `translate` is in points.
|
||||
//
|
||||
// Note that callers can call gfx::AxisTransform2d::Invert() to get a transform
|
||||
// that does conversions in the opposite direction.
|
||||
gfx::AxisTransform2d GetCanonicalToPdfTransform(float page_height);
|
||||
gfx::AxisTransform2d GetCanonicalToPdfTransform(
|
||||
float page_height,
|
||||
const gfx::Vector2dF& translate);
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
|
@ -662,15 +662,29 @@ TEST(PdfInkTransformTest,
|
||||
|
||||
TEST(PdfInkTransformTest, GetCanonicalToPdfTransform) {
|
||||
{
|
||||
gfx::AxisTransform2d tr = GetCanonicalToPdfTransform(/*page_height=*/0);
|
||||
gfx::AxisTransform2d tr = GetCanonicalToPdfTransform(
|
||||
/*page_height=*/0, /*translate=*/gfx::Vector2dF());
|
||||
EXPECT_EQ(gfx::Vector2dF(0.75f, -0.75f), tr.scale());
|
||||
EXPECT_EQ(gfx::Vector2dF(0, 0), tr.translation());
|
||||
}
|
||||
{
|
||||
gfx::AxisTransform2d tr = GetCanonicalToPdfTransform(/*page_height=*/712);
|
||||
gfx::AxisTransform2d tr = GetCanonicalToPdfTransform(
|
||||
/*page_height=*/712, /*translate=*/gfx::Vector2dF());
|
||||
EXPECT_EQ(gfx::Vector2dF(0.75f, -0.75f), tr.scale());
|
||||
EXPECT_EQ(gfx::Vector2dF(0, 712), tr.translation());
|
||||
}
|
||||
{
|
||||
gfx::AxisTransform2d tr = GetCanonicalToPdfTransform(
|
||||
/*page_height=*/0, /*translate=*/gfx::Vector2dF(50, 60));
|
||||
EXPECT_EQ(gfx::Vector2dF(0.75f, -0.75f), tr.scale());
|
||||
EXPECT_EQ(gfx::Vector2dF(50, 60), tr.translation());
|
||||
}
|
||||
{
|
||||
gfx::AxisTransform2d tr = GetCanonicalToPdfTransform(
|
||||
/*page_height=*/1008, /*translate=*/gfx::Vector2dF(50, 60));
|
||||
EXPECT_EQ(gfx::Vector2dF(0.75f, -0.75f), tr.scale());
|
||||
EXPECT_EQ(gfx::Vector2dF(50, 1068), tr.translation());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "pdf/pdf_ink_constants.h"
|
||||
#include "pdf/pdf_ink_conversions.h"
|
||||
#include "pdf/pdf_ink_transform.h"
|
||||
#include "pdf/pdf_transform.h"
|
||||
#include "pdf/pdfium/pdfium_api_wrappers.h"
|
||||
#include "printing/units.h"
|
||||
#include "third_party/ink/src/ink/geometry/mesh.h"
|
||||
@ -171,8 +172,15 @@ std::vector<ReadV2InkPathResult> ReadV2InkPathsFromPageAsModeledShapes(
|
||||
return results;
|
||||
}
|
||||
|
||||
// Get the intersection between the page's MediaBox and CropBox, to find
|
||||
// the translation offset for the shapes' transform.
|
||||
FS_RECTF bounding_box;
|
||||
auto result = FPDF_GetPageBoundingBox(page, &bounding_box);
|
||||
CHECK(result);
|
||||
const gfx::Vector2dF offset(bounding_box.left, bounding_box.bottom);
|
||||
|
||||
gfx::AxisTransform2d transform =
|
||||
GetCanonicalToPdfTransform(FPDF_GetPageHeightF(page));
|
||||
GetCanonicalToPdfTransform(FPDF_GetPageHeightF(page), offset);
|
||||
transform.Invert();
|
||||
|
||||
const int page_object_count = FPDFPage_CountObjects(page);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "pdf/pdf_ink_constants.h"
|
||||
#include "pdf/pdf_ink_conversions.h"
|
||||
#include "pdf/pdf_ink_transform.h"
|
||||
#include "pdf/pdf_transform.h"
|
||||
#include "third_party/ink/src/ink/brush/brush_coat.h"
|
||||
#include "third_party/ink/src/ink/brush/brush_tip.h"
|
||||
#include "third_party/ink/src/ink/geometry/mesh.h"
|
||||
@ -123,8 +124,15 @@ std::vector<ScopedFPDFPageObject> WriteShapeToNewPathsOnPage(
|
||||
FPDF_PAGE page) {
|
||||
CHECK(page);
|
||||
|
||||
// Get the intersection between the page's MediaBox and CropBox, to find
|
||||
// the translation offset for the shape's transform.
|
||||
FS_RECTF bounding_box;
|
||||
auto result = FPDF_GetPageBoundingBox(page, &bounding_box);
|
||||
CHECK(result);
|
||||
const gfx::Vector2dF offset(bounding_box.left, bounding_box.bottom);
|
||||
|
||||
const gfx::AxisTransform2d transform =
|
||||
GetCanonicalToPdfTransform(FPDF_GetPageHeightF(page));
|
||||
GetCanonicalToPdfTransform(FPDF_GetPageHeightF(page), offset);
|
||||
|
||||
std::vector<ScopedFPDFPageObject> results;
|
||||
ModeledShapeOutlinesIterator it(shape);
|
||||
|
@ -193,8 +193,6 @@ TEST_P(PDFiumInkWriterTest, WriteToCroppedPage) {
|
||||
std::vector<uint8_t> saved_pdf_data = engine->GetSaveData();
|
||||
ASSERT_TRUE(!saved_pdf_data.empty());
|
||||
|
||||
// TODO(crbug.com/402043701): The cropped image is incorrect since the
|
||||
// stroke shows up at (37,35) instead of at (92,35).
|
||||
base::FilePath expectation_path = GetInkTestDataFilePath(
|
||||
GetTestDataPathWithPlatformSuffix("ink_writer_cropped.png"));
|
||||
CheckPdfRendering(saved_pdf_data, /*page_index=*/0, gfx::Size(145, 97),
|
||||
@ -226,12 +224,13 @@ TEST_P(PDFiumInkWriterTest, WriteToCroppedPage) {
|
||||
bool get_bounds = FPDFPageObj_GetBounds(saved_results[0].page_object, &left,
|
||||
&bottom, &right, &top);
|
||||
ASSERT_TRUE(get_bounds);
|
||||
// TODO(crbug.com/402043701): The object's position in the PDF page is
|
||||
// relative to the MediaBox, not the CropBox. So its bounding box should be
|
||||
// 55 pixels to the right of 92.3787, at 147.3787.
|
||||
// While the cropped image shows the stroke on the visible page at an X coord
|
||||
// of 92, that object's position in the PDF page is relative to the MediaBox,
|
||||
// not the CropBox. So its bounding box should be 55 points to the right of
|
||||
// that.
|
||||
EXPECT_RECTF_NEAR(gfx::RectF(gfx::PointF(left, bottom),
|
||||
gfx::SizeF(right - left, top - bottom)),
|
||||
gfx::RectF(gfx::PointF(92.3787f, 49.5206f),
|
||||
gfx::RectF(gfx::PointF(147.3787f, 49.5206f),
|
||||
gfx::SizeF(12.5402f, 11.6486f)),
|
||||
/*abs_error=*/0.0001f);
|
||||
}
|
||||
|
Binary file not shown.
Before ![]() (image error) Size: 1.0 KiB After ![]() (image error) Size: 1.0 KiB ![]() ![]() |
Binary file not shown.
Before ![]() (image error) Size: 1.0 KiB After ![]() (image error) Size: 1.0 KiB ![]() ![]() |
Binary file not shown.
Before ![]() (image error) Size: 1019 B After ![]() (image error) Size: 1023 B ![]() ![]() |
Reference in New Issue
Block a user