Title: [97155] trunk/Source/WebKit2
Revision
97155
Author
[email protected]
Date
2011-10-11 09:41:11 -0700 (Tue, 11 Oct 2011)

Log Message

        [Mac] Should be able to display multi-page PDFs in subframes
        https://bugs.webkit.org/show_bug.cgi?id=69804

        Reviewed by Anders Carlsson.

        * WebProcess/Plugins/PDF/BuiltInPDFView.h:
        * WebProcess/Plugins/PDF/BuiltInPDFView.cpp:
        (WebKit::BuiltInPDFView::updateScrollbars): Page step should be exactly one page, so that
        one could step over the document page by page. It certainly shouldn't be a portion of the
        whole document.
        (WebKit::BuiltInPDFView::pdfDocumentDidLoad): Moved duplicated code from load callbacks here.
        (WebKit::BuiltInPDFView::calculateSizes): Calculate document size including gutters, and
        remember page boxes.
        (WebKit::BuiltInPDFView::paint): Split into separate functions.
        (WebKit::BuiltInPDFView::paintBackground): Just paint gray background for the whole dirty rect.
        (WebKit::BuiltInPDFView::paintContent): Paint pages and shadow under them. This code is still
        fairly naive, as it doesn't understand annotations or page rotation.
        Constants for shadows roughly match PDFView, but not quite, since it draws entirely custom
        shadows.
        (WebKit::BuiltInPDFView::paintControls): Moved scrollbar and scroll corner painting here.
        (WebKit::BuiltInPDFView::streamDidFinishLoading): Moved common code into pdfDocumentDidLoad().
        (WebKit::BuiltInPDFView::manualStreamDidFinishLoading): Ditto.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (97154 => 97155)


--- trunk/Source/WebKit2/ChangeLog	2011-10-11 16:13:11 UTC (rev 97154)
+++ trunk/Source/WebKit2/ChangeLog	2011-10-11 16:41:11 UTC (rev 97155)
@@ -1,3 +1,28 @@
+2011-10-11  Alexey Proskuryakov  <[email protected]>
+
+        [Mac] Should be able to display multi-page PDFs in subframes
+        https://bugs.webkit.org/show_bug.cgi?id=69804
+
+        Reviewed by Anders Carlsson.
+
+        * WebProcess/Plugins/PDF/BuiltInPDFView.h:
+        * WebProcess/Plugins/PDF/BuiltInPDFView.cpp:
+        (WebKit::BuiltInPDFView::updateScrollbars): Page step should be exactly one page, so that
+        one could step over the document page by page. It certainly shouldn't be a portion of the
+        whole document.
+        (WebKit::BuiltInPDFView::pdfDocumentDidLoad): Moved duplicated code from load callbacks here.
+        (WebKit::BuiltInPDFView::calculateSizes): Calculate document size including gutters, and
+        remember page boxes.
+        (WebKit::BuiltInPDFView::paint): Split into separate functions.
+        (WebKit::BuiltInPDFView::paintBackground): Just paint gray background for the whole dirty rect.
+        (WebKit::BuiltInPDFView::paintContent): Paint pages and shadow under them. This code is still
+        fairly naive, as it doesn't understand annotations or page rotation.
+        Constants for shadows roughly match PDFView, but not quite, since it draws entirely custom
+        shadows.
+        (WebKit::BuiltInPDFView::paintControls): Moved scrollbar and scroll corner painting here.
+        (WebKit::BuiltInPDFView::streamDidFinishLoading): Moved common code into pdfDocumentDidLoad().
+        (WebKit::BuiltInPDFView::manualStreamDidFinishLoading): Ditto.
+
 2011-10-11  Gopal Raghavan  <[email protected]>
 
         [Qt] WebProcess using proxy settings for localhost as well

Modified: trunk/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.cpp (97154 => 97155)


--- trunk/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.cpp	2011-10-11 16:13:11 UTC (rev 97154)
+++ trunk/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.cpp	2011-10-11 16:41:11 UTC (rev 97155)
@@ -48,6 +48,11 @@
 
 const uint64_t pdfDocumentRequestID = 1; // PluginController supports loading multiple streams, but we only need one for PDF.
 
