Closed Bug 2034406 Opened 5 months ago Closed 4 months ago

[skpdf] PDFs generated from pdf.js (via MozPrintCallback) are missing selectable text

Categories

(Core :: Printing: Output, defect, P3)

defect

Tracking

()

VERIFIED FIXED
153 Branch
Tracking Status
firefox154 --- verified

People

(Reporter: calixte, Assigned: emilio, NeedInfo)

References

Details

Attachments

(2 files, 1 obsolete file)

Attached file tracemonkey.pdf —

STR:

  1. Set about:config pref print.experimental.skpdf to true
  2. Print, and choose the Save to PDF backend.
  3. Open the resulting file in Firefox
  4. Try to select any text in the document.

ACTUAL RESULTS:
The text is unselectable.

EXPECTED RESULTS:
Text should be selectable.

Each page is rendered as an image.

Jamie, Emilio, can you take a look?

Flags: needinfo?(jteh)
Flags: needinfo?(emilio)

Happens on Linux as well afaict.

Calixte, how does pdf.js draw the text for printing? Just .drawText from the mozPrintCallback?

Flags: needinfo?(cdenizet)
See Also: → 2020020

(In reply to Emilio Cobos Álvarez [:emilio] from comment #3)

Calixte, how does pdf.js draw the text for printing? Just .drawText from the mozPrintCallback?

Yes just drawText.
I don't know if it matters but we call drawText for each char.

Flags: needinfo?(cdenizet)

Yeah so I think I understand what's going on. What happens is that for MozPrintCallback, we call CreateSimilarDrawTarget for each <canvas> element (for each page, effectively):

That basically causes it to get a raster surface here:

Lee, I'm not sure what the best way to go about this is, here's what I've tried:

I first tried the obvious "implement CreateSimilarDrawTarget without a raster surface". I don't see a particularly trivial way of doing that tho. SkPDFDocument::makeSurface just returns a raster surface, and reusing the SkCanvas seems like asking for trouble. Of course that works in this particular case because we only have one canvas per page, but still.

I tried to use the recording surface stuff with something like the diff below:

diff --git a/layout/generic/nsPageSequenceFrame.cpp b/layout/generic/nsPageSequenceFrame.cpp
index 7d1e0c27bff7..3cc894d849a3 100644
--- a/layout/generic/nsPageSequenceFrame.cpp
+++ b/layout/generic/nsPageSequenceFrame.cpp
@@ -12,6 +12,8 @@
 #include "mozilla/PrintedSheetFrame.h"
 #include "mozilla/StaticPresData.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/DrawEventRecorder.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/intl/AppDateTimeFormat.h"
 #include "nsCOMPtr.h"
@@ -659,16 +661,18 @@ nsresult nsPageSequenceFrame::PrePrintNextSheet(nsITimerCallback* aCallback,
       UniquePtr<gfxContext> renderingContext = dc->CreateRenderingContext();
       NS_ENSURE_TRUE(renderingContext, NS_ERROR_OUT_OF_MEMORY);

-      DrawTarget* drawTarget = renderingContext->GetDrawTarget();
-      if (NS_WARN_IF(!drawTarget)) {
+      DrawTarget* referenceDt = renderingContext->GetDrawTarget();
+      if (NS_WARN_IF(!referenceDt)) {
         return NS_ERROR_FAILURE;
       }

       for (HTMLCanvasElement* canvas : Reversed(mCurrentCanvasList)) {
         CSSIntSize size = canvas->GetSize();
-
-        RefPtr<DrawTarget> canvasTarget = drawTarget->CreateSimilarDrawTarget(
-            size.ToUnknownSize(), drawTarget->GetFormat());
+        RefPtr recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>(nullptr);
+        RefPtr<DrawTarget> canvasTarget =
+            gfx::Factory::CreateRecordingDrawTarget(
+                recorder, referenceDt,
+                gfx::IntRect(gfx::IntPoint(), size.ToUnknownSize()));
         if (!canvasTarget) {
           continue;
         }

But this hits this warning. With that diff, I get there with a mozilla::gfx::SourceSurfaceRecording, which I think it's just not handled. Should it?

Another potential approach would be to maybe use the DrawDependentSurface mechanism that iframes use, instead of CreateSimilarDrawTarget. I haven't tried that yet but it should work as well...

Lee, any suggestion on the preferred approach?

Flags: needinfo?(emilio) → needinfo?(lsalzman)

The good thing is that this is just related to pdf.js / MozPrintCallback and not a more general problem

Summary: PDFs generated by SkPDF on Windows are missing selectable text → PDFs generated by SkPDF on Windows are missing selectable text (
Summary: PDFs generated by SkPDF on Windows are missing selectable text ( → PDFs generated from pdf.js (via MozPrintCallback) are missing selectable text
Severity: -- → S3
Priority: -- → P3
Summary: PDFs generated from pdf.js (via MozPrintCallback) are missing selectable text → [skpdf] PDFs generated from pdf.js (via MozPrintCallback) are missing selectable text
Flags: needinfo?(jteh)
Flags: needinfo?(emilio)

This seems to do the trick, but I'm not super-happy about it:

  • SourceSurfaceSkia generally assumes non-null mImage, and we are
    adding this mPicture codepath, should I add a SourceSurfaceSkPicture
    or something?

  • Similarly, having to null out mCanvas and such after calling
    Snapshot() is a bit hacky, but it works for our purposes.

Assignee: nobody → emilio
Status: NEW → ASSIGNED
Flags: needinfo?(emilio)

By teaching DrawTargetRecording to draw a SourceSurfaceRecording
properly.

Calixte do you know where / how could / should we add some tests for this?

Flags: needinfo?(lsalzman) → needinfo?(cdenizet)
Pushed by sstanca@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/aabf9eb2dd63 https://hg.mozilla.org/integration/autoland/rev/f36d4216725e Revert "Bug 2034406 - Preserve vector commands in MozPrintCallback. r=lsalzman" for causing webdriver failures.

Reverted this because it was causing webdriver failures.

  • Revert link
  • Push with failures
  • Failure Log
  • Failure line: TEST-UNEXPECTED-FAIL | /webdriver/tests/classic/print/printcmd.py | test_large_html_document - AssertionError: unknown error (500): [Exception... "Unexpected error" nsresult: "0x8000ffff (NS_ERROR_UNEXPECTED)" location: "JS frame :: resource:///modules/sessionstore/SessionStore.sys.mjs :: ssi_onQuitApplicationGranted :: line 2910" data: no]

Also, please check ths wpt failure.

Flags: needinfo?(emilio)
Flags: needinfo?(emilio)
Pushed by smolnar@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/96d3f7803ff4 https://hg.mozilla.org/integration/autoland/rev/de4a613bc288 Revert "Bug 2034406 - Preserve vector commands in MozPrintCallback. r=lsalzman" for causing wpt failures

(In reply to Emilio Cobos Álvarez [:emilio] from comment #9)

Calixte do you know where / how could / should we add some tests for this?

I'd say in test directory for printing stuff.
You can use something like:
https://searchfox.org/firefox-main/source/layout/tools/reftest/reftest.sys.mjs#2240

Once you've a document from getDocument, you can call getPage(1) to get the first page and then call getTextContent in order to make sure that isn't not just an image and assert on the text content.
Jamie did something similar:
https://searchfox.org/firefox-main/source/accessible/tests/browser/pdfOutput/head.js#109-127

Flags: needinfo?(cdenizet)

(In reply to Sandor Molnar[:smolnar] from comment #15)

Backed out for causing wpt failures @ mozilla/html/canvas/mozPrintCallback-rect-001-print.html

Was missing a setTransform call.

Flags: needinfo?(emilio)
Attachment #9585418 - Attachment is obsolete: true
Status: ASSIGNED → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Target Milestone: --- → 153 Branch

sheriffs: Can we back this out of beta for causing bug 2045512? We can leave it on Nightly.

Flags: needinfo?(sheriffs)
QA Whiteboard: [qa-triage-done-c154/b153] [qa-ver-needed-c154/b153]
Flags: qe-verify+

(In reply to Emilio Cobos Álvarez [:emilio] from comment #20)

sheriffs: Can we back this out of beta for causing bug 2045512? We can leave it on Nightly.

Pascal is current release owner for beta

Flags: needinfo?(pascalc)
Flags: needinfo?(pascalc)
QA Contact: oardelean

Reproducible on a 2026-04-23 Firefox Nightly build on Windows 10.

Verified as fixed on Firefox Nightly 154.0a1 on Windows 10, Ubuntu 22, macOS 13.

Status: RESOLVED → VERIFIED
QA Whiteboard: [qa-triage-done-c154/b153] [qa-ver-needed-c154/b153] → [qa-triage-done-c154/b153] [qa-ver-done-c154/b153]
Flags: qe-verify+
Regressions: 2057444
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: