Changeset 156022 in webkit


Ignore:
Timestamp:
Sep 17, 2013 8:27:35 PM (11 years ago)
Author:
zoltan@webkit.org
Message:

[CSS Shapes] Use the float height to determine position in shape-inside
https://bugs.webkit.org/show_bug.cgi?id=102846

Reviewed by Darin Adler.

Float positioning inside shape-inside has been working only for simple cases when the float boundaries didn't overlap with the shape.
This patch fixes the behavior for left floats and shapes with inline content. I want to add this work step by step, therefore the next
step would be to add support for block content with inline content (e.g. paragraphs) then cover cases with right floats.

Source/WebCore:

Tests: fast/shapes/shape-inside/shape-inside-left-float-in-lower-left-triangle-inline-content.html

fast/shapes/shape-inside/shape-inside-left-float-in-lower-right-triangle-inline-content.html
fast/shapes/shape-inside/shape-inside-left-float-in-upper-left-triangle-inline-content.html
fast/shapes/shape-inside/shape-inside-left-float-in-upper-right-triangle-inline-content.html

  • rendering/LineWidth.cpp:

(WebCore::LineWidth::LineWidth): Use the new updateCurrentShapeSegment member function.
(WebCore::LineWidth::updateCurrentShapeSegment): We need a function to update the current line segment's reference, since we use it multiple places.

  • rendering/LineWidth.h: Add new member function.
  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::computeLogicalLocationForFloat): Fix positioning of a floating element.

  • rendering/RenderBlockLineLayout.cpp:

(WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLine): Use updateSegmentsForLine instead of computeSegmentsForLine.
(WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLineInFlowThread): Use updateSegmentsForLine instead of computeSegmentsForLine.
(WebCore::RenderBlock::adjustLogicalLineTopAndLogicalHeightIfNeeded):
(WebCore::updateSegmentsForShapes): After our float is positioned, we need to adjust the current lineTop and update the logical height to be able to wrap around the float.
(WebCore::RenderBlock::LineBreaker::nextSegmentBreak): If we have a float in our line we might need to adjust our lineTop and logicalHeight.

  • rendering/shapes/ShapeInfo.cpp:

(WebCore::::computeSegmentsForLine): Add new const function to compute the segments. I'd like make this function static later if possible.
(WebCore::::updateSegmentsForLine): Old computeSegmentsForLine, change name to indicate that it is actually changing things.

  • rendering/shapes/ShapeInfo.h: Update function names, add declaration.

(WebCore::ShapeInfo::clearSegments):
(WebCore::ShapeInfo::logicalLineBottom):
(WebCore::ShapeInfo::lineOverlapsShapeBounds):

  • rendering/shapes/ShapeInsideInfo.cpp:

(WebCore::ShapeInsideInfo::computeFirstFitPositionForFloat): Compute the first fit position below the current line position inside shapes. I called this function
this way, because currently we use it only for shapes.

  • rendering/shapes/ShapeInsideInfo.h: Update function names.
  • rendering/shapes/ShapeOutsideInfo.cpp: Update function names.

(WebCore::ShapeOutsideInfo::computeSegmentsForContainingBlockLine):
(WebCore::ShapeOutsideInfo::updateSegmentsForLine):

  • rendering/shapes/ShapeOutsideInfo.h: Update function names.

LayoutTests:

  • fast/shapes/shape-inside/shape-inside-left-float-in-lower-left-triangle-inline-content-expected.html: Added.
  • fast/shapes/shape-inside/shape-inside-left-float-in-lower-left-triangle-inline-content.html: Added.
  • fast/shapes/shape-inside/shape-inside-left-float-in-lower-right-triangle-inline-content-expected.html: Added.
  • fast/shapes/shape-inside/shape-inside-left-float-in-lower-right-triangle-inline-content.html: Added.
  • fast/shapes/shape-inside/shape-inside-left-float-in-upper-left-triangle-inline-content-expected.html: Added.
  • fast/shapes/shape-inside/shape-inside-left-float-in-upper-left-triangle-inline-content.html: Added.
  • fast/shapes/shape-inside/shape-inside-left-float-in-upper-right-triangle-inline-content-expected.html: Added.
  • fast/shapes/shape-inside/shape-inside-left-float-in-upper-right-triangle-inline-content.html: Added.
