Title: [161568] trunk/Source/WebCore
Revision
161568
Author
[email protected]
Date
2014-01-09 12:14:32 -0800 (Thu, 09 Jan 2014)

Log Message

PDFDocumentImage can be very slow to do the initial paint
https://bugs.webkit.org/show_bug.cgi?id=126633
<rdar://problem/15770980>

Reviewed by Simon Fraser.

* platform/graphics/cg/PDFDocumentImage.cpp:
(WebCore::PDFDocumentImage::PDFDocumentImage):
(WebCore::PDFDocumentImage::size):
(WebCore::transformContextForPainting):
(WebCore::PDFDocumentImage::computeBoundsForCurrentPage):
(WebCore::applyRotationForPainting):
(WebCore::PDFDocumentImage::drawPDFPage):
* platform/graphics/cg/PDFDocumentImage.h:
* platform/graphics/mac/PDFDocumentImageMac.mm:
(WebCore::PDFDocumentImage::computeBoundsForCurrentPage):
Store rotation from the PDF in degrees, since it can
only be 0, 90, 180, or 270, and don't do any trig to
perform the rotation, to avoid introducing minor rounding
issues in the size.

Once we're going to paint, if the difference between the
computed scale for each axis is due only to integer rounding
of the image size, use the same scale for both axes, to avoid
a CG slow-path which occurs whenever the scale is nonuniform.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (161567 => 161568)


--- trunk/Source/WebCore/ChangeLog	2014-01-09 20:09:53 UTC (rev 161567)
+++ trunk/Source/WebCore/ChangeLog	2014-01-09 20:14:32 UTC (rev 161568)
@@ -1,3 +1,31 @@
+2014-01-09  Tim Horton  <[email protected]>
+
+        PDFDocumentImage can be very slow to do the initial paint
+        https://bugs.webkit.org/show_bug.cgi?id=126633
+        <rdar://problem/15770980>
+
+        Reviewed by Simon Fraser.
+
+        * platform/graphics/cg/PDFDocumentImage.cpp:
+        (WebCore::PDFDocumentImage::PDFDocumentImage):
+        (WebCore::PDFDocumentImage::size):
+        (WebCore::transformContextForPainting):
+        (WebCore::PDFDocumentImage::computeBoundsForCurrentPage):
+        (WebCore::applyRotationForPainting):
+        (WebCore::PDFDocumentImage::drawPDFPage):
+        * platform/graphics/cg/PDFDocumentImage.h:
+        * platform/graphics/mac/PDFDocumentImageMac.mm:
+        (WebCore::PDFDocumentImage::computeBoundsForCurrentPage):
+        Store rotation from the PDF in degrees, since it can
+        only be 0, 90, 180, or 270, and don't do any trig to
+        perform the rotation, to avoid introducing minor rounding
+        issues in the size.
+
+        Once we're going to paint, if the difference between the
+        computed scale for each axis is due only to integer rounding
+        of the image size, use the same scale for both axes, to avoid
+        a CG slow-path which occurs whenever the scale is nonuniform.
+
 2014-01-09  Antti Koivisto  <[email protected]>
 
         Disconnect child frames iteratively

Modified: trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp (161567 => 161568)


--- trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp	2014-01-09 20:09:53 UTC (rev 161567)
+++ trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp	2014-01-09 20:14:32 UTC (rev 161568)
@@ -48,7 +48,7 @@
 PDFDocumentImage::PDFDocumentImage(ImageObserver* observer)
     : Image(observer)
     , m_cachedBytes(0)
-    , m_rotation(0.0f)
+    , m_rotationDegrees(0)
     , m_hasPage(false)
 {
 }
@@ -64,14 +64,11 @@
 
 IntSize PDFDocumentImage::size() const
 {
-    const float sina = sinf(-m_rotation);
-    const float cosa = cosf(-m_rotation);
-    const float width = m_cropBox.size().width();
-    const float height = m_cropBox.size().height();
-    const float rotWidth = fabsf(width * cosa - height * sina);
-    const float rotHeight = fabsf(width * sina + height * cosa);
-    
-    return expandedIntSize(FloatSize(rotWidth, rotHeight));
+    IntSize expandedCropBoxSize = expandedIntSize(m_cropBox.size());
+
+    if (m_rotationDegrees == 90 || m_rotationDegrees == 270)
+        return expandedCropBoxSize.transposedSize();
+    return expandedCropBoxSize;
 }
 
 void PDFDocumentImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
@@ -95,26 +92,6 @@
     return m_document; // Return true if size is available.
 }
 
