Home | History | Annotate | Download | only in page
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "PageScaleConstraintsSet.h"
     33 
     34 namespace WebCore {
     35 
     36 static const float defaultMinimumScale = 0.25f;
     37 static const float defaultMaximumScale = 5.0f;
     38 
     39 PageScaleConstraintsSet::PageScaleConstraintsSet()
     40     : m_lastContentsWidth(0)
     41     , m_needsReset(false)
     42     , m_constraintsDirty(false)
     43 {
     44     m_finalConstraints = defaultConstraints();
     45 }
     46 
     47 PageScaleConstraints PageScaleConstraintsSet::defaultConstraints() const
     48 {
     49     return PageScaleConstraints(-1, defaultMinimumScale, defaultMaximumScale);
     50 }
     51 
     52 void PageScaleConstraintsSet::updatePageDefinedConstraints(const ViewportArguments& arguments, IntSize viewSize, int layoutFallbackWidth)
     53 {
     54     m_pageDefinedConstraints = arguments.resolve(viewSize, viewSize, layoutFallbackWidth);
     55 
     56     m_constraintsDirty = true;
     57 }
     58 
     59 void PageScaleConstraintsSet::setUserAgentConstraints(const PageScaleConstraints& userAgentConstraints)
     60 {
     61     m_userAgentConstraints = userAgentConstraints;
     62     m_constraintsDirty = true;
     63 }
     64 
     65 PageScaleConstraints PageScaleConstraintsSet::computeConstraintsStack() const
     66 {
     67     PageScaleConstraints constraints = defaultConstraints();
     68     constraints.overrideWith(m_pageDefinedConstraints);
     69     constraints.overrideWith(m_userAgentConstraints);
     70     return constraints;
     71 }
     72 
     73 void PageScaleConstraintsSet::computeFinalConstraints()
     74 {
     75     m_finalConstraints = computeConstraintsStack();
     76 
     77     m_constraintsDirty = false;
     78 }
     79 
     80 void PageScaleConstraintsSet::adjustFinalConstraintsToContentsSize(IntSize viewSize, IntSize contentsSize, int nonOverlayScrollbarWidth)
     81 {
     82     m_finalConstraints.fitToContentsWidth(contentsSize.width(), viewSize.width() - nonOverlayScrollbarWidth);
     83 }
     84 
     85 void PageScaleConstraintsSet::setNeedsReset(bool needsReset)
     86 {
     87     m_needsReset = needsReset;
     88     if (needsReset)
     89         m_constraintsDirty = true;
     90 }
     91 
     92 void PageScaleConstraintsSet::didChangeContentsSize(IntSize contentsSize, float pageScaleFactor)
     93 {
     94     // If a large fixed-width element expanded the size of the document late in
     95     // loading and our initial scale is not set (or set to be less than the last
     96     // minimum scale), reset the page scale factor to the new initial scale.
     97     if (contentsSize.width() > m_lastContentsWidth
     98         && pageScaleFactor == finalConstraints().minimumScale
     99         && computeConstraintsStack().initialScale < finalConstraints().minimumScale)
    100         setNeedsReset(true);
    101 
    102     m_constraintsDirty = true;
    103     m_lastContentsWidth = contentsSize.width();
    104 }
    105 
    106 static float computeDeprecatedTargetDensityDPIFactor(const ViewportArguments& arguments, float deviceScaleFactor)
    107 {
    108     if (arguments.deprecatedTargetDensityDPI == ViewportArguments::ValueDeviceDPI)
    109         return 1.0f / deviceScaleFactor;
    110 
    111     float targetDPI = -1.0f;
    112     if (arguments.deprecatedTargetDensityDPI == ViewportArguments::ValueLowDPI)
    113         targetDPI = 120.0f;
    114     else if (arguments.deprecatedTargetDensityDPI == ViewportArguments::ValueMediumDPI)
    115         targetDPI = 160.0f;
    116     else if (arguments.deprecatedTargetDensityDPI == ViewportArguments::ValueHighDPI)
    117         targetDPI = 240.0f;
    118     else if (arguments.deprecatedTargetDensityDPI != ViewportArguments::ValueAuto)
    119         targetDPI = arguments.deprecatedTargetDensityDPI;
    120     return targetDPI > 0 ? 160.0f / targetDPI : 1.0f;
    121 }
    122 
    123 static float getLayoutWidthForNonWideViewport(const FloatSize& deviceSize, float initialScale)
    124 {
    125     return initialScale == -1 ? deviceSize.width() : deviceSize.width() / initialScale;
    126 }
    127 
    128 static float computeHeightByAspectRatio(float width, const FloatSize& deviceSize)
    129 {
    130     return width * (deviceSize.height() / deviceSize.width());
    131 }
    132 
    133 void PageScaleConstraintsSet::adjustForAndroidWebViewQuirks(const ViewportArguments& arguments, IntSize viewSize, int layoutFallbackWidth, float deviceScaleFactor, bool supportTargetDensityDPI, bool wideViewportQuirkEnabled, bool useWideViewport, bool loadWithOverviewMode)
    134 {
    135     if (!supportTargetDensityDPI && !wideViewportQuirkEnabled && loadWithOverviewMode)
    136         return;
    137 
    138     const float oldInitialScale = m_pageDefinedConstraints.initialScale;
    139     if (!loadWithOverviewMode) {
    140         bool resetInitialScale = false;
    141         if (arguments.zoom == -1) {
    142             if (arguments.width == -1)
    143                 resetInitialScale = true;
    144             if (useWideViewport || arguments.width == ViewportArguments::ValueDeviceWidth)
    145                 resetInitialScale = true;
    146         }
    147         if (resetInitialScale)
    148             m_pageDefinedConstraints.initialScale = 1.0f;
    149     }
    150 
    151     float adjustedLayoutSizeWidth = m_pageDefinedConstraints.layoutSize.width();
    152     float adjustedLayoutSizeHeight = m_pageDefinedConstraints.layoutSize.height();
    153     float targetDensityDPIFactor = 1.0f;
    154 
    155     if (supportTargetDensityDPI) {
    156         targetDensityDPIFactor = computeDeprecatedTargetDensityDPIFactor(arguments, deviceScaleFactor);
    157         if (m_pageDefinedConstraints.initialScale != -1)
    158             m_pageDefinedConstraints.initialScale *= targetDensityDPIFactor;
    159         m_pageDefinedConstraints.minimumScale *= targetDensityDPIFactor;
    160         m_pageDefinedConstraints.maximumScale *= targetDensityDPIFactor;
    161         if (wideViewportQuirkEnabled && (!useWideViewport || arguments.width <= 0)) {
    162             adjustedLayoutSizeWidth /= targetDensityDPIFactor;
    163             adjustedLayoutSizeHeight /= targetDensityDPIFactor;
    164         }
    165     }
    166 
    167     if (wideViewportQuirkEnabled) {
    168         if (useWideViewport && arguments.width == -1 && arguments.zoom != 1.0f) {
    169             adjustedLayoutSizeWidth = layoutFallbackWidth;
    170             adjustedLayoutSizeHeight = computeHeightByAspectRatio(adjustedLayoutSizeWidth, viewSize);
    171         } else if (!useWideViewport) {
    172             const float nonWideScale = arguments.zoom < 1 && arguments.width != ViewportArguments::ValueDeviceWidth ? -1 : oldInitialScale;
    173             adjustedLayoutSizeWidth = getLayoutWidthForNonWideViewport(viewSize, nonWideScale) / targetDensityDPIFactor;
    174             if (m_userAgentConstraints.initialScale != -1 && (arguments.width == ViewportArguments::ValueDeviceWidth || (arguments.width == -1 && arguments.zoom == -1)))
    175                 adjustedLayoutSizeWidth /= m_userAgentConstraints.initialScale;
    176             adjustedLayoutSizeHeight = computeHeightByAspectRatio(adjustedLayoutSizeWidth, viewSize);
    177             if (arguments.zoom < 1) {
    178                 m_pageDefinedConstraints.initialScale = targetDensityDPIFactor;
    179                 m_pageDefinedConstraints.minimumScale = std::min<float>(m_pageDefinedConstraints.minimumScale, m_pageDefinedConstraints.initialScale);
    180                 m_pageDefinedConstraints.maximumScale = std::max<float>(m_pageDefinedConstraints.maximumScale, m_pageDefinedConstraints.initialScale);
    181             }
    182         }
    183     }
    184 
    185     if (supportTargetDensityDPI && !arguments.userZoom) {
    186         m_pageDefinedConstraints.initialScale = targetDensityDPIFactor;
    187         m_pageDefinedConstraints.minimumScale = m_pageDefinedConstraints.initialScale;
    188         m_pageDefinedConstraints.maximumScale = m_pageDefinedConstraints.initialScale;
    189         if (arguments.width == -1 || arguments.width == ViewportArguments::ValueDeviceWidth) {
    190             adjustedLayoutSizeWidth = viewSize.width() / targetDensityDPIFactor;
    191             adjustedLayoutSizeHeight = computeHeightByAspectRatio(adjustedLayoutSizeWidth, viewSize);
    192         }
    193     }
    194 
    195     m_pageDefinedConstraints.layoutSize.setWidth(adjustedLayoutSizeWidth);
    196     m_pageDefinedConstraints.layoutSize.setHeight(adjustedLayoutSizeHeight);
    197 }
    198 
    199 } // namespace WebCore
    200