+const int gutterHeight = 10;
+const int shadowOffsetX = 0;
+const int shadowOffsetY = -2;
+const int shadowSize = 7;
+
 PassRefPtr<BuiltInPDFView> BuiltInPDFView::create(Page* page)
 {
     return adoptRef(new BuiltInPDFView(page));
@@ -94,18 +99,6 @@
     return static_cast<const PluginView*>(controller());
 }
 
-void BuiltInPDFView::calculateDocumentSize()
-{
-    CGPDFPageRef pdfPage = CGPDFDocumentGetPage(m_pdfDocument.get(), 1); // FIXME: Draw all pages of a document.
-    if (!pdfPage)
-        return;
-
-    CGRect box = CGPDFPageGetBoxRect(pdfPage, kCGPDFCropBox);
-    if (CGRectIsEmpty(box))
-        box = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);
-    m_pdfDocumentSize = IntSize(box.size);
-}
-
 void BuiltInPDFView::updateScrollbars()
 {
     if (m_horizontalScrollbar) {
@@ -123,9 +116,7 @@
     int horizontalScrollbarHeight = (m_horizontalScrollbar && !m_horizontalScrollbar->isOverlayScrollbar()) ? m_horizontalScrollbar->height() : 0;
     int verticalScrollbarWidth = (m_verticalScrollbar && !m_verticalScrollbar->isOverlayScrollbar()) ? m_verticalScrollbar->width() : 0;
 
-    // FIXME: Use document page size for PageDown step.
-    int clientHeight = m_pdfDocumentSize.height();
-    int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
+    int pageStep = m_pageBoxes.isEmpty() ? 0 : m_pageBoxes[0].height();
 
     if (m_horizontalScrollbar) {
         m_horizontalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
@@ -189,12 +180,32 @@
 
 void BuiltInPDFView::pdfDocumentDidLoad()
 {
-    calculateDocumentSize();
+    RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithCFData(m_dataBuffer.get()));
+    m_pdfDocument.adoptCF(CGPDFDocumentCreateWithProvider(pdfDataProvider.get()));
+
+    calculateSizes();
     updateScrollbars();
 
     controller()->invalidate(IntRect(0, 0, m_frameRect.width(), m_frameRect.height()));
 }
 
+void BuiltInPDFView::calculateSizes()
+{
+    size_t pageCount = CGPDFDocumentGetNumberOfPages(m_pdfDocument.get());
+    for (size_t i = 0; i < pageCount; ++i) {
+        CGPDFPageRef pdfPage = CGPDFDocumentGetPage(m_pdfDocument.get(), i + 1);
+        ASSERT(pdfPage);
+
+        CGRect box = CGPDFPageGetBoxRect(pdfPage, kCGPDFCropBox);
+        if (CGRectIsEmpty(box))
+            box = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);
+        m_pageBoxes.append(IntRect(box));
+        m_pdfDocumentSize.setWidth(max(m_pdfDocumentSize.width(), static_cast<int>(box.size.width)));
+        m_pdfDocumentSize.expand(0, box.size.height);
+    }
+    m_pdfDocumentSize.expand(0, gutterHeight * (m_pageBoxes.size() - 1));
+}
+
 bool BuiltInPDFView::initialize(const Parameters& parameters)
 {
     // Load the src URL if needed.
@@ -210,41 +221,79 @@
 
 void BuiltInPDFView::paint(GraphicsContext* graphicsContext, const IntRect& dirtyRectInWindowCoordinates)
 {
-    if (!m_pdfDocument) // FIXME: Draw background and loading progress.
-        return;
+    scrollAnimator()->contentAreaWillPaint();
 
-    // FIXME: This function just draws the fist page of a document at top left corner.
-    // We should show the whole document, centering small ones.
-    CGPDFPageRef pdfPage = CGPDFDocumentGetPage(m_pdfDocument.get(), 1);
-    if (!pdfPage)
+    paintBackground(graphicsContext, dirtyRectInWindowCoordinates);
+
+    if (!m_pdfDocument) // FIXME: Draw loading progress.
         return;
 
-    scrollAnimator()->contentAreaWillPaint();
+    GraphicsContextStateSaver stateSaver(*graphicsContext);
 
+    // Undo translation to window coordinates performed by PluginView::paint().
+    IntRect dirtyRect = pluginView()->parent()->windowToContents(dirtyRectInWindowCoordinates);
+    IntPoint documentOriginInWindowCoordinates = pluginView()->parent()->windowToContents(IntPoint());
+    graphicsContext->translate(-documentOriginInWindowCoordinates.x(), -documentOriginInWindowCoordinates.y());
+
+    paintContent(graphicsContext, dirtyRect);
+    paintControls(graphicsContext, dirtyRect);
+}
+
+void BuiltInPDFView::paintBackground(GraphicsContext* graphicsContext, const IntRect& dirtyRect)
+{
+    GraphicsContextStateSaver stateSaver(*graphicsContext);
+    graphicsContext->setFillColor(Color::gray, ColorSpaceDeviceRGB);
+    graphicsContext->fillRect(dirtyRect);
+}
+
+void BuiltInPDFView::paintContent(GraphicsContext* graphicsContext, const IntRect& dirtyRect)
+{
+    GraphicsContextStateSaver stateSaver(*graphicsContext);
     CGContextRef context = graphicsContext->platformContext();
-    GraphicsContextStateSaver stateSaver(*graphicsContext);
-    graphicsContext->clip(dirtyRectInWindowCoordinates);
+
     graphicsContext->setImageInterpolationQuality(InterpolationHigh);
     graphicsContext->setShouldAntialias(true);
     graphicsContext->setShouldSmoothFonts(true);
+    graphicsContext->setFillColor(Color::white, ColorSpaceDeviceRGB);
 
-    CGRect pageBox = CGPDFPageGetBoxRect(pdfPage, kCGPDFCropBox);
-    if (CGRectIsEmpty(pageBox))
-        pageBox = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);
+    graphicsContext->clip(dirtyRect);
+    IntRect contentRect(dirtyRect);
+    contentRect.moveBy(-pluginView()->location());
+    contentRect.moveBy(IntPoint(m_scrollOffset));
+    graphicsContext->translate(pluginView()->x() - m_scrollOffset.width(), pluginView()->y() - m_scrollOffset.height());
 
-    CGContextClipToRect(context, CGRectMake(m_frameRect.x(), m_frameRect.y(), m_pdfDocumentSize.width() - m_scrollOffset.width(), m_pdfDocumentSize.height() - m_scrollOffset.height()));
-    CGContextTranslateCTM(context, m_frameRect.x() - pageBox.origin.x - m_scrollOffset.width(), m_frameRect.y() + pageBox.origin.y + m_pdfDocumentSize.height() - m_scrollOffset.height());
-
     CGContextScaleCTM(context, 1, -1);
-    CGContextDrawPDFPage(context, pdfPage);
 
-    stateSaver.restore();
+    int pageTop = 0;
+    for (size_t i = 0; i < m_pageBoxes.size(); ++i) {
+        IntRect pageBox = m_pageBoxes[i];
+        if (pageTop > contentRect.maxY())
+            break;
+        if (pageTop + pageBox.height() >= contentRect.y()) {
+            CGPDFPageRef pdfPage = CGPDFDocumentGetPage(m_pdfDocument.get(), i + 1);
 
-    stateSaver.save();
-    // Undo translation to window coordinates performed by PluginView::paint().
-    IntRect dirtyRect = pluginView()->parent()->windowToContents(dirtyRectInWindowCoordinates);
-    IntPoint documentOriginInWindowCoordinates = pluginView()->parent()->windowToContents(IntPoint());
-    graphicsContext->translate(-documentOriginInWindowCoordinates.x(), -documentOriginInWindowCoordinates.y());
+            float extraOffsetForCenteringX = max((m_frameRect.width() - pageBox.width()) / 2.0f, 0.0f);
+            float extraOffsetForCenteringY = (m_pageBoxes.size() == 1) ? max((m_frameRect.height() - pageBox.height() + shadowOffsetY) / 2.0f, 0.0f) : 0;
+
+            graphicsContext->save();
+            graphicsContext->translate(extraOffsetForCenteringX - pageBox.x(), -extraOffsetForCenteringY - pageBox.y() - pageBox.height());
+
+            graphicsContext->setShadow(FloatSize(shadowOffsetX, shadowOffsetY), shadowSize, Color::black, ColorSpaceDeviceRGB);
+            graphicsContext->fillRect(pageBox);
+            graphicsContext->clearShadow();
+
+            graphicsContext->clip(pageBox);
+
+            CGContextDrawPDFPage(context, pdfPage);
+            graphicsContext->restore();
+        }
+        pageTop += pageBox.height() + gutterHeight;
+        CGContextTranslateCTM(context, 0, -pageBox.height() - gutterHeight);
+    }
+}
+
+void BuiltInPDFView::paintControls(GraphicsContext* graphicsContext, const IntRect& dirtyRect)
+{
     if (m_horizontalScrollbar)
         m_horizontalScrollbar->paint(graphicsContext, dirtyRect);
     if (m_verticalScrollbar)
@@ -334,9 +383,6 @@
 {
     ASSERT_UNUSED(streamID, streamID == pdfDocumentRequestID);
 
-    RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithCFData(m_dataBuffer.get()));
-    m_pdfDocument.adoptCF(CGPDFDocumentCreateWithProvider(pdfDataProvider.get()));
-
     pdfDocumentDidLoad();
 }
 
@@ -361,9 +407,6 @@
 
 void BuiltInPDFView::manualStreamDidFinishLoading()
 {
-    RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithCFData(m_dataBuffer.get()));
-    m_pdfDocument.adoptCF(CGPDFDocumentCreateWithProvider(pdfDataProvider.get()));
-
     pdfDocumentDidLoad();
 }
 