Location:
trunk
Files:
8 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r156019 r156022  
     12013-09-17  Zoltan Horvath  <zoltan@webkit.org>
     2
     3        [CSS Shapes] Use the float height to determine position in shape-inside
     4        https://bugs.webkit.org/show_bug.cgi?id=102846
     5
     6        Reviewed by Darin Adler.
     7
     8        Float positioning inside shape-inside has been working only for simple cases when the float boundaries didn't overlap with the shape.
     9        This patch fixes the behavior for left floats and shapes with inline content. I want to add this work step by step, therefore the next
     10        step would be to add support for block content with inline content (e.g. paragraphs) then cover cases with right floats.
     11
     12        * fast/shapes/shape-inside/shape-inside-left-float-in-lower-left-triangle-inline-content-expected.html: Added.
     13        * fast/shapes/shape-inside/shape-inside-left-float-in-lower-left-triangle-inline-content.html: Added.
     14        * fast/shapes/shape-inside/shape-inside-left-float-in-lower-right-triangle-inline-content-expected.html: Added.
     15        * fast/shapes/shape-inside/shape-inside-left-float-in-lower-right-triangle-inline-content.html: Added.
     16        * fast/shapes/shape-inside/shape-inside-left-float-in-upper-left-triangle-inline-content-expected.html: Added.
     17        * fast/shapes/shape-inside/shape-inside-left-float-in-upper-left-triangle-inline-content.html: Added.
     18        * fast/shapes/shape-inside/shape-inside-left-float-in-upper-right-triangle-inline-content-expected.html: Added.
     19        * fast/shapes/shape-inside/shape-inside-left-float-in-upper-right-triangle-inline-content.html: Added.
     20
    1212013-09-17  Filip Pizlo  <fpizlo@apple.com>
    222
  • trunk/Source/WebCore/ChangeLog

    r156015 r156022  
     12013-09-17  Zoltan Horvath  <zoltan@webkit.org>
     2
     3        [CSS Shapes] Use the float height to determine position in shape-inside
     4        https://bugs.webkit.org/show_bug.cgi?id=102846
     5
     6        Reviewed by Darin Adler.
     7
     8        Float positioning inside shape-inside has been working only for simple cases when the float boundaries didn't overlap with the shape.
     9        This patch fixes the behavior for left floats and shapes with inline content. I want to add this work step by step, therefore the next
     10        step would be to add support for block content with inline content (e.g. paragraphs) then cover cases with right floats.
     11
     12        Tests: fast/shapes/shape-inside/shape-inside-left-float-in-lower-left-triangle-inline-content.html
     13               fast/shapes/shape-inside/shape-inside-left-float-in-lower-right-triangle-inline-content.html
     14               fast/shapes/shape-inside/shape-inside-left-float-in-upper-left-triangle-inline-content.html
     15               fast/shapes/shape-inside/shape-inside-left-float-in-upper-right-triangle-inline-content.html
     16
     17        * rendering/LineWidth.cpp:
     18        (WebCore::LineWidth::LineWidth): Use the new updateCurrentShapeSegment member function.
     19        (WebCore::LineWidth::updateCurrentShapeSegment): We need a function to update the current line segment's reference, since we use it multiple places.
     20        * rendering/LineWidth.h: Add new member function.
     21        * rendering/RenderBlock.cpp:
     22        (WebCore::RenderBlock::computeLogicalLocationForFloat): Fix positioning of a floating element.
     23        * rendering/RenderBlockLineLayout.cpp:
     24        (WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLine): Use updateSegmentsForLine instead of computeSegmentsForLine.
     25        (WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLineInFlowThread): Use updateSegmentsForLine instead of computeSegmentsForLine.
     26        (WebCore::RenderBlock::adjustLogicalLineTopAndLogicalHeightIfNeeded):
     27        (WebCore::updateSegmentsForShapes): After our float is positioned, we need to adjust the current lineTop and update the logical height to be able to wrap around the float.
     28        (WebCore::RenderBlock::LineBreaker::nextSegmentBreak): If we have a float in our line we might need to adjust our lineTop and logicalHeight.
     29        * rendering/shapes/ShapeInfo.cpp:
     30        (WebCore::::computeSegmentsForLine): Add new const function to compute the segments. I'd like make this function static later if possible.
     31        (WebCore::::updateSegmentsForLine): Old computeSegmentsForLine, change name to indicate that it is actually changing things.
     32        * rendering/shapes/ShapeInfo.h: Update function names, add declaration.
     33        (WebCore::ShapeInfo::clearSegments):
     34        (WebCore::ShapeInfo::logicalLineBottom):
     35        (WebCore::ShapeInfo::lineOverlapsShapeBounds):
     36        * rendering/shapes/ShapeInsideInfo.cpp:
     37        (WebCore::ShapeInsideInfo::computeFirstFitPositionForFloat): Compute the first fit position below the current line position inside shapes. I called this function
     38        this way, because currently we use it only for shapes.
     39        * rendering/shapes/ShapeInsideInfo.h: Update function names.
     40        * rendering/shapes/ShapeOutsideInfo.cpp: Update function names.
     41        (WebCore::ShapeOutsideInfo::computeSegmentsForContainingBlockLine):
     42        (WebCore::ShapeOutsideInfo::updateSegmentsForLine):
     43        * rendering/shapes/ShapeOutsideInfo.h: Update function names.
     44
    1452013-09-17  Sam Weinig  <sam@webkit.org>
    246
  • trunk/Source/WebCore/rendering/LineWidth.cpp

    r155569 r156022  
    5050{
    5151#if ENABLE(CSS_SHAPES)
    52     if (ShapeInsideInfo* shapeInsideInfo = m_block.layoutShapeInsideInfo())
    53         m_segment = shapeInsideInfo->currentSegment();
     52    updateCurrentShapeSegment();
    5453#endif
    5554    updateAvailableWidth();
     
    205204}
    206205
     206#if ENABLE(CSS_SHAPES)
     207void LineWidth::updateCurrentShapeSegment()
     208{
     209    if (ShapeInsideInfo* shapeInsideInfo = m_block.layoutShapeInsideInfo())
     210        m_segment = shapeInsideInfo->currentSegment();
     211}
     212#endif
     213
    207214void LineWidth::computeAvailableWidthFromLeftAndRight()
    208215{
  • trunk/Source/WebCore/rendering/LineWidth.h

    r155565 r156022  
    7171    void setTrailingWhitespaceWidth(float collapsedWhitespace, float borderPaddingMargin = 0);
    7272
     73#if ENABLE(CSS_SHAPES)
     74    void updateCurrentShapeSegment();
     75#endif
     76
    7377    bool shouldIndentText() const { return m_shouldIndentText == IndentText; }
    7478
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r155975 r156022  
    33543354    // FIXME Bug 102948: This only works for shape outside directly set on this block.
    33553355    ShapeInsideInfo* shapeInsideInfo = this->shapeInsideInfo();
    3356     // FIXME Bug 102846: Take into account the height of the content. The offset should be
    3357     // equal to the maximum segment length.
    3358     if (shapeInsideInfo && shapeInsideInfo->hasSegments() && shapeInsideInfo->segments().size() == 1) {
    3359         // FIXME Bug 102949: Add support for shapes with multipe segments.
    3360 
    3361         // The segment offsets are relative to the content box.
    3362         logicalRightOffset = logicalLeftOffset + shapeInsideInfo->segments()[0].logicalRight;
    3363         logicalLeftOffset += shapeInsideInfo->segments()[0].logicalLeft;
     3356    // FIXME: Implement behavior for right floats.
     3357    if (shapeInsideInfo) {
     3358        // FIXME: If the float doesn't fit in the shape we should push it under the content box
     3359        logicalTopOffset = shapeInsideInfo->computeFirstFitPositionForFloat(LayoutSize(floatingObject->width(), floatingObject->height()));
     3360        if (logicalHeight() > logicalTopOffset)
     3361            logicalTopOffset = logicalHeight();
     3362
     3363        SegmentList segments = shapeInsideInfo->computeSegmentsForLine(logicalTopOffset, childBox->logicalHeight());
     3364        // FIXME Bug 102949: Add support for shapes with multiple segments.
     3365        if (segments.size() == 1) {
     3366            // The segment offsets are relative to the content box.
     3367            logicalRightOffset = logicalLeftOffset + segments[0].logicalRight;
     3368            logicalLeftOffset += segments[0].logicalLeft;
     3369        }
    33643370    } else
    33653371#endif
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r155975 r156022  
    13551355
    13561356    // FIXME: Bug 95361: It is possible for a line to grow beyond lineHeight, in which case these segments may be incorrect.
    1357     shapeInsideInfo->computeSegmentsForLine(LayoutSize(lineLeft, lineTop), lineHeight);
     1357    shapeInsideInfo->updateSegmentsForLine(LayoutSize(lineLeft, lineTop), lineHeight);
    13581358
    13591359    pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
     
    14281428
    14291429    // FIXME: 118571 - Shape inside on a region does not yet take into account its padding for nested flow blocks
    1430     shapeInsideInfo->computeSegmentsForLine(LayoutSize(0, lineTop), lineHeight);
     1430    shapeInsideInfo->updateSegmentsForLine(LayoutSize(0, lineTop), lineHeight);
    14311431
    14321432    if (currentRegion->isLastRegion())
     
    14461446        newLogicalHeight = logicalHeight();
    14471447    }
    1448 
    14491448
    14501449    end = restartLayoutRunsAndFloatsInRange(logicalHeight(), newLogicalHeight, lastFloatFromPreviousLine, resolver, end);
     
    25872586    return canBreakHere;
    25882587}
     2588
     2589#if ENABLE(CSS_SHAPES)
     2590static void updateSegmentsForShapes(RenderBlock* block, const FloatingObject* lastFloatFromPreviousLine, const WordMeasurements& wordMeasurements, LineWidth& width, bool isFirstLine)
     2591{
     2592    ASSERT(lastFloatFromPreviousLine);
     2593
     2594    ShapeInsideInfo* shapeInsideInfo = block->layoutShapeInsideInfo();
     2595    LayoutUnit lineLogicalHeight = logicalHeightForLine(block, isFirstLine);
     2596    LayoutUnit lineLogicalBottom = block->logicalHeight() + lineLogicalHeight;
     2597    bool lineOverlapsWithFloat = (lastFloatFromPreviousLine->y() < lineLogicalBottom) && (block->logicalHeight() < lastFloatFromPreviousLine->maxY());
     2598
     2599    if (!shapeInsideInfo || !lineOverlapsWithFloat)
     2600        return;
     2601
     2602    float minWidth = firstPositiveWidth(wordMeasurements);
     2603
     2604    LayoutUnit availableWidth = block->width() - lastFloatFromPreviousLine->maxX();
     2605    if (availableWidth < minWidth)
     2606        block->setLogicalHeight(lastFloatFromPreviousLine->maxY());
     2607
     2608    if (block->logicalHeight() < lastFloatFromPreviousLine->y()) {
     2609        shapeInsideInfo->adjustLogicalLineTop(minWidth + lastFloatFromPreviousLine->width());
     2610        block->setLogicalHeight(shapeInsideInfo->logicalLineTop());
     2611    }
     2612
     2613    shapeInsideInfo->updateSegmentsForLine(block->logicalHeight(), lineLogicalHeight);
     2614    width.updateCurrentShapeSegment();
     2615    width.updateAvailableWidth();
     2616}
     2617#endif
    25892618
    25902619InlineIterator RenderBlock::LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements)
     
    29262955                    wordMeasurement.endOffset = current.m_pos;
    29272956                    wordMeasurement.startOffset = lastSpace;
    2928                    
     2957
    29292958                    float additionalTempWidth;
    29302959                    if (wordTrailingSpaceWidth && c == ' ')
     
    29492978                    }
    29502979
     2980#if ENABLE(CSS_SHAPES)
     2981                    if (lastFloatFromPreviousLine)
     2982                        updateSegmentsForShapes(m_block, lastFloatFromPreviousLine, wordMeasurements, width, lineInfo.isFirstLine());
     2983#endif
    29512984                    applyWordSpacing = wordSpacing && currentCharacterIsSpace;
    29522985
  • trunk/Source/WebCore/rendering/shapes/ShapeInfo.cpp

    r155627 r156022  
    7070
    7171template<class RenderType>
    72 bool ShapeInfo<RenderType>::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight)
     72SegmentList ShapeInfo<RenderType>::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const
     73{
     74    ASSERT(lineHeight >= 0);
     75    SegmentList segments;
     76
     77    getIntervals((lineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - lineTop), segments);
     78
     79    for (size_t i = 0; i < segments.size(); i++) {
     80        segments[i].logicalLeft += logicalLeftOffset();
     81        segments[i].logicalRight += logicalLeftOffset();
     82    }
     83
     84    return segments;
     85}
     86
     87template<class RenderType>
     88bool ShapeInfo<RenderType>::updateSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight)
    7389{
    7490    ASSERT(lineHeight >= 0);
     
    7894
    7995    if (lineOverlapsShapeBounds())
    80         getIntervals(m_shapeLineTop, std::min(m_lineHeight, shapeLogicalBottom() - lineTop), m_segments);
    81 
    82     LayoutUnit logicalLeftOffset = this->logicalLeftOffset();
    83     for (size_t i = 0; i < m_segments.size(); i++) {
    84         m_segments[i].logicalLeft += logicalLeftOffset;
    85         m_segments[i].logicalRight += logicalLeftOffset;
    86     }
     96        m_segments = computeSegmentsForLine(lineTop, lineHeight);
    8797
    8898    return m_segments.size();
  • trunk/Source/WebCore/rendering/shapes/ShapeInfo.h

    r155655 r156022  
    8484    }
    8585
    86     virtual bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight);
     86    SegmentList computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const;
     87    virtual bool updateSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight);
    8788    void clearSegments() { m_segments.clear(); }
    8889
     
    9697    LayoutUnit logicalLineTop() const { return m_shapeLineTop + logicalTopOffset(); }
    9798    LayoutUnit logicalLineBottom() const { return m_shapeLineTop + m_lineHeight + logicalTopOffset(); }
     99    LayoutUnit logicalLineBottom(LayoutUnit lineHeight) const { return m_shapeLineTop + lineHeight + logicalTopOffset(); }
    98100
    99101    LayoutUnit shapeContainingBlockLogicalHeight() const { return (m_renderer->style()->boxSizing() == CONTENT_BOX) ? (m_shapeLogicalSize.height() + m_renderer->borderAndPaddingLogicalHeight()) : m_shapeLogicalSize.height(); }
    100102
    101103    bool lineOverlapsShapeBounds() const { return logicalLineTop() < shapeLogicalBottom() && shapeLogicalTop() <= logicalLineBottom(); }
     104    bool lineOverlapsShapeBounds(LayoutUnit lineHeight) const { return logicalLineTop() < shapeLogicalBottom() && shapeLogicalTop() <= logicalLineBottom(lineHeight); }
    102105
    103106    void dirtyShapeSize() { m_shape.clear(); }
  • trunk/Source/WebCore/rendering/shapes/ShapeInsideInfo.cpp

    r155627 r156022  
    8282}
    8383
     84LayoutUnit ShapeInsideInfo::computeFirstFitPositionForFloat(const LayoutSize floatSize) const
     85{
     86    if (!computedShape() || !floatSize.width() || shapeLogicalBottom() < logicalLineTop())
     87        return 0;
     88
     89    LayoutUnit firstFitPosition = 0;
     90    if (computedShape()->firstIncludedIntervalLogicalTop(m_shapeLineTop, floatSize, firstFitPosition) && (m_shapeLineTop <= firstFitPosition))
     91        return firstFitPosition;
     92
     93    return 0;
     94}
     95
    8496}
    8597#endif
  • trunk/Source/WebCore/rendering/shapes/ShapeInsideInfo.h

    r155627 r156022  
    6969    static bool isEnabledFor(const RenderBlock* renderer);
    7070
    71     bool computeSegmentsForLine(LayoutSize lineOffset, LayoutUnit lineHeight)
     71    bool updateSegmentsForLine(LayoutSize lineOffset, LayoutUnit lineHeight)
    7272    {
    7373        m_segmentRanges.clear();
    74         bool result = ShapeInfo<RenderBlock>::computeSegmentsForLine(lineOffset.height(), lineHeight);
     74        bool result = ShapeInfo<RenderBlock>::updateSegmentsForLine(lineOffset.height(), lineHeight);
    7575        for (size_t i = 0; i < m_segments.size(); i++) {
    7676            m_segments[i].logicalLeft -= lineOffset.width();
     
    8080    }
    8181
    82     virtual bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) OVERRIDE
     82    virtual bool updateSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) OVERRIDE
    8383    {
    8484        m_segmentRanges.clear();
    85         return ShapeInfo<RenderBlock>::computeSegmentsForLine(lineTop, lineHeight);
     85        return ShapeInfo<RenderBlock>::updateSegmentsForLine(lineTop, lineHeight);
    8686    }
    8787
     
    105105    }
    106106    bool adjustLogicalLineTop(float minSegmentWidth);
     107    LayoutUnit computeFirstFitPositionForFloat(const LayoutSize) const;
    107108
    108109    void setNeedsLayout(bool value) { m_needsLayout = value; }
  • trunk/Source/WebCore/rendering/shapes/ShapeOutsideInfo.cpp

    r155627 r156022  
    5656{
    5757    LayoutUnit lineTopInShapeCoordinates = lineTop - floatTop + logicalTopOffset();
    58     return computeSegmentsForLine(lineTopInShapeCoordinates, lineHeight);
     58    return updateSegmentsForLine(lineTopInShapeCoordinates, lineHeight);
    5959}
    6060
    61 bool ShapeOutsideInfo::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight)
     61bool ShapeOutsideInfo::updateSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight)
    6262{
    6363    if (shapeSizeDirty() || m_lineTop != lineTop || m_lineHeight != lineHeight) {
    64         if (ShapeInfo<RenderBox>::computeSegmentsForLine(lineTop, lineHeight)) {
     64        if (ShapeInfo<RenderBox>::updateSegmentsForLine(lineTop, lineHeight)) {
    6565            m_leftSegmentMarginBoxDelta = m_segments[0].logicalLeft + m_renderer->marginStart();
    6666            m_rightSegmentMarginBoxDelta = m_segments[m_segments.size()-1].logicalRight - m_renderer->logicalWidth() - m_renderer->marginEnd();
  • trunk/Source/WebCore/rendering/shapes/ShapeOutsideInfo.h

    r155627 r156022  
    4646
    4747    bool computeSegmentsForContainingBlockLine(LayoutUnit lineTop, LayoutUnit floatTop, LayoutUnit lineHeight);
    48     virtual bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) OVERRIDE;
     48    virtual bool updateSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) OVERRIDE;
    4949
    5050    static PassOwnPtr<ShapeOutsideInfo> createInfo(const RenderBox* renderer) { return adoptPtr(new ShapeOutsideInfo(renderer)); }
Note: See TracChangeset for help on using the changeset viewer.