821668c850c2f5c43c401ff04d7ec159922cc320
[WebKit-https.git] / Source / WebCore / rendering / TextAutosizer.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  * Copyright (C) 2012 Apple Inc. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22
23 #if ENABLE(TEXT_AUTOSIZING)
24
25 #include "TextAutosizer.h"
26
27 #include "Document.h"
28 #include "InspectorInstrumentation.h"
29 #include "RenderObject.h"
30 #include "RenderText.h"
31 #include "RenderView.h"
32 #include "Settings.h"
33
34 namespace WebCore {
35
36 TextAutosizer::TextAutosizer(Document* document)
37     : m_document(document)
38 {
39 }
40
41 TextAutosizer::~TextAutosizer()
42 {
43 }
44
45 bool TextAutosizer::boostSubtree(RenderObject* layoutRoot)
46 {
47     // FIXME: Text Autosizing should only be enabled when m_document->page()->mainFrame()->view()->useFixedLayout()
48     // is true, but for now it's useful to ignore this so that it can be tested on desktop.
49     if (!m_document->settings() || !m_document->settings()->textAutosizingEnabled() || layoutRoot->view()->printing() || !m_document->page())
50         return false;
51
52 #ifdef HACK_FORCE_TEXT_AUTOSIZING_ON_DESKTOP
53     IntSize windowSize(320, 480);
54 #else
55     Frame* mainFrame = m_document->page()->mainFrame();
56     bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenWidthOverride(mainFrame);
57     IntSize windowSize = mainFrame->view()->visibleContentRect(includeScrollbars).size(); // FIXME: Check that this is always in logical (density-independent) pixels (see wkbug.com/87440).
58 #endif
59
60     for (RenderObject* descendant = traverseNext(layoutRoot, layoutRoot); descendant; descendant = traverseNext(descendant, layoutRoot)) {
61         if (!treatAsInline(descendant))
62             boostBlock(toRenderBlock(descendant), windowSize);
63     }
64
65     return true;
66 }
67
68 void TextAutosizer::boostBlock(RenderBlock* block, LayoutSize windowSize)
69 {
70     float windowLogicalWidth = block->isHorizontalWritingMode() ? windowSize.width() : windowSize.height();
71     float multiplier = block->logicalWidth() / windowLogicalWidth; // FIXME: This is overly simplistic.
72     if (multiplier < 1)
73         return;
74     for (RenderObject* descendant = traverseNext(block, block, treatAsInline); descendant; descendant = traverseNext(descendant, block, treatAsInline)) {
75         if (descendant->isText())
76             boostText(toRenderText(descendant), multiplier);
77     }
78 }
79
80 void TextAutosizer::boostText(RenderText* text, float multiplier)
81 {
82     float specifiedSize = text->style()->fontDescription().specifiedSize();
83     float boostedSize = specifiedSize * multiplier; // FIXME: This is overly simplistic.
84
85     RefPtr<RenderStyle> style = RenderStyle::clone(text->style());
86     FontDescription fontDescription(style->fontDescription());
87     fontDescription.setComputedSize(boostedSize);
88     style->setFontDescription(fontDescription);
89     style->font().update(style->font().fontSelector());
90     text->setStyle(style.release());
91
92     // FIXME: Increase computed line height proportionately.
93     // FIXME: Boost list markers proportionately.
94 }
95
96 bool TextAutosizer::treatAsInline(const RenderObject* renderer)
97 {
98     return !renderer->isRenderBlock() || renderer->isListItem() || renderer->isInlineBlockOrInlineTable();
99 }
100
101 RenderObject* TextAutosizer::traverseNext(RenderObject* current, const RenderObject* stayWithin, RenderObjectFilter filter)
102 {
103     for (RenderObject* child = current->firstChild(); child; child = child->nextSibling()) {
104         if (!filter || filter(child)) {
105             ASSERT(!stayWithin || child->isDescendantOf(stayWithin));
106             return child;
107         }
108     }
109
110     for (RenderObject* ancestor = current; ancestor; ancestor = ancestor->parent()) {
111         if (ancestor == stayWithin)
112             return 0;
113         for (RenderObject* sibling = ancestor->nextSibling(); sibling; sibling = sibling->nextSibling()) {
114             if (!filter || filter(sibling)) {
115                 ASSERT(!stayWithin || sibling->isDescendantOf(stayWithin));
116                 return sibling;
117             }
118         }
119     }
120
121     return 0;
122 }
123
124 } // namespace WebCore
125
126 #endif // ENABLE(TEXT_AUTOSIZING)