Modified: trunk/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp (108079 => 108080)
--- trunk/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp 2012-02-17 16:40:42 UTC (rev 108079)
+++ trunk/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp 2012-02-17 16:42:58 UTC (rev 108080)
@@ -88,6 +88,10 @@
printOperation->m_pagesToPrint = gtk_print_job_get_pages(printOperation->m_printJob.get());
printOperation->m_needsRotation = gtk_print_job_get_rotate(printOperation->m_printJob.get());
+ // Manual capabilities.
+ printOperation->m_numberUp = gtk_print_job_get_n_up(printOperation->m_printJob.get());
+ printOperation->m_numberUpLayout = gtk_print_job_get_n_up_layout(printOperation->m_printJob.get());
+
printOperation->print(surface, 72, 72);
}
@@ -101,6 +105,9 @@
void startPage(cairo_t* cr)
{
+ if (!currentPageIsFirstPageOfSheet())
+ return;
+
GtkPaperSize* paperSize = gtk_page_setup_get_paper_size(m_pageSetup.get());
double width = gtk_paper_size_get_width(paperSize, GTK_UNIT_POINTS);
double height = gtk_paper_size_get_height(paperSize, GTK_UNIT_POINTS);
@@ -127,7 +134,8 @@
void endPage(cairo_t* cr)
{
- cairo_show_page(cr);
+ if (currentPageIsLastPageOfSheet())
+ cairo_show_page(cr);
}
static void printJobComplete(GtkPrintJob* printJob, WebPrintOperationGtkUnix* printOperation, const GError*)
@@ -190,7 +198,8 @@
: printOperation(printOperation)
, totalPrinted(-1)
, pageNumber(0)
- , pagePosition(0)
+ , sheetNumber(0)
+ , numberOfSheets(0)
, isDone(false)
{
if (printOperation->pagesToPrint() == GTK_PRINT_PAGES_RANGES) {
@@ -221,8 +230,15 @@
for (int i = 0; i < printOperation->pageCount(); ++i)
pages.append(i);
}
+ printOperation->setNumberOfPagesToPrint(pages.size());
- pageNumber = pages[pagePosition];
+ size_t numberUp = printOperation->numberUp();
+ if (numberUp > 1)
+ numberOfSheets = (pages.size() % numberUp) ? pages.size() / numberUp + 1 : pages.size() / numberUp;
+ else
+ numberOfSheets = pages.size();
+
+ pageNumber = pages[printOperation->pagePosition()];
}
void incrementPageSequence()
@@ -232,8 +248,15 @@
return;
}
- pagePosition++;
- if (pagePosition >= pages.size()) {
+ size_t pagePosition = printOperation->pagePosition();
+ if (printOperation->currentPageIsLastPageOfSheet()) {
+ sheetNumber++;
+ pagePosition = sheetNumber * printOperation->numberUp();
+ } else
+ pagePosition++;
+ printOperation->setPagePosition(pagePosition);
+
+ if (pagePosition >= pages.size() || sheetNumber >= numberOfSheets) {
isDone = true;
return;
}
@@ -246,8 +269,9 @@
int totalPrinted;
size_t totalToPrint;
int pageNumber;
- size_t pagePosition;
Vector<size_t> pages;
+ size_t sheetNumber;
+ size_t numberOfSheets;
bool isDone : 1;
};
@@ -271,10 +295,14 @@
, m_xDPI(1)
, m_yDPI(1)
, m_printPagesIdleId(0)
+ , m_numberOfPagesToPrint(0)
, m_pagesToPrint(GTK_PRINT_PAGES_ALL)
+ , m_pagePosition(0)
, m_pageRanges(0)
, m_pageRangesCount(0)
, m_needsRotation(false)
+ , m_numberUp(1)
+ , m_numberUpLayout(0)
{
}
@@ -289,6 +317,16 @@
return m_printContext ? m_printContext->pageCount() : 0;
}
+bool WebPrintOperationGtk::currentPageIsFirstPageOfSheet() const
+{
+ return (m_numberUp < 2 || !((m_pagePosition) % m_numberUp));
+}
+
+bool WebPrintOperationGtk::currentPageIsLastPageOfSheet() const
+{
+ return (m_numberUp < 2 || !((m_pagePosition + 1) % m_numberUp) || m_pagePosition == m_numberOfPagesToPrint - 1);
+}
+
void WebPrintOperationGtk::rotatePage()
{
GtkPaperSize* paperSize = gtk_page_setup_get_paper_size(m_pageSetup.get());
@@ -318,6 +356,169 @@
}
}
+void WebPrintOperationGtk::getRowsAndColumnsOfPagesPerSheet(size_t& rows, size_t& columns)
+{
+ switch (m_numberUp) {
+ default:
+ columns = 1;
+ rows = 1;
+ break;
+ case 2:
+ columns = 2;
+ rows = 1;
+ break;
+ case 4:
+ columns = 2;
+ rows = 2;
+ break;
+ case 6:
+ columns = 3;
+ rows = 2;
+ break;
+ case 9:
+ columns = 3;
+ rows = 3;
+ break;
+ case 16:
+ columns = 4;
+ rows = 4;
+ break;
+ }
+}
+
+void WebPrintOperationGtk::getPositionOfPageInSheet(size_t rows, size_t columns, int& x, int&y)
+{
+ switch (m_numberUpLayout) {
+ case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
+ x = m_pagePosition % columns;
+ y = (m_pagePosition / columns) % rows;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
+ x = m_pagePosition % columns;
+ y = rows - 1 - (m_pagePosition / columns) % rows;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
+ x = columns - 1 - m_pagePosition % columns;
+ y = (m_pagePosition / columns) % rows;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
+ x = columns - 1 - m_pagePosition % columns;
+ y = rows - 1 - (m_pagePosition / columns) % rows;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
+ x = (m_pagePosition / rows) % columns;
+ y = m_pagePosition % rows;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
+ x = columns - 1 - (m_pagePosition / rows) % columns;
+ y = m_pagePosition % rows;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
+ x = (m_pagePosition / rows) % columns;
+ y = rows - 1 - m_pagePosition % rows;
+ break;
+ case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
+ x = columns - 1 - (m_pagePosition / rows) % columns;
+ y = rows - 1 - m_pagePosition % rows;
+ break;
+ }
+}
+
+void WebPrintOperationGtk::prepareContextToDraw()
+{
+ if (m_numberUp < 2) {
+ double left = gtk_page_setup_get_left_margin(m_pageSetup.get(), GTK_UNIT_INCH);
+ double top = gtk_page_setup_get_top_margin(m_pageSetup.get(), GTK_UNIT_INCH);
+ cairo_translate(m_cairoContext.get(), left * m_xDPI, top * m_yDPI);
+
+ return;
+ }
+
+ // Multiple pages per sheet.
+ double marginLeft = gtk_page_setup_get_left_margin(m_pageSetup.get(), GTK_UNIT_POINTS);
+ double marginRight = gtk_page_setup_get_right_margin(m_pageSetup.get(), GTK_UNIT_POINTS);
+ double marginTop = gtk_page_setup_get_top_margin(m_pageSetup.get(), GTK_UNIT_POINTS);
+ double marginBottom = gtk_page_setup_get_bottom_margin(m_pageSetup.get(), GTK_UNIT_POINTS);
+
+ double paperWidth = gtk_page_setup_get_paper_width(m_pageSetup.get(), GTK_UNIT_POINTS);
+ double paperHeight = gtk_page_setup_get_paper_height(m_pageSetup.get(), GTK_UNIT_POINTS);
+
+ size_t rows, columns;
+ getRowsAndColumnsOfPagesPerSheet(rows, columns);
+
+ GtkPageOrientation orientation = gtk_page_setup_get_orientation(m_pageSetup.get());
+ double pageWidth = 0, pageHeight = 0;
+ switch (orientation) {
+ case GTK_PAGE_ORIENTATION_PORTRAIT:
+ case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+ pageWidth = paperWidth - (marginLeft + marginRight);
+ pageHeight = paperHeight - (marginTop + marginBottom);
+ cairo_translate(m_cairoContext.get(), marginLeft, marginTop);
+ break;
+ case GTK_PAGE_ORIENTATION_LANDSCAPE:
+ case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+ pageWidth = paperWidth - (marginTop + marginBottom);
+ pageHeight = paperHeight - (marginLeft + marginRight);
+ cairo_translate(m_cairoContext.get(), marginTop, marginLeft);
+
+ size_t tmp = columns;
+ columns = rows;
+ rows = tmp;
+ break;
+ }
+
+ int x, y;
+ getPositionOfPageInSheet(rows, columns, x, y);
+
+ switch (m_numberUp) {
+ case 4:
+ case 9:
+ case 16: {
+ double scaleX = pageWidth / (columns * paperWidth);
+ double scaleY = pageHeight / (rows * paperHeight);
+ double scale = std::min(scaleX, scaleY);
+
+ double stepX = paperWidth * (scaleX / scale);
+ double stepY = paperHeight * (scaleY / scale);
+
+ double width = gtk_page_setup_get_page_width(m_pageSetup.get(), GTK_UNIT_INCH) * m_xDPI;
+ double height = gtk_page_setup_get_page_height(m_pageSetup.get(), GTK_UNIT_INCH) * m_yDPI;
+
+ double offsetX, offsetY;
+ if (marginLeft + marginRight > 0) {
+ offsetX = marginLeft * (stepX - width) / (marginLeft + marginRight);
+ offsetY = marginTop * (stepY - height) / (marginTop + marginBottom);
+ } else {
+ offsetX = (stepX - width) / 2.0;
+ offsetY = (stepY - height) / 2.0;
+ }
+
+ cairo_scale(m_cairoContext.get(), scale, scale);
+ cairo_translate(m_cairoContext.get(), x * stepX + offsetX, y * stepY + offsetY);
+ break;
+ }
+ case 2:
+ case 6: {
+ double scaleX = pageHeight / (columns * paperWidth);
+ double scaleY = pageWidth / (rows * paperHeight);
+ double scale = std::min(scaleX, scaleY);
+
+ double stepX = paperWidth * (scaleX / scale);
+ double stepY = paperHeight * (scaleY / scale);
+
+ double offsetX = ((stepX - paperWidth) / 2.0 * columns) - marginRight;
+ double offsetY = ((stepY - paperHeight) / 2.0 * rows) + marginTop;
+
+ cairo_scale(m_cairoContext.get(), scale, scale);
+ cairo_translate(m_cairoContext.get(), y * paperHeight + offsetY, (columns - x) * paperWidth + offsetX);
+ cairo_rotate(m_cairoContext.get(), -G_PI / 2);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
void WebPrintOperationGtk::renderPage(int pageNumber)
{
startPage(m_cairoContext.get());
@@ -325,11 +526,8 @@
if (m_needsRotation)
rotatePage();
+ prepareContextToDraw();
- double left = gtk_page_setup_get_left_margin(m_pageSetup.get(), GTK_UNIT_INCH);
- double top = gtk_page_setup_get_top_margin(m_pageSetup.get(), GTK_UNIT_INCH);
- cairo_translate(m_cairoContext.get(), left * m_xDPI, top * m_yDPI);
-
double pageWidth = gtk_page_setup_get_page_width(m_pageSetup.get(), GTK_UNIT_INCH) * m_xDPI;
WebCore::PlatformContextCairo platformContext(m_cairoContext.get());
WebCore::GraphicsContext graphicsContext(&platformContext);
Modified: trunk/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h (108079 => 108080)
--- trunk/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h 2012-02-17 16:40:42 UTC (rev 108079)
+++ trunk/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h 2012-02-17 16:42:58 UTC (rev 108080)
@@ -51,11 +51,19 @@
GtkPrintSettings* printSettings() const { return m_printSettings.get(); }
GtkPageSetup* pageSetup() const { return m_pageSetup.get(); }
+ void setNumberOfPagesToPrint(size_t numberOfPages) { m_numberOfPagesToPrint = numberOfPages; }
unsigned int pagesToPrint() const { return m_pagesToPrint; }
int pageCount() const;
+ bool currentPageIsFirstPageOfSheet() const;
+ bool currentPageIsLastPageOfSheet() const;
+ size_t pagePosition() const { return m_pagePosition; }
+ void setPagePosition(size_t position) { m_pagePosition = position; }
GtkPageRange* pageRanges() const { return m_pageRanges; }
size_t pageRangesCount() const { return m_pageRangesCount; }
+ unsigned int numberUp() const { return m_numberUp; }
+ unsigned int numberUpLayout() const { return m_numberUpLayout; }
+
virtual void startPrint(WebCore::PrintContext*, uint64_t callbackID) = 0;
protected:
@@ -71,6 +79,9 @@
void print(cairo_surface_t*, double xDPI, double yDPI);
void renderPage(int pageNumber);
void rotatePage();
+ void getRowsAndColumnsOfPagesPerSheet(size_t& rows, size_t& columns);
+ void getPositionOfPageInSheet(size_t rows, size_t columns, int& x, int&y);
+ void prepareContextToDraw();
void printDone();
WebPage* m_webPage;
@@ -83,10 +94,16 @@
double m_yDPI;
unsigned int m_printPagesIdleId;
+ size_t m_numberOfPagesToPrint;
unsigned int m_pagesToPrint;
+ size_t m_pagePosition;
GtkPageRange* m_pageRanges;
size_t m_pageRangesCount;
bool m_needsRotation;
+
+ // Manual capabilities.
+ unsigned int m_numberUp;
+ unsigned int m_numberUpLayout;
};
}