-void PDFDocumentImage::applyRotationForPainting(GraphicsContext* context) const
-{
-    // Rotate the crop box and calculate bounding box.
-    float sina = sinf(-m_rotation);
-    float cosa = cosf(-m_rotation);
-    float width = m_cropBox.width();
-    float height = m_cropBox.height();
-
-    // Calculate rotated x and y edges of the crop box. If they're negative, it means part of the image has
-    // been rotated outside of the bounds and we need to shift over the image so it lies inside the bounds again.
-    CGPoint rx = CGPointMake(width * cosa, width * sina);
-    CGPoint ry = CGPointMake(-height * sina, height * cosa);
-
-    // Adjust so we are at the crop box origin.
-    const CGFloat zero = 0;
-    context->translate(floorf(-std::min(zero, std::min(rx.x, ry.x))), floorf(-std::min(zero, std::min(rx.y, ry.y))));
-
-    context->rotate(-m_rotation);
-}
-
 bool PDFDocumentImage::cacheParametersMatch(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect) const
 {
     if (dstRect.size() != m_cachedDestinationSize)
@@ -138,6 +115,17 @@
 {
     float hScale = dstRect.width() / srcRect.width();
     float vScale = dstRect.height() / srcRect.height();
+
+    float minimumScale = std::max((dstRect.width() - 0.5) / srcRect.width(), (dstRect.height() - 0.5) / srcRect.height());
+    float maximumScale = std::min((dstRect.width() + 0.5) / srcRect.width(), (dstRect.height() + 0.5) / srcRect.height());
+
+    // If the difference between the two scales is due to integer rounding of image sizes,
+    // use the average scale for both axes.
+    if (minimumScale <= maximumScale) {
+        hScale = (maximumScale + minimumScale) / 2;
+        vScale = hScale;
+    }
+
     context->translate(srcRect.x() * hScale, srcRect.y() * vScale);
     context->scale(FloatSize(hScale, -vScale));
     context->translate(0, -srcRect.height());
@@ -228,7 +216,7 @@
     else
         m_cropBox = mediaBox;
 
-    m_rotation = deg2rad(static_cast<float>(CGPDFPageGetRotationAngle(cgPage)));
+    m_rotationDegrees = CGPDFPageGetRotationAngle(cgPage);
 }
 
 unsigned PDFDocumentImage::pageCount() const
@@ -236,9 +224,21 @@
     return CGPDFDocumentGetNumberOfPages(m_document.get());
 }
 
+static void applyRotationForPainting(GraphicsContext* context, IntSize size, int rotationDegrees)
+{
+    if (rotationDegrees == 90)
+        context->translate(0, size.height());
+    else if (rotationDegrees == 180)
+        context->translate(size.width(), size.height());
+    else if (rotationDegrees == 270)
+        context->translate(size.width(), 0);
+
+    context->rotate(-deg2rad(static_cast<float>(rotationDegrees)));
+}
+
 void PDFDocumentImage::drawPDFPage(GraphicsContext* context)
 {
-    applyRotationForPainting(context);
+    applyRotationForPainting(context, size(), m_rotationDegrees);
 
     context->translate(-m_cropBox.x(), -m_cropBox.y());
 

Modified: trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h (161567 => 161568)


--- trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h	2014-01-09 20:09:53 UTC (rev 161567)
+++ trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h	2014-01-09 20:14:32 UTC (rev 161568)
@@ -74,8 +74,6 @@
     // FIXME: Implement this to be less conservative.
     virtual bool currentFrameKnownToBeOpaque() OVERRIDE { return false; }
 
-    void applyRotationForPainting(GraphicsContext*) const;
-
     void createPDFDocument();
     void computeBoundsForCurrentPage();
     unsigned pageCount() const;
@@ -97,7 +95,7 @@
     size_t m_cachedBytes;
 
     FloatRect m_cropBox;
-    float m_rotation;
+    int m_rotationDegrees; // Can only be 0, 90, 180, or 270 degrees.
     bool m_hasPage;
 };
 

Modified: trunk/Source/WebCore/platform/graphics/mac/PDFDocumentImageMac.mm (161567 => 161568)


--- trunk/Source/WebCore/platform/graphics/mac/PDFDocumentImageMac.mm	2014-01-09 20:09:53 UTC (rev 161567)
+++ trunk/Source/WebCore/platform/graphics/mac/PDFDocumentImageMac.mm	2014-01-09 20:14:32 UTC (rev 161568)
@@ -61,7 +61,7 @@
     PDFPage *pdfPage = [m_document pageAtIndex:0];
 
     m_cropBox = [pdfPage boundsForBox:kPDFDisplayBoxCropBox];
-    m_rotation = deg2rad(static_cast<float>([pdfPage rotation]));
+    m_rotationDegrees = [pdfPage rotation];
 }
 
 unsigned PDFDocumentImage::pageCount() const
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to