Title: [108080] trunk/Source/WebKit2
Revision
108080
Author
[email protected]
Date
2012-02-17 08:42:58 -0800 (Fri, 17 Feb 2012)

Log Message

[GTK] Allow printing multiple pages per sheet in WebKit2 for printers that don't support it
https://bugs.webkit.org/show_bug.cgi?id=78715

Reviewed by Gustavo Noronha Silva.

* UIProcess/API/gtk/WebKitPrintOperation.cpp:
(webkitPrintOperationRunDialogUnix): Enable multiple pages per
sheet options in print dialog.
* WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp:
(WebKit::PrintPagesData::PrintPagesData): Initialize sheetNumber
and numberOfSheets. Move pagePosition to WebPrintOperationGtk.
(WebKit::PrintPagesData::incrementPageSequence): Increment current
sheet and page position.
(WebKit::WebPrintOperationGtk::WebPrintOperationGtk):
(WebKit::WebPrintOperationGtk::currentPageIsFirstPageOfSheet):
Helper function to check whether current pages is the first one of
the current sheet.
(WebKit::WebPrintOperationGtk::currentPageIsLastPageOfSheet):
Helper function to check whether current pages is the last one of
the current sheet.
(WebKit::WebPrintOperationGtk::getRowsAndColumnsOfPagesPerSheet):
Returns the number of rows and columns of pages per sheet.
(WebKit::WebPrintOperationGtk::getPositionOfPageInSheet): Returns
the row and column number of the current page in the current sheet.
(WebKit::WebPrintOperationGtk::prepareContextToDraw): Translate,
scale and rotate accordingly to render every page in the right
place of the sheet.
(WebKit::WebPrintOperationGtk::renderPage): Call
prepareContextToDraw() before drawing the page.
* WebProcess/WebPage/gtk/WebPrintOperationGtk.h:
(WebKit::WebPrintOperationGtk::setNumberOfPagesToPrint):
(WebKit::WebPrintOperationGtk::pagePosition):
(WebKit::WebPrintOperationGtk::setPagePosition):
(WebKit::WebPrintOperationGtk::numberUp):
(WebKit::WebPrintOperationGtk::numberUpLayout):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (108079 => 108080)


--- trunk/Source/WebKit2/ChangeLog	2012-02-17 16:40:42 UTC (rev 108079)
+++ trunk/Source/WebKit2/ChangeLog	2012-02-17 16:42:58 UTC (rev 108080)
@@ -1,5 +1,43 @@
 2012-02-17  Carlos Garcia Campos  <[email protected]>
 
+        [GTK] Allow printing multiple pages per sheet in WebKit2 for printers that don't support it
+        https://bugs.webkit.org/show_bug.cgi?id=78715
+
+        Reviewed by Gustavo Noronha Silva.
+
+        * UIProcess/API/gtk/WebKitPrintOperation.cpp:
+        (webkitPrintOperationRunDialogUnix): Enable multiple pages per
+        sheet options in print dialog.
+        * WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp:
+        (WebKit::PrintPagesData::PrintPagesData): Initialize sheetNumber
+        and numberOfSheets. Move pagePosition to WebPrintOperationGtk.
+        (WebKit::PrintPagesData::incrementPageSequence): Increment current
+        sheet and page position.
+        (WebKit::WebPrintOperationGtk::WebPrintOperationGtk):
+        (WebKit::WebPrintOperationGtk::currentPageIsFirstPageOfSheet):
+        Helper function to check whether current pages is the first one of
+        the current sheet.
+        (WebKit::WebPrintOperationGtk::currentPageIsLastPageOfSheet):
+        Helper function to check whether current pages is the last one of
+        the current sheet.
+        (WebKit::WebPrintOperationGtk::getRowsAndColumnsOfPagesPerSheet):
+        Returns the number of rows and columns of pages per sheet.
+        (WebKit::WebPrintOperationGtk::getPositionOfPageInSheet): Returns
+        the row and column number of the current page in the current sheet.
+        (WebKit::WebPrintOperationGtk::prepareContextToDraw): Translate,
+        scale and rotate accordingly to render every page in the right
+        place of the sheet.
+        (WebKit::WebPrintOperationGtk::renderPage): Call
+        prepareContextToDraw() before drawing the page.
+        * WebProcess/WebPage/gtk/WebPrintOperationGtk.h:
+        (WebKit::WebPrintOperationGtk::setNumberOfPagesToPrint):
+        (WebKit::WebPrintOperationGtk::pagePosition):
+        (WebKit::WebPrintOperationGtk::setPagePosition):
+        (WebKit::WebPrintOperationGtk::numberUp):
+        (WebKit::WebPrintOperationGtk::numberUpLayout):
+
+2012-02-17  Carlos Garcia Campos  <[email protected]>
+
         [GTK] Rename WebKitPrintOperation::done signal to ::finished in WebKit2
         https://bugs.webkit.org/show_bug.cgi?id=78893
 

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp (108079 => 108080)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp	2012-02-17 16:40:42 UTC (rev 108079)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp	2012-02-17 16:42:58 UTC (rev 108080)
@@ -200,7 +200,8 @@
 static WebKitPrintOperationResponse webkitPrintOperationRunDialogUnix(WebKitPrintOperation* printOperation, GtkWindow* parent)
 {
     GtkPrintUnixDialog* printDialog = GTK_PRINT_UNIX_DIALOG(gtk_print_unix_dialog_new(0, parent));
-    gtk_print_unix_dialog_set_manual_capabilities(printDialog, static_cast<GtkPrintCapabilities>(0));
+    gtk_print_unix_dialog_set_manual_capabilities(printDialog, static_cast<GtkPrintCapabilities>(GTK_PRINT_CAPABILITY_NUMBER_UP
+                                                                                                 | GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT));
 
     WebKitPrintOperationPrivate* priv = printOperation->priv;
     if (priv->printSettings)

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;
 };
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to