Closed Bug 1278259 Opened 6 years ago Closed 5 years ago

Elements that require an offscreen surface print blurry/fuzzy on Mac

Categories

(Core :: Printing: Output, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: jwatt, Assigned: jwatt)

References

()

Details

Attachments

(2 files)

It seems like SVG prints blurry/fuzzy on Mac.
Attached image example SVG
This seems to happen both with and without e10s enabled.
Actually this only seems to be an issue for elements that require an offscreen surface, such as elements with group opacity. For example, try:

data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"><circle cx="100" cy="100" r="50" fill="none" stroke="black"/><g opacity="0.98"><circle cx="150" cy="100" r="50" fill="none" stroke="black"/></g></svg>

In this test the left hand circle is crisp, but the right hand circle with the group opacity on it is blurred.
Summary: SVG prints blurry/fuzzy on Mac → SVG elements that require an offscreen surface print blurry/fuzzy on Mac
The output from my real hardware printer is even weirder. In this case the circle with group opacity is scaled in the horizontal direction by a what looks like 2x.
Actually, this is not specific to SVG:

data:text/html,foo <span style="opacity:0.98;">b<span>ar</span></span>
Summary: SVG elements that require an offscreen surface print blurry/fuzzy on Mac → Elements that require an offscreen surface print blurry/fuzzy on Mac
I *think* what's happening here is something along the lines of the following:

PrintTargetCG::MakePrintTarget gets a CGContextRef using PMSessionGetCGGraphicsContext, and I believe the resulting CGContextRef being backed by a PDF backend (or at least some other vector backend). When someone calls PrintTarget::MakeDrawTarget on the PrintTargetCG they get a DrawTargetCairo that wraps this CGContextRef.

Whenever we create something like an nsDisplayOpacity, the layers code ends up using gfxContext::PushGroupForBlendBack, which calls CreateSimilarDrawTarget on the DrawTargetCairo that wraps the CGContextRef (which will call cairo_surface_create_similar). Unfortunately the new DrawTargetCairo will wrap a CGContextRef that is not vector backed.

Since elements that require an offscreen surface will be backed by a raster DrawTarget, the resolution of these DrawTargets really matters. From what I can tell, in nsDeviceContextSpecX::MakePrintTarget, the initial PrintTargetCG is given the size of the paper in _points_. This size is in turn used to create the DrawTarget that wraps the printer CGContextRef, which doesn't matter for _it_ since it is backed by a vector backend. However, when DrawTargets that are created via PushGroupForBlendBack their size is based on the size of the printer DrawTarget, which is why we get these problems.

As far as I know there is no way to create your own non-printer CGContextRef that is vector backed so I'm not sure we can fix this using CGContextRef on Mac. I wonder if fixing bug 1309272 is our best way forward here. One possible stumbling block would be if we can't take the contents of one SkPDF backed SkCanvas and blend it into another.
Depends on: 1309272
(In reply to Jonathan Watt [:jwatt] from comment #7)
> One possible stumbling block would be if we can't take the contents of
> one SkPDF backed SkCanvas and blend it into another.

It looks like SkImage and SkSurface can both store vector commands, so I'd hope that won't be a problem.
Could this be down to the regression I caused, which I'm hopefully fixing in bug 1308259 comment 5?
(In reply to Bob Owen (:bobowen) from comment #9)
> Could this be down to the regression I caused, which I'm hopefully fixing in
> bug 1308259 comment 5?

No, but I fixed this bug in bug 1316750. More details below.


(In reply to Jonathan Watt [:jwatt] from comment #7)
> Whenever we create something like an nsDisplayOpacity, the layers code ends
> up using gfxContext::PushGroupForBlendBack, which calls
> CreateSimilarDrawTarget on the DrawTargetCairo that wraps the CGContextRef
> (which will call cairo_surface_create_similar). Unfortunately the new
> DrawTargetCairo will wrap a CGContextRef that is not vector backed.

Actually it's cairo_quartz_surface_create_cg_layer that is called, which should be vector based.

> when DrawTargets that are created via PushGroupForBlendBack their
> size is based on the size of the printer DrawTarget, which is why we get
> these problems.

By which I mean the DrawTargets device pixel size corresponds to one point in the final rendering.

> As far as I know there is no way to create your own non-printer CGContextRef
> that is vector backed...on Mac.

Actually there is, and that's what we get when we call cairo_quartz_surface_create_cg_layer, so that was not the problem.

I fixed multiple issues relating to this bug but the final one was that, with e10s turned on, the code to replay a print recording was creating raster backed DrawTargets when handling replaying of CreateSimilarDrawTarget() calls (even though the corresponding calls recorded in the content process were creating vector backed DrawTargets). The last issue that was part of fixing that puzzle was that PrintTranslator generates the DrawTarget from which CreateSimilarDrawTargets are generated before printing begins, which for PrintTargetCG meant that the wrapped CGContext was raster based. Bug 1310165 fixed that.
Assignee: nobody → jwatt
Status: NEW → RESOLVED
Closed: 5 years ago
Component: Print Preview → Printing: Output
Depends on: 1310165
No longer depends on: 1309272
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.