Bug 1631449 - Apply a grayscale filter to pages when monochrome. r=jwatt

This hooks the "monochrome" media query and co to the
nsIPrintSettings.printInColor setting.

This print setting we're using is not exposed in the print preview UI,
but you can test it setting the print.print_in_color preference to
"false", and then print preview will correctly show up greyscale'd.

Once this lands, the UI folks just have to use it as they see fit :)

I would've liked to add a proper rendering test, but the print reftests
check only whether the PDF text matches.

I could add a test to printpreview_helper.xhtml, but I'm refactoring
that file in bug 1648064 so I'd rather wait a bit and add it in a
separate bug. The test for the media feature should make sure that we
test that code path at least.

Differential Revision: https://phabricator.services.mozilla.com/D83552
This commit is contained in:
Emilio Cobos Álvarez 2020-07-15 03:45:33 +00:00
parent f543954b4b
commit d275fd6251
7 changed files with 50 additions and 4 deletions

View File

@ -14,3 +14,4 @@ fails print test-print-single-page.html test-print-single-page-noref.html
print test-async-print.html test-text-ref.html
fails print test-unexpected-text.html test-unexpected-text-noref.html
fails print test-missing-text.html test-missing-text-noref.html
test-pref(print.print_in_color,false) fails print test-color-text-01.html test-color-text-01.html

View File

@ -0,0 +1,9 @@
<!doctype html>
<style>
@media (monochrome) {
p { display: none }
}
</style>
<p style="color: red">
Red
</p>

View File

@ -610,6 +610,8 @@ mozilla::StyleDisplayMode Gecko_MediaFeatures_GetDisplayMode(
const mozilla::dom::Document*);
uint32_t Gecko_MediaFeatures_GetColorDepth(const mozilla::dom::Document*);
uint32_t Gecko_MediaFeatures_GetMonochromeBitsPerPixel(
const mozilla::dom::Document*);
void Gecko_MediaFeatures_GetDeviceSize(const mozilla::dom::Document*,
nscoord* width, nscoord* height);

View File

@ -16,6 +16,7 @@
#include "nsDeviceContext.h"
#include "nsIBaseWindow.h"
#include "nsIDocShell.h"
#include "nsIPrintSettings.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentInlines.h"
#include "nsIWidget.h"
@ -112,14 +113,38 @@ void Gecko_MediaFeatures_GetDeviceSize(const Document* aDocument,
*aHeight = size.height;
}
uint32_t Gecko_MediaFeatures_GetMonochromeBitsPerPixel(
const Document* aDocument) {
// The default bits per pixel for a monochrome device. We could propagate this
// further to nsIPrintSettings, but Gecko doesn't actually know this value
// from the hardware, so it seems silly to do so.
static constexpr uint32_t kDefaultMonochromeBpp = 8;
nsPresContext* pc = aDocument->GetPresContext();
if (!pc) {
return 0;
}
nsIPrintSettings* ps = pc->GetPrintSettings();
if (!ps) {
return 0;
}
bool color = true;
ps->GetPrintInColor(&color);
return color ? 0 : kDefaultMonochromeBpp;
}
uint32_t Gecko_MediaFeatures_GetColorDepth(const Document* aDocument) {
if (Gecko_MediaFeatures_GetMonochromeBitsPerPixel(aDocument) != 0) {
// If we're a monochrome device, then the color depth is zero.
return 0;
}
// Use depth of 24 when resisting fingerprinting, or when we're not being
// rendered.
uint32_t depth = 24;
if (!nsContentUtils::ShouldResistFingerprinting(aDocument)) {
if (nsDeviceContext* dx = GetDeviceContextFor(aDocument)) {
// FIXME: On a monochrome device, return 0!
dx->GetDepth(depth);
}
}

View File

@ -306,6 +306,12 @@
margin: 0.125in 0.25in;
}
@media (monochrome) {
*|*::-moz-page {
filter: grayscale(1);
}
}
*|*::-moz-pagecontent {
display: block;
margin: auto;

View File

@ -1687,6 +1687,10 @@ function RecvStartPrint(isPrintSelection, printRange)
ps.endPageRange = +range[1] || 1;
}
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
ps.printInColor = prefs.getBoolPref("print.print_in_color", true);
g.browser.frameLoader.print(g.browser.outerWindowID, ps, {
onStateChange: function(webProgress, request, stateFlags, status) {
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP &&

View File

@ -247,13 +247,12 @@ fn eval_color_index(
/// https://drafts.csswg.org/mediaqueries-4/#monochrome
fn eval_monochrome(
_: &Device,
device: &Device,
query_value: Option<u32>,
range_or_operator: Option<RangeOrOperator>,
) -> bool {
// For color devices we should return 0.
// FIXME: On a monochrome device, return the actual color depth, not 0!
let depth = 0;
let depth = unsafe { bindings::Gecko_MediaFeatures_GetMonochromeBitsPerPixel(device.document()) };
RangeOrOperator::evaluate(range_or_operator, query_value, depth)
}