OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 return parent; | 56 return parent; |
57 } | 57 } |
58 return 0; | 58 return 0; |
59 } | 59 } |
60 | 60 |
61 FastTextAutosizer::FastTextAutosizer(const Document* document) | 61 FastTextAutosizer::FastTextAutosizer(const Document* document) |
62 : m_document(document) | 62 : m_document(document) |
63 , m_frameWidth(0) | 63 , m_frameWidth(0) |
64 , m_layoutWidth(0) | 64 , m_layoutWidth(0) |
65 , m_baseMultiplier(0) | 65 , m_baseMultiplier(0) |
| 66 , m_pageAutosizingStatus(PageAutosizingStatusUnknown) |
66 , m_firstBlock(0) | 67 , m_firstBlock(0) |
67 #ifndef NDEBUG | 68 #ifndef NDEBUG |
68 , m_renderViewInfoPrepared(false) | 69 , m_renderViewInfoPrepared(false) |
69 , m_blocksThatHaveBegunLayout() | 70 , m_blocksThatHaveBegunLayout() |
70 #endif | 71 #endif |
71 , m_superclusters() | 72 , m_superclusters() |
72 , m_clusterStack() | 73 , m_clusterStack() |
73 , m_fingerprintMapper() | 74 , m_fingerprintMapper() |
74 { | 75 { |
75 } | 76 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 #ifndef NDEBUG | 109 #ifndef NDEBUG |
109 m_blocksThatHaveBegunLayout.add(block); | 110 m_blocksThatHaveBegunLayout.add(block); |
110 #endif | 111 #endif |
111 if (Cluster* cluster = maybeCreateCluster(block)) | 112 if (Cluster* cluster = maybeCreateCluster(block)) |
112 m_clusterStack.append(adoptPtr(cluster)); | 113 m_clusterStack.append(adoptPtr(cluster)); |
113 } | 114 } |
114 } | 115 } |
115 | 116 |
116 void FastTextAutosizer::beginLayout(RenderBlock* block) | 117 void FastTextAutosizer::beginLayout(RenderBlock* block) |
117 { | 118 { |
118 ASSERT(enabled()); | 119 ASSERT(enabled() && m_pageAutosizingStatus == PageNeedsAutosizing); |
119 #ifndef NDEBUG | 120 #ifndef NDEBUG |
120 m_blocksThatHaveBegunLayout.add(block); | 121 m_blocksThatHaveBegunLayout.add(block); |
121 #endif | 122 #endif |
122 | 123 |
123 if (!m_firstBlock) { | 124 if (!m_firstBlock) { |
124 prepareRenderViewInfo(); | 125 m_firstBlock = block; |
125 prepareClusterStack(block->parent()); | 126 prepareClusterStack(block->parent()); |
126 m_firstBlock = block; | |
127 } else if (block == currentCluster()->m_root) { | 127 } else if (block == currentCluster()->m_root) { |
128 // Ignore beginLayout on the same block twice. | 128 // Ignore beginLayout on the same block twice. |
129 // This can happen with paginated overflow. | 129 // This can happen with paginated overflow. |
130 return; | 130 return; |
131 } | 131 } |
132 | 132 |
133 if (Cluster* cluster = maybeCreateCluster(block)) { | 133 if (Cluster* cluster = maybeCreateCluster(block)) { |
134 m_clusterStack.append(adoptPtr(cluster)); | 134 m_clusterStack.append(adoptPtr(cluster)); |
135 if (block->isTable()) | 135 if (block->isTable()) |
136 inflateTable(toRenderTable(block)); | 136 inflateTable(toRenderTable(block)); |
137 } | 137 } |
138 | 138 |
139 if (block->childrenInline() && block->firstChild()) | 139 if (block->childrenInline() && block->firstChild()) |
140 inflate(block); | 140 inflate(block); |
141 } | 141 } |
142 | 142 |
143 void FastTextAutosizer::inflateListItem(RenderListItem* listItem, RenderListMark
er* listItemMarker) | 143 void FastTextAutosizer::inflateListItem(RenderListItem* listItem, RenderListMark
er* listItemMarker) |
144 { | 144 { |
145 if (!enabled()) | 145 if (!enabled() || m_pageAutosizingStatus != PageNeedsAutosizing) |
146 return; | 146 return; |
147 ASSERT(listItem && listItemMarker); | 147 ASSERT(listItem && listItemMarker); |
148 #ifndef NDEBUG | 148 #ifndef NDEBUG |
149 m_blocksThatHaveBegunLayout.add(listItem); | 149 m_blocksThatHaveBegunLayout.add(listItem); |
150 #endif | 150 #endif |
151 // Force the LI to be inside the DBCAT when computing the multiplier. | 151 // Force the LI to be inside the DBCAT when computing the multiplier. |
152 // This guarantees that the DBCAT has entered layout, so we can ask for its
width. | 152 // This guarantees that the DBCAT has entered layout, so we can ask for its
width. |
153 // It also makes sense because the list marker is autosized like a text node
. | 153 // It also makes sense because the list marker is autosized like a text node
. |
154 float multiplier = clusterMultiplier(currentCluster()); | 154 float multiplier = clusterMultiplier(currentCluster()); |
155 | 155 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 } | 189 } |
190 } | 190 } |
191 } | 191 } |
192 } | 192 } |
193 } | 193 } |
194 } | 194 } |
195 } | 195 } |
196 | 196 |
197 void FastTextAutosizer::endLayout(RenderBlock* block) | 197 void FastTextAutosizer::endLayout(RenderBlock* block) |
198 { | 198 { |
199 ASSERT(enabled()); | 199 ASSERT(enabled() && m_pageAutosizingStatus == PageNeedsAutosizing); |
200 | 200 |
201 if (block == m_firstBlock) { | 201 if (block == m_firstBlock) { |
202 m_firstBlock = 0; | 202 m_firstBlock = 0; |
| 203 m_pageAutosizingStatus = PageAutosizingStatusUnknown; |
203 m_clusterStack.clear(); | 204 m_clusterStack.clear(); |
204 m_superclusters.clear(); | 205 m_superclusters.clear(); |
205 #ifndef NDEBUG | 206 #ifndef NDEBUG |
206 m_blocksThatHaveBegunLayout.clear(); | 207 m_blocksThatHaveBegunLayout.clear(); |
207 #endif | 208 #endif |
208 } else if (currentCluster()->m_root == block) { | 209 } else if (currentCluster()->m_root == block) { |
209 m_clusterStack.removeLast(); | 210 m_clusterStack.removeLast(); |
210 } | 211 } |
211 } | 212 } |
212 | 213 |
(...skipping 14 matching lines...) Expand all Loading... |
227 } | 228 } |
228 | 229 |
229 bool FastTextAutosizer::enabled() | 230 bool FastTextAutosizer::enabled() |
230 { | 231 { |
231 if (!m_document->settings() || !m_document->page() || m_document->printing()
) | 232 if (!m_document->settings() || !m_document->page() || m_document->printing()
) |
232 return false; | 233 return false; |
233 | 234 |
234 return m_document->settings()->textAutosizingEnabled(); | 235 return m_document->settings()->textAutosizingEnabled(); |
235 } | 236 } |
236 | 237 |
237 void FastTextAutosizer::prepareRenderViewInfo() | 238 void FastTextAutosizer::updateRenderViewInfo() |
238 { | 239 { |
239 RenderView* renderView = toRenderView(m_document->renderer()); | 240 RenderView* renderView = toRenderView(m_document->renderer()); |
240 bool horizontalWritingMode = isHorizontalWritingMode(renderView->style()->wr
itingMode()); | 241 bool horizontalWritingMode = isHorizontalWritingMode(renderView->style()->wr
itingMode()); |
241 | 242 |
242 LocalFrame* mainFrame = m_document->page()->mainFrame(); | 243 LocalFrame* mainFrame = m_document->page()->mainFrame(); |
243 IntSize frameSize = m_document->settings()->textAutosizingWindowSizeOverride
(); | 244 IntSize frameSize = m_document->settings()->textAutosizingWindowSizeOverride
(); |
244 if (frameSize.isEmpty()) | 245 if (frameSize.isEmpty()) |
245 frameSize = mainFrame->view()->unscaledVisibleContentSize(IncludeScrollb
ars); | 246 frameSize = mainFrame->view()->unscaledVisibleContentSize(IncludeScrollb
ars); |
246 m_frameWidth = horizontalWritingMode ? frameSize.width() : frameSize.height(
); | 247 m_frameWidth = horizontalWritingMode ? frameSize.width() : frameSize.height(
); |
247 | 248 |
248 IntSize layoutSize = m_document->page()->mainFrame()->view()->layoutSize(); | 249 IntSize layoutSize = m_document->page()->mainFrame()->view()->layoutSize(); |
249 m_layoutWidth = horizontalWritingMode ? layoutSize.width() : layoutSize.heig
ht(); | 250 m_layoutWidth = horizontalWritingMode ? layoutSize.width() : layoutSize.heig
ht(); |
250 | 251 |
251 // Compute the base font scale multiplier based on device and accessibility
settings. | 252 // Compute the base font scale multiplier based on device and accessibility
settings. |
252 m_baseMultiplier = m_document->settings()->accessibilityFontScaleFactor(); | 253 m_baseMultiplier = m_document->settings()->accessibilityFontScaleFactor(); |
253 // If the page has a meta viewport or @viewport, don't apply the device scal
e adjustment. | 254 // If the page has a meta viewport or @viewport, don't apply the device scal
e adjustment. |
254 const ViewportDescription& viewportDescription = m_document->page()->mainFra
me()->document()->viewportDescription(); | 255 const ViewportDescription& viewportDescription = m_document->page()->mainFra
me()->document()->viewportDescription(); |
255 if (!viewportDescription.isSpecifiedByAuthor()) { | 256 if (!viewportDescription.isSpecifiedByAuthor()) { |
256 float deviceScaleAdjustment = m_document->settings()->deviceScaleAdjustm
ent(); | 257 float deviceScaleAdjustment = m_document->settings()->deviceScaleAdjustm
ent(); |
257 m_baseMultiplier *= deviceScaleAdjustment; | 258 m_baseMultiplier *= deviceScaleAdjustment; |
258 } | 259 } |
| 260 |
| 261 m_pageAutosizingStatus = m_frameWidth && (m_baseMultiplier * (static_cast<fl
oat>(m_layoutWidth) / m_frameWidth) > 1.0f) |
| 262 ? PageNeedsAutosizing : PageDoesNotNeedAutosizing; |
| 263 |
259 #ifndef NDEBUG | 264 #ifndef NDEBUG |
260 m_renderViewInfoPrepared = true; | 265 m_renderViewInfoPrepared = true; |
261 #endif | 266 #endif |
262 } | 267 } |
263 | 268 |
264 bool FastTextAutosizer::isFingerprintingCandidate(const RenderBlock* block) | 269 bool FastTextAutosizer::isFingerprintingCandidate(const RenderBlock* block) |
265 { | 270 { |
266 // FIXME: move the logic out of TextAutosizer.cpp into this class. | 271 // FIXME: move the logic out of TextAutosizer.cpp into this class. |
267 return block->isRenderView() | 272 return block->isRenderView() |
268 || (TextAutosizer::isAutosizingContainer(block) | 273 || (TextAutosizer::isAutosizingContainer(block) |
269 && (TextAutosizer::isIndependentDescendant(block) | 274 && (TextAutosizer::isIndependentDescendant(block) |
270 || mightBeWiderOrNarrowerDescendant(block))); | 275 || mightBeWiderOrNarrowerDescendant(block))); |
271 } | 276 } |
272 | 277 |
273 bool FastTextAutosizer::clusterWouldHaveEnoughTextToAutosize(const RenderBlock*
root, const RenderBlock* widthProvider) | 278 bool FastTextAutosizer::clusterWouldHaveEnoughTextToAutosize(const RenderBlock*
root, const RenderBlock* widthProvider) |
274 { | 279 { |
275 Cluster hypotheticalCluster(root, true, 0); | 280 Cluster hypotheticalCluster(root, true, 0); |
276 return clusterHasEnoughTextToAutosize(&hypotheticalCluster, widthProvider); | 281 return clusterHasEnoughTextToAutosize(&hypotheticalCluster, widthProvider); |
277 } | 282 } |
278 | 283 |
279 bool FastTextAutosizer::clusterHasEnoughTextToAutosize(Cluster* cluster, const R
enderBlock* widthProvider) | 284 bool FastTextAutosizer::clusterHasEnoughTextToAutosize(Cluster* cluster, const R
enderBlock* widthProvider) |
280 { | 285 { |
281 if (cluster->m_hasEnoughTextToAutosize != Unknown) | 286 if (cluster->m_hasEnoughTextToAutosize != UnknownAmountOfText) |
282 return cluster->m_hasEnoughTextToAutosize == Yes; | 287 return cluster->m_hasEnoughTextToAutosize == HasEnoughText; |
283 | 288 |
284 const RenderBlock* root = cluster->m_root; | 289 const RenderBlock* root = cluster->m_root; |
285 if (!widthProvider) | 290 if (!widthProvider) |
286 widthProvider = clusterWidthProvider(root); | 291 widthProvider = clusterWidthProvider(root); |
287 | 292 |
288 // TextAreas and user-modifiable areas get a free pass to autosize regardles
s of text content. | 293 // TextAreas and user-modifiable areas get a free pass to autosize regardles
s of text content. |
289 if (root->isTextArea() || (root->style() && root->style()->userModify() != R
EAD_ONLY)) { | 294 if (root->isTextArea() || (root->style() && root->style()->userModify() != R
EAD_ONLY)) { |
290 cluster->m_hasEnoughTextToAutosize = Yes; | 295 cluster->m_hasEnoughTextToAutosize = HasEnoughText; |
291 return true; | 296 return true; |
292 } | 297 } |
293 | 298 |
294 if (!TextAutosizer::containerShouldBeAutosized(root)) { | 299 if (!TextAutosizer::containerShouldBeAutosized(root)) { |
295 cluster->m_hasEnoughTextToAutosize = No; | 300 cluster->m_hasEnoughTextToAutosize = NotEnoughText; |
296 return false; | 301 return false; |
297 } | 302 } |
298 | 303 |
299 // 4 lines of text is considered enough to autosize. | 304 // 4 lines of text is considered enough to autosize. |
300 float minimumTextLengthToAutosize = widthFromBlock(widthProvider) * 4; | 305 float minimumTextLengthToAutosize = widthFromBlock(widthProvider) * 4; |
301 | 306 |
302 float length = 0; | 307 float length = 0; |
303 RenderObject* descendant = root->nextInPreOrder(root); | 308 RenderObject* descendant = root->nextInPreOrder(root); |
304 while (descendant) { | 309 while (descendant) { |
305 if (descendant->isRenderBlock()) { | 310 if (descendant->isRenderBlock()) { |
306 RenderBlock* block = toRenderBlock(descendant); | 311 RenderBlock* block = toRenderBlock(descendant); |
307 if (TextAutosizer::isAutosizingContainer(block)) { | 312 if (TextAutosizer::isAutosizingContainer(block)) { |
308 // Note: Ideally we would check isWiderOrNarrowerDescendant here
but we only know that | 313 // Note: Ideally we would check isWiderOrNarrowerDescendant here
but we only know that |
309 // after the block has entered layout, which may not be th
e case. | 314 // after the block has entered layout, which may not be th
e case. |
310 bool isAutosizingClusterRoot = TextAutosizer::isIndependentDesce
ndant(block); | 315 bool isAutosizingClusterRoot = TextAutosizer::isIndependentDesce
ndant(block); |
311 if (isAutosizingClusterRoot || !TextAutosizer::containerShouldBe
Autosized(block)) { | 316 if (isAutosizingClusterRoot || !TextAutosizer::containerShouldBe
Autosized(block)) { |
312 descendant = descendant->nextInPreOrderAfterChildren(root); | 317 descendant = descendant->nextInPreOrderAfterChildren(root); |
313 continue; | 318 continue; |
314 } | 319 } |
315 } | 320 } |
316 } else if (descendant->isText()) { | 321 } else if (descendant->isText()) { |
317 // Note: Using text().stripWhiteSpace().length() instead of rendered
TextLength() because | 322 // Note: Using text().stripWhiteSpace().length() instead of rendered
TextLength() because |
318 // the lineboxes will not be built until layout. These values can be
different. | 323 // the lineboxes will not be built until layout. These values can be
different. |
319 // Note: This is an approximation assuming each character is 1em wid
e. | 324 // Note: This is an approximation assuming each character is 1em wid
e. |
320 length += toRenderText(descendant)->text().stripWhiteSpace().length(
) * descendant->style()->specifiedFontSize(); | 325 length += toRenderText(descendant)->text().stripWhiteSpace().length(
) * descendant->style()->specifiedFontSize(); |
321 | 326 |
322 if (length >= minimumTextLengthToAutosize) { | 327 if (length >= minimumTextLengthToAutosize) { |
323 cluster->m_hasEnoughTextToAutosize = Yes; | 328 cluster->m_hasEnoughTextToAutosize = HasEnoughText; |
324 return true; | 329 return true; |
325 } | 330 } |
326 } | 331 } |
327 descendant = descendant->nextInPreOrder(root); | 332 descendant = descendant->nextInPreOrder(root); |
328 } | 333 } |
329 | 334 |
330 cluster->m_hasEnoughTextToAutosize = No; | 335 cluster->m_hasEnoughTextToAutosize = NotEnoughText; |
331 return false; | 336 return false; |
332 } | 337 } |
333 | 338 |
334 FastTextAutosizer::Fingerprint FastTextAutosizer::getFingerprint(const RenderObj
ect* renderer) | 339 FastTextAutosizer::Fingerprint FastTextAutosizer::getFingerprint(const RenderObj
ect* renderer) |
335 { | 340 { |
336 Fingerprint result = m_fingerprintMapper.get(renderer); | 341 Fingerprint result = m_fingerprintMapper.get(renderer); |
337 if (!result) { | 342 if (!result) { |
338 result = computeFingerprint(renderer); | 343 result = computeFingerprint(renderer); |
339 m_fingerprintMapper.add(renderer, result); | 344 m_fingerprintMapper.add(renderer, result); |
340 } | 345 } |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 | 515 |
511 float FastTextAutosizer::multiplierFromBlock(const RenderBlock* block) | 516 float FastTextAutosizer::multiplierFromBlock(const RenderBlock* block) |
512 { | 517 { |
513 // If block->needsLayout() is false, it does not need to be in m_blocksThatH
aveBegunLayout. | 518 // If block->needsLayout() is false, it does not need to be in m_blocksThatH
aveBegunLayout. |
514 // This can happen during layout of a positioned object if the cluster's DBC
AT is deeper | 519 // This can happen during layout of a positioned object if the cluster's DBC
AT is deeper |
515 // than the positioned object's containing block, and wasn't marked as needi
ng layout. | 520 // than the positioned object's containing block, and wasn't marked as needi
ng layout. |
516 ASSERT(m_blocksThatHaveBegunLayout.contains(block) || !block->needsLayout())
; | 521 ASSERT(m_blocksThatHaveBegunLayout.contains(block) || !block->needsLayout())
; |
517 | 522 |
518 // Block width, in CSS pixels. | 523 // Block width, in CSS pixels. |
519 float blockWidth = widthFromBlock(block); | 524 float blockWidth = widthFromBlock(block); |
520 float multiplier = min(blockWidth, static_cast<float>(m_layoutWidth)) / m_fr
ameWidth; | 525 float multiplier = m_frameWidth ? min(blockWidth, static_cast<float>(m_layou
tWidth)) / m_frameWidth : 1.0f; |
521 | 526 |
522 return max(m_baseMultiplier * multiplier, 1.0f); | 527 return max(m_baseMultiplier * multiplier, 1.0f); |
523 } | 528 } |
524 | 529 |
525 const RenderBlock* FastTextAutosizer::deepestBlockContainingAllText(Cluster* clu
ster) | 530 const RenderBlock* FastTextAutosizer::deepestBlockContainingAllText(Cluster* clu
ster) |
526 { | 531 { |
527 if (!cluster->m_deepestBlockContainingAllText) | 532 if (!cluster->m_deepestBlockContainingAllText) |
528 cluster->m_deepestBlockContainingAllText = deepestBlockContainingAllText
(cluster->m_root); | 533 cluster->m_deepestBlockContainingAllText = deepestBlockContainingAllText
(cluster->m_root); |
529 | 534 |
530 return cluster->m_deepestBlockContainingAllText; | 535 return cluster->m_deepestBlockContainingAllText; |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
695 return *m_blocksForFingerprint.get(fingerprint); | 700 return *m_blocksForFingerprint.get(fingerprint); |
696 } | 701 } |
697 | 702 |
698 RenderObject* FastTextAutosizer::nextChildSkippingChildrenOfBlocks(const RenderO
bject* current, const RenderObject* stayWithin) | 703 RenderObject* FastTextAutosizer::nextChildSkippingChildrenOfBlocks(const RenderO
bject* current, const RenderObject* stayWithin) |
699 { | 704 { |
700 if (current == stayWithin || !current->isRenderBlock()) | 705 if (current == stayWithin || !current->isRenderBlock()) |
701 return current->nextInPreOrder(stayWithin); | 706 return current->nextInPreOrder(stayWithin); |
702 return current->nextInPreOrderAfterChildren(stayWithin); | 707 return current->nextInPreOrderAfterChildren(stayWithin); |
703 } | 708 } |
704 | 709 |
| 710 FastTextAutosizer::LayoutScope::LayoutScope(RenderBlock* block) |
| 711 : m_textAutosizer(block->document().fastTextAutosizer()) |
| 712 , m_block(block) |
| 713 { |
| 714 if (!m_textAutosizer) |
| 715 return; |
| 716 |
| 717 if (!m_textAutosizer->enabled()) { |
| 718 m_textAutosizer = 0; |
| 719 return; |
| 720 } |
| 721 |
| 722 if (m_textAutosizer->m_pageAutosizingStatus == PageAutosizingStatusUnknown) |
| 723 m_textAutosizer->updateRenderViewInfo(); |
| 724 |
| 725 if (m_textAutosizer->m_pageAutosizingStatus == PageNeedsAutosizing) |
| 726 m_textAutosizer->beginLayout(m_block); |
| 727 else |
| 728 m_textAutosizer = 0; |
| 729 } |
| 730 |
| 731 FastTextAutosizer::LayoutScope::~LayoutScope() |
| 732 { |
| 733 if (m_textAutosizer) |
| 734 m_textAutosizer->endLayout(m_block); |
| 735 } |
| 736 |
705 } // namespace WebCore | 737 } // namespace WebCore |
OLD | NEW |