Bug 1669854 - Add a single pageRanges print setting. r=nordzilla

... which is an array of pairs of ranges, and use it instead of the
existing printRange / startPage / endPage settings.

Differential Revision: https://phabricator.services.mozilla.com/D96093
This commit is contained in:
Emilio Cobos Álvarez 2020-11-07 16:01:57 +00:00
parent 3bf1904869
commit 771dd03229
23 changed files with 175 additions and 319 deletions

View File

@ -96,42 +96,7 @@ void PrintedSheetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// NS_PAGE_SKIPPED_BY_CUSTOM_RANGE state bit and returns true.
static bool TagIfSkippedByCustomRange(nsPageFrame* aPageFrame, int32_t aPageNum,
nsSharedPageData* aPD) {
if (!aPD->mDoingPageRange) {
MOZ_ASSERT(!aPageFrame->HasAnyStateBits(NS_PAGE_SKIPPED_BY_CUSTOM_RANGE),
"page frames shouldn't be tagged as skipped if we're not "
"printing with a custom page range");
return false;
}
bool isPageSkipped = false;
// As described in nsSharedPageData documentation: we can use mFromPageNum
// and mToPageNum as a quick way to reject entirely-out-of-range pages. For
// page numbers inside these bounds, we need to check mRanges to find out if
// they're included in our subranges (if there are any).
if (aPageNum < aPD->mFromPageNum || aPageNum > aPD->mToPageNum) {
// Page is out-of-bounds; it's skipped.
isPageSkipped = true;
} else {
// Check subranges (if there are any).
const auto& ranges = aPD->mPageRanges;
int32_t length = ranges.Length();
// Page ranges are pairs (start, end) of included pages.
if (length && (length % 2 == 0)) {
isPageSkipped = true;
for (int32_t i = 0; i < length; i += 2) {
if (ranges[i] <= aPageNum && aPageNum <= ranges[i + 1]) {
// The page is included in this piece of the custom range,
// so it's not skipped.
isPageSkipped = false;
break;
}
}
}
}
if (!isPageSkipped) {
if (!nsIPrintSettings::IsPageSkipped(aPageNum, aPD->mPageRanges)) {
MOZ_ASSERT(!aPageFrame->HasAnyStateBits(NS_PAGE_SKIPPED_BY_CUSTOM_RANGE),
"page frames NS_PAGE_SKIPPED_BY_CUSTOM_RANGE state should "
"only be set if we actually want to skip the page");

View File

@ -296,15 +296,8 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext,
mPageData->mEdgePaperMargin = nsPresContext::CSSTwipsToAppUnits(edgeTwips);
// Get the custom page-range state:
mPageData->mPrintSettings->GetStartPageRange(&mPageData->mFromPageNum);
mPageData->mPrintSettings->GetEndPageRange(&mPageData->mToPageNum);
mPageData->mPrintSettings->GetPageRanges(mPageData->mPageRanges);
int16_t printType;
mPageData->mPrintSettings->GetPrintRange(&printType);
mPageData->mDoingPageRange =
nsIPrintSettings::kRangeSpecifiedPageRange == printType;
// We use the CSS "margin" property on the -moz-printed-sheet pseudoelement
// to determine the space between each printed sheet in print preview.
// Keep a running y-offset for each printed sheet.
@ -453,14 +446,6 @@ nsresult nsPageSequenceFrame::StartPrint(nsPresContext* aPresContext,
mPageData->mDocURL = aDocURL;
}
// If printing a range of pages make sure at least the starting page
// number is valid
if (mPageData->mDoingPageRange) {
if (mPageData->mFromPageNum > mPageData->mRawNumPages) {
return NS_ERROR_INVALID_ARG;
}
}
// Begin printing of the document
mCurrentSheetIdx = 0;
return NS_OK;

View File

@ -63,19 +63,9 @@ class nsSharedPageData {
// that it's reflowed the final page):
int32_t mRawNumPages = 0;
// Smallest included page num. 1-based. Only used if mDoingPageRange is true.
int32_t mFromPageNum = 0;
// Largest included page num. 1-based. Only used if mDoingPageRange is true.
int32_t mToPageNum = 0;
// If there's more than one page-range, then its components are stored here
// as pairs of (start,end). They're stored in the order provided (not
// necessarily in ascending order). The most extreme included values will
// still be stored in mFromPageNum and mToPageNum, so that entirely
// out-of-bounds pages can be easily filtered out without needing to inspect
// this array. As above, the values are 1-based, and this member is only used
// if mDoingPageRange is true.
// necessarily in ascending order).
nsTArray<int32_t> mPageRanges;
// Margin for headers and footers; it defaults to 4/100 of an inch on UNIX
@ -90,9 +80,6 @@ class nsSharedPageData {
// frames that overflowed. It's 1.0 if none overflowed horizontally.
float mShrinkToFitRatio = 1.0f;
// True if the current print operation uses one or more print ranges:
bool mDoingPageRange = false;
// Lazy getter, to look up our pages-per-sheet info based on mPrintSettings
// (if it's available). The result is stored in our mPagesPerSheetInfo
// member-var to speed up subsequent lookups.

View File

@ -784,7 +784,7 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview,
// In legacy print-preview mode, override any UI that wants to PrintPreview
// any selection or page range. The legacy print-preview intends to view
// every page in PrintPreview each time.
printData->mPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages);
printData->mPrintSettings->SetPageRanges({});
}
MOZ_TRY(EnablePOsForPrinting());
@ -1380,14 +1380,12 @@ nsresult nsPrintJob::SetupToPrintContent() {
int32_t startPage = 1;
int32_t endPage = printData->mNumPrintablePages;
int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
printData->mPrintSettings->GetPrintRange(&printRangeType);
if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) {
printData->mPrintSettings->GetStartPageRange(&startPage);
printData->mPrintSettings->GetEndPageRange(&endPage);
if (endPage > printData->mNumPrintablePages) {
endPage = printData->mNumPrintablePages;
}
nsTArray<int32_t> ranges;
printData->mPrintSettings->GetPageRanges(ranges);
for (size_t i = 0; i < ranges.Length(); i += 2) {
startPage = std::max(1, std::min(startPage, ranges[i]));
endPage = std::min(printData->mNumPrintablePages,
std::max(endPage, ranges[i + 1]));
}
nsresult rv = NS_OK;

View File

@ -12,6 +12,7 @@ print test-print-selection.html test-text-ref.html
print test-print-selection-shadow-dom.html test-text-ref.html
print test-print-selection-iframe.html test-text-ref.html
print test-print-range.html test-print-range-ref.html
print test-print-range-complex.html test-print-range-complex-ref.html
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

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="print.css" rel="stylesheet">
</head>
<body>
<p>This text should appear on page 1</p>
<p>This text should appear on page 2</p>
<p>This text should appear on page 3</p>
</body>
</html>

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html reftest-print-range="2-2,4-5">
<head>
<meta charset="utf-8">
<link href="print.css" rel="stylesheet">
</head>
<body>
<p>This text should not be here</p>
<p>This text should appear on page 1</p>
<p>This text should not be here</p>
<p>This text should appear on page 2</p>
<p>This text should appear on page 3</p>
<p>This text should not be here</p>
</body>
</html>

View File

@ -274,7 +274,7 @@ function printToPdf() {
if (printRange) {
if (printRange === 'selection') {
isPrintSelection = true;
} else if (!/^[1-9]\d*-[1-9]\d*$/.test(printRange)) {
} else if (!printRange.split(',').every(range => /^[1-9]\d*-[1-9]\d*$/.test(range))) {
SendException("invalid value for reftest-print-range");
return;
}

View File

@ -1702,10 +1702,10 @@ function RecvStartPrint(isPrintSelection, printRange)
ps.outputFormat = Ci.nsIPrintSettings.kOutputFormatPDF;
ps.printSelectionOnly = isPrintSelection;
if (printRange) {
ps.printRange = Ci.nsIPrintSettings.kRangeSpecifiedPageRange;
let range = printRange.split('-');
ps.startPageRange = +range[0] || 1;
ps.endPageRange = +range[1] || 1;
ps.pageRanges = printRange.split(',').map(function(r) {
let range = r.split('-');
return [+range[0] || 1, +range[1] || 1]
}).flat();
}
var prefs = Cc["@mozilla.org/preferences-service;1"].

View File

@ -98,11 +98,7 @@ class PrintingChild extends JSWindowActorChild {
BrowsingContext.get(data.browsingContextId),
data.simplifiedMode,
data.changingBrowsers,
data.lastUsedPrinterName,
data.outputFormat,
data.startPageRange,
data.endPageRange,
data.printRange
data.lastUsedPrinterName
);
break;
}
@ -332,11 +328,7 @@ class PrintingChild extends JSWindowActorChild {
browsingContext,
simplifiedMode,
changingBrowsers,
lastUsedPrinterName,
outputFormat,
startPageRange,
endPageRange,
printRange
lastUsedPrinterName
) {
const { docShell } = this;
@ -350,16 +342,6 @@ class PrintingChild extends JSWindowActorChild {
false
);
if (outputFormat == printSettings.kOutputFormatPDF) {
printSettings.outputFormat = printSettings.kOutputFormatPDF;
printSettings.printToFile = true;
}
// TODO: waiting on the print preview to be updated in Bug 1659005
printSettings.startPageRange = startPageRange;
printSettings.endPageRange = endPageRange;
printSettings.printRange = printRange;
// If we happen to be on simplified mode, we need to set docURL in order
// to generate header/footer content correctly, since simplified tab has
// "about:blank" as its URI.

View File

@ -148,11 +148,7 @@ var PrintEventHandler = {
// These settings do not have an associated pref value or flag, but
// changing them requires us to update the print preview.
_nonFlaggedUpdatePreviewSettings: new Set([
"printAllOrCustomRange",
"startPageRange",
"endPageRange",
]),
_nonFlaggedUpdatePreviewSettings: new Set(["pageRanges"]),
async init() {
Services.telemetry.scalarAdd("printing.preview_opened_tm", 1);
@ -1178,11 +1174,6 @@ var PrintSettingsViewProxy = {
name => !!target[name]
);
case "printAllOrCustomRange":
return target.printRange == Ci.nsIPrintSettings.kRangeAllPages
? "all"
: "custom";
case "supportsColor":
return this.availablePrinters[target.printerName].supportsColor;
@ -1271,13 +1262,6 @@ var PrintSettingsViewProxy = {
}
break;
case "printAllOrCustomRange":
target.printRange =
value == "all"
? Ci.nsIPrintSettings.kRangeAllPages
: Ci.nsIPrintSettings.kRangeSpecifiedPageRange;
break;
case "customMargins":
if (value != null) {
for (let [settingName, newVal] of Object.entries(value)) {
@ -1779,14 +1763,14 @@ class PageRangeInput extends PrintUIControlMixin(HTMLElement) {
updatePageRange() {
this.dispatchSettingsChange({
printAllOrCustomRange: this._rangePicker.value,
startPageRange: this._startRange.value,
endPageRange: this._endRange.value,
pageRanges: this._rangePicker.value
? [this._startRange.value, this._endRange.value]
: [],
});
}
update(settings) {
this.toggleAttribute("all-pages", settings.printRange == 0);
this.toggleAttribute("all-pages", !settings.pageRanges.length);
}
handleEvent(e) {
@ -1832,8 +1816,7 @@ class PageRangeInput extends PrintUIControlMixin(HTMLElement) {
if (this._startRange.validity.valid && this._endRange.validity.valid) {
this.dispatchSettingsChange({
startPageRange: this._startRange.value,
endPageRange: this._endRange.value,
pageRanges: [this._startRange.value, this._endRange.value],
});
this._rangeError.hidden = true;
this._startRangeOverflowError.hidden = true;

View File

@ -39,8 +39,7 @@ add_task(async function testRangeResetAfterScale() {
helper.resolvePrint();
});
helper.assertPrintedWithSettings({
startPageRange: 1,
endPageRange: 1,
pageRanges: [1, 1],
scaling: 0.1,
});
});
@ -56,8 +55,8 @@ add_task(async function testInvalidRangeResetAfterDestinationChange() {
let startPageRange = helper.get("custom-range-start");
await helper.assertSettingsChanged(
{ printRange: 0 },
{ printRange: 1 },
{ pageRanges: [] },
{ pageRanges: [1, 1] },
async () => {
await helper.waitForPreview(() => changeAllToCustom(helper));
}
@ -65,7 +64,7 @@ add_task(async function testInvalidRangeResetAfterDestinationChange() {
let rangeError = helper.get("error-invalid-start-range-overflow");
await helper.assertSettingsNotChanged({ startPageRange: 1 }, async () => {
await helper.assertSettingsNotChanged({ pageRanges: [1, 1] }, async () => {
ok(rangeError.hidden, "Range error is hidden");
await helper.text(startPageRange, "9");
await BrowserTestUtils.waitForAttributeRemoval("hidden", rangeError);

View File

@ -109,9 +109,7 @@ add_task(async function testSheetCountPageRange() {
// Set page range to 2-3, sheet count should be 2.
await helper.waitForPreview(() =>
helper.dispatchSettingsChange({
printRange: helper.settings.kRangeSpecifiedPageRange,
startPageRange: 2,
endPageRange: 3,
pageRanges: [2, 3],
})
);

View File

@ -302,17 +302,28 @@ class PrintHelper {
return this.win.PrintEventHandler.viewSettings;
}
_assertMatches(a, b, msg) {
if (Array.isArray(a)) {
is(a.length, b.length, msg);
for (let i = 0; i < a.length; ++i) {
this._assertMatches(a[i], b[i], msg);
}
return;
}
is(a, b, msg);
}
assertSettingsMatch(expected) {
let { settings } = this;
for (let [setting, value] of Object.entries(expected)) {
is(settings[setting], value, `${setting} matches`);
this._assertMatches(settings[setting], value, `${setting} matches`);
}
}
assertPrintedWithSettings(expected) {
ok(this._printedSettings, "Printed settings have been recorded");
for (let [setting, value] of Object.entries(expected)) {
is(
this._assertMatches(
this._printedSettings[setting],
value,
`${setting} matches printed setting`

View File

@ -15,8 +15,6 @@ struct CStringKeyValue {
struct PrintData {
nullable PRemotePrintJob remotePrintJob;
int32_t startPageRange;
int32_t endPageRange;
double edgeTop;
double edgeLeft;
double edgeBottom;
@ -36,7 +34,7 @@ struct PrintData {
bool showMarginGuides;
bool isPrintSelectionRBEnabled;
bool printSelectionOnly;
short printRange;
int32_t[] pageRanges;
nsString title;
nsString docURL;
nsString headerStrLeft;

View File

@ -221,13 +221,21 @@ NSPrintInfo* nsPrintSettingsX::CreateOrCopyPrintInfo(bool aWithScaling) {
// if the caller explicitly asked for it.
[printInfo setScalingFactor:CGFloat(aWithScaling ? mScaling : 1.0f)];
BOOL allPages = mPrintRange == nsIPrintSettings::kRangeAllPages ? YES : NO;
const bool allPages = mPageRanges.IsEmpty();
NSMutableDictionary* dict = [printInfo dictionary];
[dict setObject:[NSNumber numberWithInt:mNumCopies] forKey:NSPrintCopies];
[dict setObject:[NSNumber numberWithBool:allPages] forKey:NSPrintAllPages];
[dict setObject:[NSNumber numberWithInt:mStartPageNum] forKey:NSPrintFirstPage];
[dict setObject:[NSNumber numberWithInt:mEndPageNum] forKey:NSPrintLastPage];
int32_t start = 1;
int32_t end = 1;
for (size_t i = 0; i < mPageRanges.Length(); i += 2) {
start = std::min(start, mPageRanges[i]);
end = std::max(end, mPageRanges[i + 1]);
}
[dict setObject:[NSNumber numberWithInt:start] forKey:NSPrintFirstPage];
[dict setObject:[NSNumber numberWithInt:end] forKey:NSPrintLastPage];
NSURL* jobSavingURL = nullptr;
if (!mToFileName.IsEmpty()) {
@ -359,11 +367,11 @@ void nsPrintSettingsX::SetFromPrintInfo(NSPrintInfo* aPrintInfo, bool aAdoptPrin
nsCocoaUtils::GetStringForNSString([aPrintInfo jobDisposition], mDisposition);
mNumCopies = [[dict objectForKey:NSPrintCopies] intValue];
mPrintRange = [[dict objectForKey:NSPrintAllPages] boolValue]
? nsIPrintSettings::kRangeAllPages
: nsIPrintSettings::kRangeSpecifiedPageRange;
mStartPageNum = [[dict objectForKey:NSPrintFirstPage] intValue];
mEndPageNum = [[dict objectForKey:NSPrintLastPage] intValue];
mPageRanges.Clear();
if (![[dict objectForKey:NSPrintAllPages] boolValue]) {
mPageRanges.AppendElement([[dict objectForKey:NSPrintFirstPage] intValue]);
mPageRanges.AppendElement([[dict objectForKey:NSPrintLastPage] intValue]);
}
NSDictionary* printSettings = [aPrintInfo printSettings];
NSNumber* value = [printSettings objectForKey:@"com_apple_print_PrintSettings_PMDuplexing"];

View File

@ -48,7 +48,7 @@ nsPrintSettingsGTK::nsPrintSettingsGTK()
}
already_AddRefed<nsIPrintSettings> CreatePlatformPrintSettings(
const PrintSettingsInitializer& aSettings) {
const mozilla::PrintSettingsInitializer& aSettings) {
RefPtr<nsPrintSettings> settings = new nsPrintSettingsGTK();
settings->InitWithInitializer(aSettings);
settings->SetDefaultFileName();
@ -204,91 +204,26 @@ NS_IMETHODIMP nsPrintSettingsGTK::GetOutputFormat(int16_t* aOutputFormat) {
* from the GTK objects rather than our own variables.
*/
NS_IMETHODIMP nsPrintSettingsGTK::GetPrintRange(int16_t* aPrintRange) {
NS_ENSURE_ARG_POINTER(aPrintRange);
GtkPrintPages gtkRange = gtk_print_settings_get_print_pages(mPrintSettings);
if (gtkRange == GTK_PRINT_PAGES_RANGES)
*aPrintRange = kRangeSpecifiedPageRange;
else
*aPrintRange = kRangeAllPages;
return NS_OK;
}
NS_IMETHODIMP nsPrintSettingsGTK::SetPrintRange(int16_t aPrintRange) {
if (aPrintRange == kRangeSpecifiedPageRange)
gtk_print_settings_set_print_pages(mPrintSettings, GTK_PRINT_PAGES_RANGES);
else
gtk_print_settings_set_print_pages(mPrintSettings, GTK_PRINT_PAGES_ALL);
return NS_OK;
}
NS_IMETHODIMP
nsPrintSettingsGTK::GetStartPageRange(int32_t* aStartPageRange) {
gint ctRanges;
GtkPageRange* lstRanges =
gtk_print_settings_get_page_ranges(mPrintSettings, &ctRanges);
// Make sure we got a range.
if (ctRanges < 1) {
*aStartPageRange = 1;
} else {
// GTK supports multiple page ranges; gecko only supports 1. So find
// the lowest start page.
int32_t start(lstRanges[0].start);
for (gint ii = 1; ii < ctRanges; ii++) {
start = std::min(lstRanges[ii].start, start);
}
*aStartPageRange = start + 1;
nsPrintSettingsGTK::SetPageRanges(const nsTArray<int32_t>& aRanges) {
if (aRanges.Length() % 2 != 0) {
return NS_ERROR_FAILURE;
}
g_free(lstRanges);
return NS_OK;
}
NS_IMETHODIMP
nsPrintSettingsGTK::SetStartPageRange(int32_t aStartPageRange) {
int32_t endRange;
GetEndPageRange(&endRange);
gtk_print_settings_set_print_pages(
mPrintSettings,
aRanges.IsEmpty() ? GTK_PRINT_PAGES_ALL : GTK_PRINT_PAGES_RANGES);
GtkPageRange gtkRange;
gtkRange.start = aStartPageRange - 1;
gtkRange.end = endRange - 1;
gtk_print_settings_set_page_ranges(mPrintSettings, &gtkRange, 1);
return NS_OK;
}
NS_IMETHODIMP
nsPrintSettingsGTK::GetEndPageRange(int32_t* aEndPageRange) {
gint ctRanges;
GtkPageRange* lstRanges =
gtk_print_settings_get_page_ranges(mPrintSettings, &ctRanges);
if (ctRanges < 1) {
*aEndPageRange = 1;
} else {
int32_t end(lstRanges[0].end);
for (gint ii = 1; ii < ctRanges; ii++) {
end = std::max(lstRanges[ii].end, end);
}
*aEndPageRange = end + 1;
nsTArray<GtkPageRange> ranges;
ranges.SetCapacity(aRanges.Length() / 2);
for (size_t i = 0; i < aRanges.Length(); i += 2) {
GtkPageRange* gtkRange = ranges.AppendElement();
gtkRange->start = aRanges[i] - 1;
gtkRange->end = aRanges[i + 1] - 1;
}
g_free(lstRanges);
return NS_OK;
}
NS_IMETHODIMP
nsPrintSettingsGTK::SetEndPageRange(int32_t aEndPageRange) {
int32_t startRange;
GetStartPageRange(&startRange);
GtkPageRange gtkRange;
gtkRange.start = startRange - 1;
gtkRange.end = aEndPageRange - 1;
gtk_print_settings_set_page_ranges(mPrintSettings, &gtkRange, 1);
gtk_print_settings_set_page_ranges(mPrintSettings, ranges.Elements(),
ranges.Length());
return NS_OK;
}
@ -406,7 +341,7 @@ nsPrintSettingsGTK::GetPrinterName(nsAString& aPrinter) {
return NS_OK;
}
}
CopyUTF8toUTF16(MakeStringSpan(gtkPrintName), aPrinter);
CopyUTF8toUTF16(mozilla::MakeStringSpan(gtkPrintName), aPrinter);
return NS_OK;
}
@ -668,17 +603,21 @@ nsPrintSettingsGTK::SetupSilentPrinting() {
NS_IMETHODIMP
nsPrintSettingsGTK::GetPageRanges(nsTArray<int32_t>& aPages) {
GtkPrintPages gtkRange = gtk_print_settings_get_print_pages(mPrintSettings);
if (gtkRange != GTK_PRINT_PAGES_RANGES) {
aPages.Clear();
return NS_OK;
}
gint ctRanges;
GtkPageRange* lstRanges =
gtk_print_settings_get_page_ranges(mPrintSettings, &ctRanges);
aPages.Clear();
if (ctRanges > 1) {
for (gint i = 0; i < ctRanges; i++) {
aPages.AppendElement(lstRanges[i].start + 1);
aPages.AppendElement(lstRanges[i].end + 1);
}
for (gint i = 0; i < ctRanges; i++) {
aPages.AppendElement(lstRanges[i].start + 1);
aPages.AppendElement(lstRanges[i].end + 1);
}
g_free(lstRanges);

View File

@ -46,16 +46,6 @@ class nsPrintSettingsGTK : public nsPrintSettings {
GtkPrinter* GetGtkPrinter() { return mGTKPrinter; };
void SetGtkPrinter(GtkPrinter* aPrinter);
// If not printing the selection, this is stored in the GtkPrintSettings.
NS_IMETHOD GetPrintRange(int16_t* aPrintRange) override;
NS_IMETHOD SetPrintRange(int16_t aPrintRange) override;
// The page range is stored as as single range in the GtkPrintSettings object.
NS_IMETHOD GetStartPageRange(int32_t* aStartPageRange) override;
NS_IMETHOD SetStartPageRange(int32_t aStartPageRange) override;
NS_IMETHOD GetEndPageRange(int32_t* aEndPageRange) override;
NS_IMETHOD SetEndPageRange(int32_t aEndPageRange) override;
// Reversed, color, orientation and file name are all stored in the
// GtkPrintSettings. Orientation is also stored in the GtkPageSetup and its
// setting takes priority when getting the orientation.
@ -109,7 +99,8 @@ class nsPrintSettingsGTK : public nsPrintSettings {
NS_IMETHOD SetupSilentPrinting() override;
NS_IMETHOD GetPageRanges(nsTArray<int32_t>& aPages) override;
NS_IMETHOD SetPageRanges(const nsTArray<int32_t>&) override;
NS_IMETHOD GetPageRanges(nsTArray<int32_t>&) override;
NS_IMETHOD GetResolution(int32_t* aResolution) override;
NS_IMETHOD SetResolution(int32_t aResolution) override;

View File

@ -16,7 +16,6 @@
*/
native nsNativeIntMargin(nsIntMargin);
[ref] native nsNativeIntMarginRef(nsIntMargin);
[ref] native IntegerArray(nsTArray<int32_t>);
interface nsIPrintSession;
@ -62,10 +61,6 @@ interface nsIPrintSettings : nsISupports
const unsigned long kInitSaveAll = 0xFFFFFFFF;
/* Print Range Enums */
const long kRangeAllPages = 0;
const long kRangeSpecifiedPageRange = 1;
/* Justification Enums */
const long kJustLeft = 0;
const long kJustCenter = 1;
@ -118,9 +113,6 @@ interface nsIPrintSettings : nsISupports
*/
[noscript] attribute nsIPrintSession printSession; /* We hold a weak reference */
attribute long startPageRange;
attribute long endPageRange;
/**
* The edge measurements define the positioning of the headers
* and footers on the page. They're treated as an offset from the edges of
@ -167,8 +159,6 @@ interface nsIPrintSettings : nsISupports
/** Whether to only print the selected nodes */
[infallible] attribute boolean printSelectionOnly;
attribute short printRange;
attribute AString title;
attribute AString docURL;
@ -270,9 +260,13 @@ interface nsIPrintSettings : nsISupports
* ranges (start, end), must not overlap and must be in the
* (startPageRange, endPageRange) scope.
*
* If there are no print ranges the aPages array is cleared.
* If there are no print ranges the aPages array is empty.
*/
[noscript] void GetPageRanges(in IntegerArray aPages);
attribute Array<long> pageRanges;
%{C++
static bool IsPageSkipped(int32_t aPageNum, const nsTArray<int32_t>& aRanges);
%}
};
%{ C++

View File

@ -5,6 +5,7 @@
#include "nsPrintSettingsImpl.h"
#include "prenv.h"
#include "nsCoord.h"
#include "nsPaper.h"
#include "nsReadableUtils.h"
@ -16,10 +17,7 @@
NS_IMPL_ISUPPORTS(nsPrintSettings, nsIPrintSettings)
nsPrintSettings::nsPrintSettings()
: mPrintRange(kRangeAllPages),
mStartPageNum(1),
mEndPageNum(1),
mScaling(1.0),
: mScaling(1.0),
mPrintBGColors(false),
mPrintBGImages(false),
mIsCancelled(false),
@ -103,6 +101,7 @@ NS_IMETHODIMP nsPrintSettings::GetPrintSession(
NS_ADDREF(*aPrintSession);
return NS_OK;
}
NS_IMETHODIMP nsPrintSettings::SetPrintSession(nsIPrintSession* aPrintSession) {
// Clearing it by passing nullptr is not allowed. That's why we
// use a weak ref so that it doesn't have to be cleared.
@ -118,28 +117,7 @@ NS_IMETHODIMP nsPrintSettings::SetPrintSession(nsIPrintSession* aPrintSession) {
return NS_OK;
}
NS_IMETHODIMP nsPrintSettings::GetStartPageRange(int32_t* aStartPageRange) {
// NS_ENSURE_ARG_POINTER(aStartPageRange);
*aStartPageRange = mStartPageNum;
return NS_OK;
}
NS_IMETHODIMP nsPrintSettings::SetStartPageRange(int32_t aStartPageRange) {
mStartPageNum = aStartPageRange;
return NS_OK;
}
NS_IMETHODIMP nsPrintSettings::GetEndPageRange(int32_t* aEndPageRange) {
// NS_ENSURE_ARG_POINTER(aEndPageRange);
*aEndPageRange = mEndPageNum;
return NS_OK;
}
NS_IMETHODIMP nsPrintSettings::SetEndPageRange(int32_t aEndPageRange) {
mEndPageNum = aEndPageRange;
return NS_OK;
}
NS_IMETHODIMP nsPrintSettings::GetPrintReversed(bool* aPrintReversed) {
// NS_ENSURE_ARG_POINTER(aPrintReversed);
*aPrintReversed = mPrintReversed;
return NS_OK;
}
@ -149,7 +127,6 @@ NS_IMETHODIMP nsPrintSettings::SetPrintReversed(bool aPrintReversed) {
}
NS_IMETHODIMP nsPrintSettings::GetPrintInColor(bool* aPrintInColor) {
// NS_ENSURE_ARG_POINTER(aPrintInColor);
*aPrintInColor = mPrintInColor;
return NS_OK;
}
@ -159,7 +136,6 @@ NS_IMETHODIMP nsPrintSettings::SetPrintInColor(bool aPrintInColor) {
}
NS_IMETHODIMP nsPrintSettings::GetOrientation(int32_t* aOrientation) {
NS_ENSURE_ARG_POINTER(aOrientation);
*aOrientation = mOrientation;
return NS_OK;
}
@ -453,16 +429,6 @@ NS_IMETHODIMP nsPrintSettings::SetPrintBGImages(bool aPrintBGImages) {
return NS_OK;
}
NS_IMETHODIMP nsPrintSettings::GetPrintRange(int16_t* aPrintRange) {
NS_ENSURE_ARG_POINTER(aPrintRange);
*aPrintRange = mPrintRange;
return NS_OK;
}
NS_IMETHODIMP nsPrintSettings::SetPrintRange(int16_t aPrintRange) {
mPrintRange = aPrintRange;
return NS_OK;
}
NS_IMETHODIMP nsPrintSettings::GetTitle(nsAString& aTitle) {
aTitle = mTitle;
return NS_OK;
@ -732,11 +698,37 @@ nsPrintSettings::GetEffectivePageSize(double* aWidth, double* aHeight) {
}
NS_IMETHODIMP
nsPrintSettings::GetPageRanges(nsTArray<int32_t>& aPages) {
aPages.Clear();
nsPrintSettings::SetPageRanges(const nsTArray<int32_t>& aPages) {
// Needs to be a set of (start, end) pairs.
if (aPages.Length() % 2 != 0) {
return NS_ERROR_FAILURE;
}
mPageRanges = aPages.Clone();
return NS_OK;
}
NS_IMETHODIMP
nsPrintSettings::GetPageRanges(nsTArray<int32_t>& aPages) {
aPages = mPageRanges.Clone();
return NS_OK;
}
bool nsIPrintSettings::IsPageSkipped(int32_t aPageNum,
const nsTArray<int32_t>& aRanges) {
MOZ_RELEASE_ASSERT(aRanges.Length() % 2 == 0);
if (aRanges.IsEmpty()) {
return false;
}
for (size_t i = 0; i < aRanges.Length(); i += 2) {
if (aRanges[i] <= aPageNum && aPageNum <= aRanges[i + 1]) {
// The page is included in this piece of the custom range,
// so it's not skipped.
return false;
}
}
return true;
}
nsresult nsPrintSettings::_Clone(nsIPrintSettings** _retval) {
RefPtr<nsPrintSettings> printSettings = new nsPrintSettings(*this);
printSettings.forget(_retval);
@ -767,15 +759,13 @@ nsPrintSettings& nsPrintSettings::operator=(const nsPrintSettings& rhs) {
return *this;
}
mStartPageNum = rhs.mStartPageNum;
mEndPageNum = rhs.mEndPageNum;
mPageRanges = rhs.mPageRanges.Clone();
mMargin = rhs.mMargin;
mEdge = rhs.mEdge;
mUnwriteableMargin = rhs.mUnwriteableMargin;
mScaling = rhs.mScaling;
mPrintBGColors = rhs.mPrintBGColors;
mPrintBGImages = rhs.mPrintBGImages;
mPrintRange = rhs.mPrintRange;
mTitle = rhs.mTitle;
mURL = rhs.mURL;
mIsCancelled = rhs.mIsCancelled;

View File

@ -78,10 +78,8 @@ class nsPrintSettings : public nsIPrintSettings {
nsIntMargin mEdge;
nsIntMargin mUnwriteableMargin;
// scriptable data members
int16_t mPrintRange;
int32_t mStartPageNum; // only used for ePrintRange_SpecifiedRange
int32_t mEndPageNum;
nsTArray<int32_t> mPageRanges;
double mScaling;
bool mPrintBGColors; // print background colors
bool mPrintBGImages; // print background images

View File

@ -91,8 +91,7 @@ nsPrintSettingsService::SerializeToPrintData(nsIPrintSettings* aSettings,
data->remotePrintJobChild() = session->GetRemotePrintJob();
}
aSettings->GetStartPageRange(&data->startPageRange());
aSettings->GetEndPageRange(&data->endPageRange());
aSettings->GetPageRanges(data->pageRanges());
aSettings->GetEdgeTop(&data->edgeTop());
aSettings->GetEdgeLeft(&data->edgeLeft());
@ -118,8 +117,6 @@ nsPrintSettingsService::SerializeToPrintData(nsIPrintSettings* aSettings,
data->isPrintSelectionRBEnabled() = aSettings->GetIsPrintSelectionRBEnabled();
data->printSelectionOnly() = aSettings->GetPrintSelectionOnly();
aSettings->GetPrintRange(&data->printRange());
aSettings->GetTitle(data->title());
aSettings->GetDocURL(data->docURL());
@ -180,8 +177,8 @@ nsPrintSettingsService::DeserializeToPrintSettings(const PrintData& data,
session->SetRemotePrintJob(
static_cast<RemotePrintJobChild*>(data.remotePrintJobChild()));
}
settings->SetStartPageRange(data.startPageRange());
settings->SetEndPageRange(data.endPageRange());
settings->SetPageRanges(data.pageRanges());
settings->SetEdgeTop(data.edgeTop());
settings->SetEdgeLeft(data.edgeLeft());
@ -205,7 +202,6 @@ nsPrintSettingsService::DeserializeToPrintSettings(const PrintData& data,
settings->SetShowMarginGuides(data.showMarginGuides());
settings->SetIsPrintSelectionRBEnabled(data.isPrintSelectionRBEnabled());
settings->SetPrintSelectionOnly(data.printSelectionOnly());
settings->SetPrintRange(data.printRange());
settings->SetTitle(data.title());
settings->SetDocURL(data.docURL());

View File

@ -219,19 +219,24 @@ static nsresult ShowNativePrintDialog(HWND aHWnd,
prntdlg.Flags |= PD_NOSELECTION;
}
int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
aPrintSettings->GetPrintRange(&printRangeType);
// if there is a specified page range then enable the "Custom" radio button
if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) {
nsTArray<int32_t> pageRanges;
aPrintSettings->GetPageRanges(pageRanges);
// If there is a specified page range then enable the "Custom" radio button
if (!pageRanges.IsEmpty()) {
prntdlg.Flags |= PD_PAGENUMS;
}
int32_t pg = 1;
aPrintSettings->GetStartPageRange(&pg);
prntdlg.nFromPage = pg;
// TODO(emilio): Can we represent all the page ranges instead?
int32_t start = 1;
int32_t end = 1;
for (size_t i = 0; i < pageRanges.Length(); i += 2) {
start = std::min(start, pageRanges[i]);
end = std::max(end, pageRanges[i + 1]);
}
aPrintSettings->GetEndPageRange(&pg);
prntdlg.nToPage = pg;
prntdlg.nFromPage = start;
prntdlg.nToPage = end;
prntdlg.nMinPage = 1;
prntdlg.nMaxPage = 0xFFFF;
@ -303,13 +308,14 @@ static nsresult ShowNativePrintDialog(HWND aHWnd,
aPrintSettings->SetPrinterName(nsDependentString(device));
aPrintSettings->SetPrintSelectionOnly(prntdlg.Flags & PD_SELECTION);
nsTArray<int32_t> pageRanges;
if (prntdlg.Flags & PD_PAGENUMS) {
aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSpecifiedPageRange);
aPrintSettings->SetStartPageRange(prntdlg.nFromPage);
aPrintSettings->SetEndPageRange(prntdlg.nToPage);
} else { // (prntdlg.Flags & PD_ALLPAGES)
aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages);
pageRanges.AppendElement(prntdlg.nFromPage);
pageRanges.AppendElement(prntdlg.nToPage);
} else {
// (prntdlg.Flags & PD_ALLPAGES)
}
aPrintSettings->SetPageRanges(pageRanges);
// Unlock DeviceNames
::GlobalUnlock(prntdlg.hDevNames);