0

[PDF Ink Signatures] Change page object mark name in WriteStrokeToPage()

Delete the placeholder mark name constant inside pdfium_ink_writer.cc
and use the real one in pdf_ink_constants.h. This is all that is needed,
since prior changes have already aligned the WriteStrokeToPage() output
with the "V2" Ink format.

Prove it works in PDFiumInkWriterTest.Basic by reloading the saved PDF
into a second PDFiumEngine. Then verify the only page in the saved PDF
has an ink::ModeledShape that behaves exactly like the original in terms
of what it can intersect. i.e. Demonstrate a round trip write and read
preserves a sufficient amount of data.

Bug: 353904284
Change-Id: Ia1f1a824cc74b86e5ddddb6ba3a900b76aa88eb2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5984473
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Alan Screen <awscreen@chromium.org>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#1378773}
This commit is contained in:
Lei Zhang
2024-11-06 05:20:56 +00:00
committed by Chromium LUCI CQ
parent 5d76d451f5
commit c084d39aaa
3 changed files with 56 additions and 7 deletions

@ -10,6 +10,7 @@
#include "base/containers/span.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/memory/raw_ref.h"
#include "pdf/pdf_ink_constants.h"
#include "pdf/pdf_ink_conversions.h"
#include "pdf/pdf_ink_transform.h"
#include "third_party/ink/src/ink/geometry/mesh.h"
@ -25,10 +26,6 @@ namespace chrome_pdf {
namespace {
// TODO(crbug.com/353904284): Choose real marker name that doesn't conflict
// with other writers.
constexpr char kInkAnnotationIdentifierKey[] = "ink-annot-id";
// Wrapper around an `ink::ModeledShape` to iterate through all the outlines
// that make up the shape.
class ModeledShapeOutlinesIterator {
@ -196,7 +193,7 @@ FPDF_PAGEOBJECT WriteStrokeToPage(FPDF_DOCUMENT document,
FPDF_PAGEOBJECT page_obj = path.get();
FPDF_PAGEOBJECTMARK mark =
FPDFPageObj_AddMark(page_obj, kInkAnnotationIdentifierKey);
FPDFPageObj_AddMark(page_obj, kInkAnnotationIdentifierKeyV2);
CHECK(mark);
SetBrushPropertiesForPath(stroke.GetBrush(), page_obj);

@ -16,7 +16,7 @@ class Stroke;
namespace chrome_pdf {
// Writes `stroke` into `page` in `document`.
// Writes `stroke` into `page` in `document` using the "V2" Ink format.
//
// Returns a handle to the page object if the operation is successful. If the
// operation fails, then both `document` and `page` are left unchanged.

@ -14,11 +14,16 @@
#include "base/time/time.h"
#include "pdf/pdf_ink_brush.h"
#include "pdf/pdfium/pdfium_engine.h"
#include "pdf/pdfium/pdfium_ink_reader.h"
#include "pdf/pdfium/pdfium_page.h"
#include "pdf/pdfium/pdfium_test_base.h"
#include "pdf/test/pdf_ink_test_helpers.h"
#include "pdf/test/test_client.h"
#include "pdf/test/test_helpers.h"
#include "third_party/ink/src/ink/geometry/affine_transform.h"
#include "third_party/ink/src/ink/geometry/intersects.h"
#include "third_party/ink/src/ink/geometry/modeled_shape.h"
#include "third_party/ink/src/ink/geometry/point.h"
#include "third_party/ink/src/ink/strokes/input/stroke_input.h"
#include "third_party/ink/src/ink/strokes/input/stroke_input_batch.h"
#include "third_party/ink/src/ink/strokes/stroke.h"
@ -77,7 +82,7 @@ std::unique_ptr<PdfInkBrush> CreateTestBrush() {
using PDFiumInkWriterTest = PDFiumTestBase;
TEST_P(PDFiumInkWriterTest, Basic) {
TEST_P(PDFiumInkWriterTest, BasicWriteAndRead) {
TestClient client;
std::unique_ptr<PDFiumEngine> engine =
InitializeEngine(&client, FILE_PATH_LITERAL("blank.pdf"));
@ -103,6 +108,53 @@ TEST_P(PDFiumInkWriterTest, Basic) {
CheckPdfRendering(saved_pdf_data,
/*page_index=*/0, gfx::Size(200, 200),
GetInkTestDataFilePath("ink_writer_basic.png"));
// Load `saved_pdf_data` into `saved_engine` and get a handle to the one and
// only page.
TestClient saved_client;
std::unique_ptr<PDFiumEngine> saved_engine =
InitializeEngineFromData(&saved_client, std::move(saved_pdf_data));
ASSERT_TRUE(saved_engine);
ASSERT_EQ(saved_engine->GetNumberOfPages(), 1);
PDFiumPage& saved_pdfium_page = GetPDFiumPageForTest(*saved_engine, 0);
FPDF_PAGE saved_page = saved_pdfium_page.GetPage();
ASSERT_TRUE(saved_page);
// Complete the round trip and read the written PDF data back into memory as
// an ink::ModeledShape. ReadV2InkPathsFromPageAsModeledShapes() is known to
// be good because its unit tests reads from a real, known to be good Ink PDF.
std::vector<ReadV2InkPathResult> saved_results =
ReadV2InkPathsFromPageAsModeledShapes(saved_page);
ASSERT_EQ(saved_results.size(), 1u);
// Take the original and saved shapes and compare them. Note that
// `saved_shape` does not have an outline, so just check they behave the same
// way with ink::Intersects().
const auto& shape = stroke.GetShape();
const auto& saved_shape = saved_results[0].shape;
// All point values below are in canonical coordinates, so no transform is
// necessary.
const auto no_transform = ink::AffineTransform::Identity();
// Points at the corners do not intersect.
EXPECT_FALSE(ink::Intersects(ink::Point{0, 0}, shape, no_transform));
EXPECT_FALSE(ink::Intersects(ink::Point{0, 0}, saved_shape, no_transform));
EXPECT_FALSE(ink::Intersects(ink::Point{266, 266}, shape, no_transform));
EXPECT_FALSE(
ink::Intersects(ink::Point{266, 266}, saved_shape, no_transform));
// Points close to `shape`, that still do not intersect.
EXPECT_FALSE(ink::Intersects(ink::Point{139, 51}, shape, no_transform));
EXPECT_FALSE(ink::Intersects(ink::Point{139, 51}, saved_shape, no_transform));
EXPECT_FALSE(ink::Intersects(ink::Point{128, 63}, shape, no_transform));
EXPECT_FALSE(ink::Intersects(ink::Point{128, 63}, saved_shape, no_transform));
// Points that do intersect.
EXPECT_TRUE(ink::Intersects(ink::Point{139, 53}, shape, no_transform));
EXPECT_TRUE(ink::Intersects(ink::Point{139, 53}, saved_shape, no_transform));
EXPECT_TRUE(ink::Intersects(ink::Point{129, 63}, shape, no_transform));
EXPECT_TRUE(ink::Intersects(ink::Point{129, 63}, saved_shape, no_transform));
}
TEST_P(PDFiumInkWriterTest, EmptyStroke) {