Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Side by Side Diff: Source/core/rendering/RenderRegion.cpp

Issue 143323014: *** DO NOT LAND *** Attempt to understand Regions complexity Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/rendering/RenderRegion.h ('k') | Source/core/rendering/RenderRegionSet.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2011 Adobe Systems Incorporated. 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
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include "config.h"
31 #include "core/rendering/RenderRegion.h"
32
33 #include "core/css/resolver/StyleResolver.h"
34 #include "core/rendering/FlowThreadController.h"
35 #include "core/rendering/HitTestLocation.h"
36 #include "core/rendering/PaintInfo.h"
37 #include "core/rendering/RenderBoxRegionInfo.h"
38 #include "core/rendering/RenderNamedFlowThread.h"
39 #include "core/rendering/RenderView.h"
40
41 using namespace std;
42
43 namespace WebCore {
44
45 RenderRegion::RenderRegion(Element* element, RenderFlowThread* flowThread)
46 : RenderBlockFlow(element)
47 , m_flowThread(flowThread)
48 , m_parentNamedFlowThread(0)
49 , m_computedAutoHeight(-1)
50 , m_isValid(false)
51 , m_hasCustomRegionStyle(false)
52 , m_hasAutoLogicalHeight(false)
53 {
54 }
55
56 LayoutUnit RenderRegion::pageLogicalWidth() const
57 {
58 ASSERT(m_flowThread);
59 return m_flowThread->isHorizontalWritingMode() ? contentWidth() : contentHei ght();
60 }
61
62 LayoutUnit RenderRegion::pageLogicalHeight() const
63 {
64 ASSERT(m_flowThread);
65 if (hasComputedAutoHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
66 ASSERT(hasAutoLogicalHeight());
67 return computedAutoHeight();
68 }
69 return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWi dth();
70 }
71
72 // This method returns the maximum page size of a region with auto-height. This is the initial
73 // height value for auto-height regions in the first layout phase of the parent named flow.
74 LayoutUnit RenderRegion::maxPageLogicalHeight() const
75 {
76 ASSERT(m_flowThread);
77 ASSERT(hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase());
78 return style()->logicalMaxHeight().isUndefined() ? RenderFlowThread::maxLogi calHeight() : computeReplacedLogicalHeightUsing(style()->logicalMaxHeight());
79 }
80
81 LayoutUnit RenderRegion::logicalHeightOfAllFlowThreadContent() const
82 {
83 ASSERT(m_flowThread);
84 if (hasComputedAutoHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
85 ASSERT(hasAutoLogicalHeight());
86 return computedAutoHeight();
87 }
88 return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWi dth();
89 }
90
91 LayoutRect RenderRegion::flowThreadPortionOverflowRect() const
92 {
93 return overflowRectForFlowThreadPortion(flowThreadPortionRect(), isFirstRegi on(), isLastRegion());
94 }
95
96 LayoutRect RenderRegion::overflowRectForFlowThreadPortion(const LayoutRect& flow ThreadPortionRect, bool isFirstPortion, bool isLastPortion) const
97 {
98 ASSERT(isValid());
99
100 bool isLastRegionWithRegionFragmentBreak = (isLastPortion && (style()->regio nFragment() == BreakRegionFragment));
101 if (hasOverflowClip() || isLastRegionWithRegionFragmentBreak)
102 return flowThreadPortionRect;
103
104 LayoutRect flowThreadOverflow = m_flowThread->visualOverflowRect();
105
106 // Only clip along the flow thread axis.
107 LayoutUnit outlineSize = maximalOutlineSize(PaintPhaseOutline);
108 LayoutRect clipRect;
109 if (m_flowThread->isHorizontalWritingMode()) {
110 LayoutUnit minY = isFirstPortion ? (flowThreadOverflow.y() - outlineSize ) : flowThreadPortionRect.y();
111 LayoutUnit maxY = isLastPortion ? max(flowThreadPortionRect.maxY(), flow ThreadOverflow.maxY()) + outlineSize : flowThreadPortionRect.maxY();
112 bool clipX = style()->overflowX() != OVISIBLE;
113 LayoutUnit minX = clipX ? flowThreadPortionRect.x() : min(flowThreadPort ionRect.x(), flowThreadOverflow.x() - outlineSize);
114 LayoutUnit maxX = clipX ? flowThreadPortionRect.maxX() : max(flowThreadP ortionRect.maxX(), (flowThreadOverflow.maxX() + outlineSize));
115 clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
116 } else {
117 LayoutUnit minX = isFirstPortion ? (flowThreadOverflow.x() - outlineSize ) : flowThreadPortionRect.x();
118 LayoutUnit maxX = isLastPortion ? max(flowThreadPortionRect.maxX(), flow ThreadOverflow.maxX()) + outlineSize : flowThreadPortionRect.maxX();
119 bool clipY = style()->overflowY() != OVISIBLE;
120 LayoutUnit minY = clipY ? flowThreadPortionRect.y() : min(flowThreadPort ionRect.y(), (flowThreadOverflow.y() - outlineSize));
121 LayoutUnit maxY = clipY ? flowThreadPortionRect.maxY() : max(flowThreadP ortionRect.y(), (flowThreadOverflow.maxY() + outlineSize));
122 clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
123 }
124
125 return clipRect;
126 }
127
128 RegionOversetState RenderRegion::regionOversetState() const
129 {
130 if (isValid() && element())
131 return element()->regionOversetState();
132
133 return RegionUndefined;
134 }
135
136 void RenderRegion::setRegionOversetState(RegionOversetState state)
137 {
138 if (element())
139 element()->setRegionOversetState(state);
140 }
141
142 Element* RenderRegion::element() const
143 {
144 ASSERT(nodeForRegion() && nodeForRegion()->isElementNode());
145 return toElement(nodeForRegion());
146 }
147
148 LayoutUnit RenderRegion::pageLogicalTopForOffset(LayoutUnit /* offset */) const
149 {
150 return flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x();
151 }
152
153 bool RenderRegion::isFirstRegion() const
154 {
155 ASSERT(isValid());
156
157 return m_flowThread->firstRegion() == this;
158 }
159
160 bool RenderRegion::isLastRegion() const
161 {
162 ASSERT(isValid());
163
164 return m_flowThread->lastRegion() == this;
165 }
166
167 static bool shouldPaintRegionContentsInPhase(PaintPhase phase)
168 {
169 return phase == PaintPhaseForeground
170 || phase == PaintPhaseSelection
171 || phase == PaintPhaseTextClip;
172 }
173
174 void RenderRegion::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOff set)
175 {
176 if (style()->visibility() != VISIBLE)
177 return;
178
179 RenderBlock::paintObject(paintInfo, paintOffset);
180
181 if (!isValid())
182 return;
183
184 // Delegate painting of content in region to RenderFlowThread.
185 // RenderFlowThread is a self painting layer (being a positioned object) who is painting its children, the collected objects.
186 // Since we do not want to paint the flow thread content multiple times (for each painting phase of the region object),
187 // we allow the flow thread painting only in certain phases.
188 if (!shouldPaintRegionContentsInPhase(paintInfo.phase))
189 return;
190
191 setRegionObjectsRegionStyle();
192 m_flowThread->paintFlowThreadPortionInRegion(paintInfo, this, flowThreadPort ionRect(), flowThreadPortionOverflowRect(), LayoutPoint(paintOffset.x() + border Left() + paddingLeft(), paintOffset.y() + borderTop() + paddingTop()));
193 restoreRegionObjectsOriginalStyle();
194 }
195
196 // Hit Testing
197 bool RenderRegion::hitTestFlowThreadContents(const HitTestRequest& request, HitT estResult& result, const HitTestLocation& locationInContainer, const LayoutPoint & accumulatedOffset, HitTestAction action)
198 {
199 if (!isValid() || action != HitTestForeground)
200 return false;
201
202 LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
203 boundsRect.moveBy(accumulatedOffset);
204 if (visibleToHitTesting() && locationInContainer.intersects(boundsRect)) {
205 if (m_flowThread->hitTestFlowThreadPortionInRegion(this, flowThreadPorti onRect(), flowThreadPortionOverflowRect(), request, result,
206 locationInContainer, LayoutPoint(accumulatedOffset.x() + borderLeft( ) + paddingLeft(), accumulatedOffset.y() + borderTop() + paddingTop())))
207 return true;
208 }
209
210 return false;
211 }
212
213 void RenderRegion::checkRegionStyle()
214 {
215 ASSERT(m_flowThread);
216 bool customRegionStyle = false;
217
218 // FIXME: Region styling doesn't work for pseudo elements.
219 if (isElementBasedRegion())
220 customRegionStyle = view()->document().ensureStyleResolver().checkRegion Style(this->element());
221
222 setHasCustomRegionStyle(customRegionStyle);
223 m_flowThread->checkRegionsWithStyling();
224 }
225
226 void RenderRegion::incrementAutoLogicalHeightCount()
227 {
228 ASSERT(isValid());
229 ASSERT(m_hasAutoLogicalHeight);
230
231 m_flowThread->incrementAutoLogicalHeightRegions();
232 }
233
234 void RenderRegion::decrementAutoLogicalHeightCount()
235 {
236 ASSERT(isValid());
237
238 m_flowThread->decrementAutoLogicalHeightRegions();
239 }
240
241 void RenderRegion::updateRegionHasAutoLogicalHeightFlag()
242 {
243 ASSERT(m_flowThread);
244
245 if (!isValid())
246 return;
247
248 bool didHaveAutoLogicalHeight = m_hasAutoLogicalHeight;
249 m_hasAutoLogicalHeight = shouldHaveAutoLogicalHeight();
250 if (m_hasAutoLogicalHeight != didHaveAutoLogicalHeight) {
251 if (m_hasAutoLogicalHeight) {
252 incrementAutoLogicalHeightCount();
253 } else {
254 clearComputedAutoHeight();
255 decrementAutoLogicalHeightCount();
256 }
257 }
258 }
259
260 bool RenderRegion::shouldHaveAutoLogicalHeight() const
261 {
262 bool hasSpecifiedEndpointsForHeight = style()->logicalTop().isSpecified() && style()->logicalBottom().isSpecified();
263 bool hasAnchoredEndpointsForHeight = isOutOfFlowPositioned() && hasSpecified EndpointsForHeight;
264 bool hasAutoHeightStyle = style()->logicalHeight().isAuto() || style()->logi calHeight().isFitContent()
265 || style()->logicalHeight().isMaxContent() || style()->logicalHeight().i sMinContent();
266 return hasAutoHeightStyle && !hasAnchoredEndpointsForHeight;
267 }
268
269 void RenderRegion::styleDidChange(StyleDifference diff, const RenderStyle* oldSt yle)
270 {
271 RenderBlock::styleDidChange(diff, oldStyle);
272
273 // If the region is not attached to any thread, there is no need to check
274 // whether the region has region styling since no content will be displayed
275 // into the region.
276 if (!m_flowThread) {
277 setHasCustomRegionStyle(false);
278 return;
279 }
280
281 checkRegionStyle();
282 updateRegionHasAutoLogicalHeightFlag();
283
284 if (oldStyle && oldStyle->writingMode() != style()->writingMode())
285 m_flowThread->regionChangedWritingMode(this);
286 }
287
288 void RenderRegion::layoutBlock(bool relayoutChildren)
289 {
290 RenderBlockFlow::layoutBlock(relayoutChildren);
291
292 if (isValid()) {
293 LayoutRect oldRegionRect(flowThreadPortionRect());
294 if (!isHorizontalWritingMode())
295 oldRegionRect = oldRegionRect.transposedRect();
296
297 if (hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
298 m_flowThread->invalidateRegions();
299 clearComputedAutoHeight();
300 return;
301 }
302
303 if (!isRenderRegionSet() && (oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != pageLogicalHeight())) {
304 // This can happen even if we are in the inConstrainedLayoutPhase an d it will trigger a pathological layout of the flow thread.
305 m_flowThread->invalidateRegions();
306 }
307 }
308
309 // FIXME: We need to find a way to set up overflow properly. Our flow thread hasn't gotten a layout
310 // yet, so we can't look to it for correct information. It's possible we cou ld wait until after the RenderFlowThread
311 // gets a layout, and then try to propagate overflow information back to the region, and then mark for a second layout.
312 // That second layout would then be able to use the information from the Ren derFlowThread to set up overflow.
313 //
314 // The big problem though is that overflow needs to be region-specific. We c an't simply use the RenderFlowThread's global
315 // overflow values, since then we'd always think any narrow region had huge overflow (all the way to the width of the
316 // RenderFlowThread itself).
317 //
318 // We'll need to expand RenderBoxRegionInfo to also hold left and right over flow values.
319 }
320
321 void RenderRegion::repaintFlowThreadContent(const LayoutRect& repaintRect) const
322 {
323 repaintFlowThreadContentRectangle(repaintRect, flowThreadPortionRect(), flow ThreadPortionOverflowRect(), contentBoxRect().location());
324 }
325
326 void RenderRegion::repaintFlowThreadContentRectangle(const LayoutRect& repaintRe ct, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortion OverflowRect, const LayoutPoint& regionLocation) const
327 {
328 ASSERT(isValid());
329
330 // We only have to issue a repaint in this region if the region rect interse cts the repaint rect.
331 LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
332 LayoutRect flippedFlowThreadPortionOverflowRect(flowThreadPortionOverflowRec t);
333 flowThread()->flipForWritingMode(flippedFlowThreadPortionRect); // Put the r egion rects into physical coordinates.
334 flowThread()->flipForWritingMode(flippedFlowThreadPortionOverflowRect);
335
336 LayoutRect clippedRect(repaintRect);
337 clippedRect.intersect(flippedFlowThreadPortionOverflowRect);
338 if (clippedRect.isEmpty())
339 return;
340
341 // Put the region rect into the region's physical coordinate space.
342 clippedRect.setLocation(regionLocation + (clippedRect.location() - flippedFl owThreadPortionRect.location()));
343
344 // Now switch to the region's writing mode coordinate space and let it repai nt itself.
345 flipForWritingMode(clippedRect);
346
347 // Issue the repaint.
348 repaintRectangle(clippedRect);
349 }
350
351 void RenderRegion::installFlowThread()
352 {
353 ASSERT(view());
354
355 m_flowThread = view()->flowThreadController()->ensureRenderFlowThreadWithNam e(style()->regionThread());
356
357 // By now the flow thread should already be added to the rendering tree,
358 // so we go up the rendering parents and check that this region is not part of the same
359 // flow that it actually needs to display. It would create a circular refere nce.
360 RenderObject* parentObject = parent();
361 m_parentNamedFlowThread = 0;
362 for ( ; parentObject; parentObject = parentObject->parent()) {
363 if (parentObject->isRenderNamedFlowThread()) {
364 m_parentNamedFlowThread = toRenderNamedFlowThread(parentObject);
365 // Do not take into account a region that links a flow with itself. The dependency
366 // cannot change, so it is not worth adding it to the list.
367 if (m_flowThread == m_parentNamedFlowThread)
368 m_flowThread = 0;
369 break;
370 }
371 }
372 }
373
374 void RenderRegion::attachRegion()
375 {
376 if (documentBeingDestroyed())
377 return;
378
379 // A region starts off invalid.
380 setIsValid(false);
381
382 // Initialize the flow thread reference and create the flow thread object if needed.
383 // The flow thread lifetime is influenced by the number of regions attached to it,
384 // and we are attaching the region to the flow thread.
385 installFlowThread();
386
387 if (!m_flowThread)
388 return;
389
390 // Only after adding the region to the thread, the region is marked to be va lid.
391 m_flowThread->addRegionToThread(this);
392
393 // The region just got attached to the flow thread, lets check whether
394 // it has region styling rules associated.
395 checkRegionStyle();
396
397 if (!isValid())
398 return;
399
400 m_hasAutoLogicalHeight = shouldHaveAutoLogicalHeight();
401 if (hasAutoLogicalHeight())
402 incrementAutoLogicalHeightCount();
403 }
404
405 void RenderRegion::detachRegion()
406 {
407 if (m_flowThread) {
408 m_flowThread->removeRegionFromThread(this);
409 if (hasAutoLogicalHeight())
410 decrementAutoLogicalHeightCount();
411 }
412 m_flowThread = 0;
413 }
414
415 RenderBoxRegionInfo* RenderRegion::renderBoxRegionInfo(const RenderBox* box) con st
416 {
417 ASSERT(isValid());
418 return m_renderBoxRegionInfo.get(box);
419 }
420
421 RenderBoxRegionInfo* RenderRegion::setRenderBoxRegionInfo(const RenderBox* box, LayoutUnit logicalLeftInset, LayoutUnit logicalRightInset,
422 bool containingBlockChainIsInset)
423 {
424 ASSERT(isValid());
425
426 OwnPtr<RenderBoxRegionInfo>& boxInfo = m_renderBoxRegionInfo.add(box, nullpt r).iterator->value;
427 if (boxInfo)
428 *boxInfo = RenderBoxRegionInfo(logicalLeftInset, logicalRightInset, cont ainingBlockChainIsInset);
429 else
430 boxInfo = adoptPtr(new RenderBoxRegionInfo(logicalLeftInset, logicalRigh tInset, containingBlockChainIsInset));
431
432 return boxInfo.get();
433 }
434
435 PassOwnPtr<RenderBoxRegionInfo> RenderRegion::takeRenderBoxRegionInfo(const Rend erBox* box)
436 {
437 return m_renderBoxRegionInfo.take(box);
438 }
439
440 void RenderRegion::removeRenderBoxRegionInfo(const RenderBox* box)
441 {
442 m_renderBoxRegionInfo.remove(box);
443 }
444
445 void RenderRegion::deleteAllRenderBoxRegionInfo()
446 {
447 m_renderBoxRegionInfo.clear();
448 }
449
450 LayoutUnit RenderRegion::logicalTopOfFlowThreadContentRect(const LayoutRect& rec t) const
451 {
452 ASSERT(isValid());
453 return flowThread()->isHorizontalWritingMode() ? rect.y() : rect.x();
454 }
455
456 LayoutUnit RenderRegion::logicalBottomOfFlowThreadContentRect(const LayoutRect& rect) const
457 {
458 ASSERT(isValid());
459 return flowThread()->isHorizontalWritingMode() ? rect.maxY() : rect.maxX();
460 }
461
462 void RenderRegion::setRegionObjectsRegionStyle()
463 {
464 if (!hasCustomRegionStyle())
465 return;
466
467 // Start from content nodes and recursively compute the style in region for the render objects below.
468 // If the style in region was already computed, used that style instead of c omputing a new one.
469 RenderNamedFlowThread* namedFlow = view()->flowThreadController()->ensureRen derFlowThreadWithName(style()->regionThread());
470 const NamedFlowContentNodes& contentNodes = namedFlow->contentNodes();
471
472 for (NamedFlowContentNodes::const_iterator iter = contentNodes.begin(), end = contentNodes.end(); iter != end; ++iter) {
473 const Node* node = *iter;
474 // The list of content nodes contains also the nodes with display:none.
475 if (!node->renderer())
476 continue;
477
478 RenderObject* object = node->renderer();
479 // If the content node does not flow any of its children in this region,
480 // we do not compute any style for them in this region.
481 if (!flowThread()->objectInFlowRegion(object, this))
482 continue;
483
484 // If the object has style in region, use that instead of computing a ne w one.
485 RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find (object);
486 RefPtr<RenderStyle> objectStyleInRegion;
487 bool objectRegionStyleCached = false;
488 if (it != m_renderObjectRegionStyle.end()) {
489 objectStyleInRegion = it->value.style;
490 ASSERT(it->value.cached);
491 objectRegionStyleCached = true;
492 } else {
493 objectStyleInRegion = computeStyleInRegion(object);
494 }
495
496 setObjectStyleInRegion(object, objectStyleInRegion, objectRegionStyleCac hed);
497
498 computeChildrenStyleInRegion(object);
499 }
500 }
501
502 void RenderRegion::restoreRegionObjectsOriginalStyle()
503 {
504 if (!hasCustomRegionStyle())
505 return;
506
507 RenderObjectRegionStyleMap temp;
508 for (RenderObjectRegionStyleMap::iterator iter = m_renderObjectRegionStyle.b egin(), end = m_renderObjectRegionStyle.end(); iter != end; ++iter) {
509 RenderObject* object = const_cast<RenderObject*>(iter->key);
510 RefPtr<RenderStyle> objectRegionStyle = object->style();
511 RefPtr<RenderStyle> objectOriginalStyle = iter->value.style;
512 object->setStyleInternal(objectOriginalStyle);
513
514 bool shouldCacheRegionStyle = iter->value.cached;
515 if (!shouldCacheRegionStyle) {
516 // Check whether we should cache the computed style in region.
517 unsigned changedContextSensitiveProperties = ContextSensitivePropert yNone;
518 StyleDifference styleDiff = objectOriginalStyle->diff(objectRegionSt yle.get(), changedContextSensitiveProperties);
519 if (styleDiff < StyleDifferenceLayoutPositionedMovementOnly)
520 shouldCacheRegionStyle = true;
521 }
522 if (shouldCacheRegionStyle) {
523 ObjectRegionStyleInfo styleInfo;
524 styleInfo.style = objectRegionStyle;
525 styleInfo.cached = true;
526 temp.set(object, styleInfo);
527 }
528 }
529
530 m_renderObjectRegionStyle.swap(temp);
531 }
532
533 void RenderRegion::insertedIntoTree()
534 {
535 RenderBlock::insertedIntoTree();
536
537 attachRegion();
538 }
539
540 void RenderRegion::willBeRemovedFromTree()
541 {
542 RenderBlock::willBeRemovedFromTree();
543
544 detachRegion();
545 }
546
547 PassRefPtr<RenderStyle> RenderRegion::computeStyleInRegion(const RenderObject* o bject)
548 {
549 ASSERT(object);
550 ASSERT(object->view());
551 ASSERT(!object->isAnonymous());
552 ASSERT(object->node() && object->node()->isElementNode());
553
554 // FIXME: Region styling fails for pseudo-elements because the renderers don 't have a node.
555 Element* element = toElement(object->node());
556 RefPtr<RenderStyle> renderObjectRegionStyle = object->view()->document().ens ureStyleResolver().styleForElement(element, 0, DisallowStyleSharing, MatchAllRul es, this);
557
558 return renderObjectRegionStyle.release();
559 }
560
561 void RenderRegion::computeChildrenStyleInRegion(const RenderObject* object)
562 {
563 for (RenderObject* child = object->lastChild(); child; child = child->previo usSibling()) {
564
565 RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find (child);
566
567 RefPtr<RenderStyle> childStyleInRegion;
568 bool objectRegionStyleCached = false;
569 if (it != m_renderObjectRegionStyle.end()) {
570 childStyleInRegion = it->value.style;
571 objectRegionStyleCached = true;
572 } else {
573 if (child->isAnonymous() || child->isInFlowRenderFlowThread())
574 childStyleInRegion = RenderStyle::createAnonymousStyleWithDispla y(object->style(), child->style()->display());
575 else if (child->isText())
576 childStyleInRegion = RenderStyle::clone(object->style());
577 else
578 childStyleInRegion = computeStyleInRegion(child);
579 }
580
581 setObjectStyleInRegion(child, childStyleInRegion, objectRegionStyleCache d);
582
583 computeChildrenStyleInRegion(child);
584 }
585 }
586
587 void RenderRegion::setObjectStyleInRegion(RenderObject* object, PassRefPtr<Rende rStyle> styleInRegion, bool objectRegionStyleCached)
588 {
589 ASSERT(object->flowThreadContainingBlock());
590
591 RefPtr<RenderStyle> objectOriginalStyle = object->style();
592 object->setStyleInternal(styleInRegion);
593
594 if (object->isBoxModelObject() && !object->hasBoxDecorations()) {
595 bool hasBoxDecorations = object->isTableCell()
596 || object->style()->hasBackground()
597 || object->style()->hasBorder()
598 || object->style()->hasAppearance()
599 || object->style()->boxShadow();
600 object->setHasBoxDecorations(hasBoxDecorations);
601 }
602
603 ObjectRegionStyleInfo styleInfo;
604 styleInfo.style = objectOriginalStyle;
605 styleInfo.cached = objectRegionStyleCached;
606 m_renderObjectRegionStyle.set(object, styleInfo);
607 }
608
609 void RenderRegion::clearObjectStyleInRegion(const RenderObject* object)
610 {
611 ASSERT(object);
612 m_renderObjectRegionStyle.remove(object);
613
614 // Clear the style for the children of this object.
615 for (RenderObject* child = object->lastChild(); child; child = child->previo usSibling())
616 clearObjectStyleInRegion(child);
617 }
618
619 void RenderRegion::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, La youtUnit& maxLogicalWidth) const
620 {
621 if (!isValid()) {
622 RenderBlock::computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWi dth);
623 return;
624 }
625
626 minLogicalWidth = m_flowThread->minPreferredLogicalWidth();
627 maxLogicalWidth = m_flowThread->maxPreferredLogicalWidth();
628 }
629
630 void RenderRegion::getRanges(Vector<RefPtr<Range> >& rangeObjects) const
631 {
632 RenderNamedFlowThread* namedFlow = view()->flowThreadController()->ensureRen derFlowThreadWithName(style()->regionThread());
633 namedFlow->getRanges(rangeObjects, this);
634 }
635
636 void RenderRegion::updateLogicalHeight()
637 {
638 RenderBlock::updateLogicalHeight();
639
640 if (!hasAutoLogicalHeight())
641 return;
642
643 // We want to update the logical height based on the computed auto-height
644 // only if the view is in the layout phase in which all the
645 // auto logical height regions have a computed auto-height.
646 if (!m_flowThread->inConstrainedLayoutPhase())
647 return;
648
649 // There may be regions with auto logical height that during the prerequisit e layout phase
650 // did not have the chance to layout flow thread content. Because of that, t hese regions do not
651 // have a computedAutoHeight and they will not be able to fragment any flow
652 // thread content.
653 if (!hasComputedAutoHeight())
654 return;
655
656 LayoutUnit autoHeight = hasOverrideHeight() ? overrideLogicalContentHeight() : computedAutoHeight();
657
658 LayoutUnit newLogicalHeight = autoHeight + borderAndPaddingLogicalHeight();
659 ASSERT(newLogicalHeight < RenderFlowThread::maxLogicalHeight());
660 if (newLogicalHeight > logicalHeight()) {
661 setLogicalHeight(newLogicalHeight);
662 // Recalculate position of the render block after new logical height is set.
663 // (needed in absolute positioning case with bottom alignment for exampl e)
664 RenderBlock::updateLogicalHeight();
665 }
666 }
667
668 Node* RenderRegion::nodeForRegion() const
669 {
670 if (parent() && isRenderNamedFlowFragment())
671 return parent()->node();
672 return node();
673 }
674
675 Node* RenderRegion::generatingNodeForRegion() const
676 {
677 if (parent() && isRenderNamedFlowFragment())
678 return parent()->generatingNode();
679 return generatingNode();
680 }
681
682 bool RenderRegion::isElementBasedRegion() const
683 {
684 Node* node = nodeForRegion();
685 return node && node->isElementNode() && !node->isPseudoElement();
686 }
687
688 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderRegion.h ('k') | Source/core/rendering/RenderRegionSet.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698