Modified: trunk/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h (97154 => 97155)


--- trunk/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h	2011-10-11 16:13:11 UTC (rev 97154)
+++ trunk/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h	2011-10-11 16:41:11 UTC (rev 97155)
@@ -53,18 +53,21 @@
     PluginView* pluginView();
     const PluginView* pluginView() const;
 
-    void calculateDocumentSize();
     void updateScrollbars();
     void didAddHorizontalScrollbar(WebCore::Scrollbar*);
     void willRemoveHorizontalScrollbar(WebCore::Scrollbar*);
     PassRefPtr<WebCore::Scrollbar> createScrollbar(WebCore::ScrollbarOrientation);
     void destroyScrollbar(WebCore::ScrollbarOrientation);
     void pdfDocumentDidLoad();
+    void calculateSizes();
+    void paintBackground(WebCore::GraphicsContext*, const WebCore::IntRect& dirtyRect);
+    void paintContent(WebCore::GraphicsContext*, const WebCore::IntRect& dirtyRect);
+    void paintControls(WebCore::GraphicsContext*, const WebCore::IntRect& dirtyRect);
 
     // Plug-in methods
     virtual bool initialize(const Parameters&);
     virtual void destroy();
-    virtual void paint(WebCore::GraphicsContext*, const WebCore::IntRect& dirtyRect);
+    virtual void paint(WebCore::GraphicsContext*, const WebCore::IntRect& dirtyRectInWindowCoordinates);
     virtual void updateControlTints(WebCore::GraphicsContext*);
     virtual PassRefPtr<ShareableBitmap> snapshot();
 #if PLATFORM(MAC)
@@ -136,6 +139,7 @@
 
     RetainPtr<CFMutableDataRef> m_dataBuffer;
     RetainPtr<CGPDFDocumentRef> m_pdfDocument;
+    Vector<WebCore::IntRect> m_pageBoxes;
     WebCore::IntSize m_pdfDocumentSize; // All pages, including gaps.
 
     RefPtr<WebCore::Scrollbar> m_horizontalScrollbar;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to