Text Autosizing: Multiply large fonts less, as they are already more legible.
[WebKit-https.git] / Source / WebCore / rendering / TextAutosizer.cpp
index 95b3e29..4cd735a 100644 (file)
@@ -31,6 +31,7 @@
 #include "RenderText.h"
 #include "RenderView.h"
 #include "Settings.h"
 #include "RenderText.h"
 #include "RenderView.h"
 #include "Settings.h"
+#include "StyleInheritedData.h"
 
 namespace WebCore {
 
 
 namespace WebCore {
 
@@ -50,26 +51,40 @@ bool TextAutosizer::processSubtree(RenderObject* layoutRoot)
     if (!m_document->settings() || !m_document->settings()->textAutosizingEnabled() || layoutRoot->view()->printing() || !m_document->page())
         return false;
 
     if (!m_document->settings() || !m_document->settings()->textAutosizingEnabled() || layoutRoot->view()->printing() || !m_document->page())
         return false;
 
+    Frame* mainFrame = m_document->page()->mainFrame();
+
+    // Window area, in logical (density-independent) pixels.
     IntSize windowSize = m_document->settings()->textAutosizingWindowSizeOverride();
     if (windowSize.isEmpty()) {
     IntSize windowSize = m_document->settings()->textAutosizingWindowSizeOverride();
     if (windowSize.isEmpty()) {
-        Frame* mainFrame = m_document->page()->mainFrame();
         bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenWidthOverride(mainFrame);
         windowSize = mainFrame->view()->visibleContentRect(includeScrollbars).size(); // FIXME: Check that this is always in logical (density-independent) pixels (see wkbug.com/87440).
     }
 
         bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenWidthOverride(mainFrame);
         windowSize = mainFrame->view()->visibleContentRect(includeScrollbars).size(); // FIXME: Check that this is always in logical (density-independent) pixels (see wkbug.com/87440).
     }
 
+    // Largest area of block that can be visible at once (assuming the main
+    // frame doesn't get scaled to less than overview scale), in CSS pixels.
+    IntSize minLayoutSize = mainFrame->view()->layoutSize();
+    for (Frame* frame = m_document->frame(); frame; frame = frame->tree()->parent()) {
+        if (!frame->view()->isInChildFrameWithFrameFlattening())
+            minLayoutSize = minLayoutSize.shrunkTo(frame->view()->layoutSize());
+    }
+
     for (RenderObject* descendant = layoutRoot->nextInPreOrder(layoutRoot); descendant; descendant = descendant->nextInPreOrder(layoutRoot)) {
         if (isNotAnAutosizingContainer(descendant))
             continue;
     for (RenderObject* descendant = layoutRoot->nextInPreOrder(layoutRoot); descendant; descendant = descendant->nextInPreOrder(layoutRoot)) {
         if (isNotAnAutosizingContainer(descendant))
             continue;
-        processBox(toRenderBox(descendant), windowSize);
+        processBox(toRenderBox(descendant), windowSize, minLayoutSize);
     }
 
     return true;
 }
 
     }
 
     return true;
 }
 
-void TextAutosizer::processBox(RenderBox* box, const IntSize& windowSize)
+void TextAutosizer::processBox(RenderBox* box, const IntSize& windowSize, const IntSize& layoutSize)
 {
 {
-    int windowLogicalWidth = box->isHorizontalWritingMode() ? windowSize.width() : windowSize.height();
-    float multiplier = static_cast<float>(box->logicalWidth()) / windowLogicalWidth; // FIXME: This is overly simplistic.
+    int logicalWindowWidth = box->isHorizontalWritingMode() ? windowSize.width() : windowSize.height();
+    int logicalLayoutWidth = box->isHorizontalWritingMode() ? layoutSize.width() : layoutSize.height();
+    // Ignore box width in excess of the layout width, to avoid extreme multipliers.
+    float logicalBoxWidth = std::min<float>(box->logicalWidth(), logicalLayoutWidth);
+
+    float multiplier = logicalBoxWidth / logicalWindowWidth;
     multiplier *= m_document->settings()->textAutosizingFontScaleFactor();
 
     if (multiplier < 1)
     multiplier *= m_document->settings()->textAutosizingFontScaleFactor();
 
     if (multiplier < 1)
@@ -92,6 +107,34 @@ void TextAutosizer::setMultiplier(RenderObject* renderer, float multiplier)
     renderer->setStyle(newStyle.release());
 }
 
     renderer->setStyle(newStyle.release());
 }
 
+float TextAutosizer::computeAutosizedFontSize(float specifiedSize, float multiplier)
+{
+    // Somewhat arbitrary "pleasant" font size.
+    const float pleasantSize = 16;
+
+    // Multiply fonts that the page author has specified to be larger than
+    // pleasantSize by less and less, until huge fonts are not increased at all.
+    // For specifiedSize between 0 and pleasantSize we directly apply the
+    // multiplier; hence for specifiedSize == pleasantSize, computedSize will be
+    // multiplier * pleasantSize. For greater specifiedSizes we want to
+    // gradually fade out the multiplier, so for every 1px increase in
+    // specifiedSize beyond pleasantSize we will only increase computedSize
+    // by gradientAfterPleasantSize px until we meet the
+    // computedSize = specifiedSize line, after which we stay on that line (so
+    // then every 1px increase in specifiedSize increases computedSize by 1px).
+    const float gradientAfterPleasantSize = 0.5;
+
+    float computedSize;
+    if (specifiedSize <= pleasantSize)
+        computedSize = multiplier * specifiedSize;
+    else {
+        computedSize = multiplier * pleasantSize + gradientAfterPleasantSize * (specifiedSize - pleasantSize);
+        if (computedSize < specifiedSize)
+            computedSize = specifiedSize;
+    }
+    return computedSize;
+}
+
 bool TextAutosizer::isNotAnAutosizingContainer(const RenderObject* renderer)
 {
     // "Autosizing containers" are the smallest unit for which we can enable/disable
 bool TextAutosizer::isNotAnAutosizingContainer(const RenderObject* renderer)
 {
     // "Autosizing containers" are the smallest unit for which we can enable/disable