Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #ifndef InlineFlowBox_h
     22 #define InlineFlowBox_h
     23 
     24 #include "InlineRunBox.h"
     25 #include "RenderOverflow.h"
     26 
     27 namespace WebCore {
     28 
     29 class HitTestRequest;
     30 class HitTestResult;
     31 class RenderLineBoxList;
     32 
     33 class InlineFlowBox : public InlineRunBox {
     34 public:
     35     InlineFlowBox(RenderObject* obj)
     36         : InlineRunBox(obj)
     37         , m_firstChild(0)
     38         , m_lastChild(0)
     39         , m_includeLeftEdge(false)
     40         , m_includeRightEdge(false)
     41 #ifndef NDEBUG
     42         , m_hasBadChildList(false)
     43 #endif
     44     {
     45         // Internet Explorer and Firefox always create a marker for list items, even when the list-style-type is none.  We do not make a marker
     46         // in the list-style-type: none case, since it is wasteful to do so.  However, in order to match other browsers we have to pretend like
     47         // an invisible marker exists.  The side effect of having an invisible marker is that the quirks mode behavior of shrinking lines with no
     48         // text children must not apply.  This change also means that gaps will exist between image bullet list items.  Even when the list bullet
     49         // is an image, the line is still considered to be immune from the quirk.
     50         m_hasTextChildren = obj->style()->display() == LIST_ITEM;
     51     }
     52 
     53 #ifndef NDEBUG
     54     virtual ~InlineFlowBox();
     55 #endif
     56 
     57     InlineFlowBox* prevFlowBox() const { return static_cast<InlineFlowBox*>(m_prevLine); }
     58     InlineFlowBox* nextFlowBox() const { return static_cast<InlineFlowBox*>(m_nextLine); }
     59 
     60     InlineBox* firstChild() const { checkConsistency(); return m_firstChild; }
     61     InlineBox* lastChild() const { checkConsistency(); return m_lastChild; }
     62 
     63     virtual bool isLeaf() const { return false; }
     64 
     65     InlineBox* firstLeafChild() const;
     66     InlineBox* lastLeafChild() const;
     67 
     68     virtual void setConstructed()
     69     {
     70         InlineBox::setConstructed();
     71         if (firstChild())
     72             firstChild()->setConstructed();
     73     }
     74 
     75     void addToLine(InlineBox* child);
     76     virtual void deleteLine(RenderArena*);
     77     virtual void extractLine();
     78     virtual void attachLine();
     79     virtual void adjustPosition(int dx, int dy);
     80 
     81     virtual void extractLineBoxFromRenderObject();
     82     virtual void attachLineBoxToRenderObject();
     83     virtual void removeLineBoxFromRenderObject();
     84 
     85     virtual void clearTruncation();
     86 
     87     virtual void paintBoxDecorations(RenderObject::PaintInfo&, int tx, int ty);
     88     virtual void paintMask(RenderObject::PaintInfo&, int tx, int ty);
     89     void paintFillLayers(const RenderObject::PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
     90     void paintFillLayer(const RenderObject::PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
     91     void paintBoxShadow(GraphicsContext*, RenderStyle*, ShadowStyle, int tx, int ty, int w, int h);
     92     virtual void paintTextDecorations(RenderObject::PaintInfo&, int tx, int ty, bool paintedChildren = false);
     93     virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
     94     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
     95 
     96     virtual RenderLineBoxList* rendererLineBoxes() const;
     97 
     98     int marginBorderPaddingLeft() const { return marginLeft() + borderLeft() + paddingLeft(); }
     99     int marginBorderPaddingRight() const { return marginRight() + borderRight() + paddingRight(); }
    100     int marginLeft() const { if (includeLeftEdge()) return boxModelObject()->marginLeft(); return 0; }
    101     int marginRight() const { if (includeRightEdge()) return boxModelObject()->marginRight(); return 0; }
    102     int borderLeft() const { if (includeLeftEdge()) return renderer()->style()->borderLeftWidth(); return 0; }
    103     int borderRight() const { if (includeRightEdge()) return renderer()->style()->borderRightWidth(); return 0; }
    104     int borderTop() const { return renderer()->style()->borderTopWidth(); }
    105     int borderBottom() const { return renderer()->style()->borderBottomWidth(); }
    106     int paddingLeft() const { if (includeLeftEdge()) return boxModelObject()->paddingLeft(); return 0; }
    107     int paddingRight() const { if (includeRightEdge()) return boxModelObject()->paddingRight(); return 0; }
    108     int paddingTop() const { return boxModelObject()->paddingTop(); }
    109     int paddingBottom() const { return boxModelObject()->paddingBottom(); }
    110 
    111     bool includeLeftEdge() const { return m_includeLeftEdge; }
    112     bool includeRightEdge() const { return m_includeRightEdge; }
    113     void setEdges(bool includeLeft, bool includeRight)
    114     {
    115         m_includeLeftEdge = includeLeft;
    116         m_includeRightEdge = includeRight;
    117     }
    118 
    119     // Helper functions used during line construction and placement.
    120     void determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject);
    121     int getFlowSpacingWidth();
    122     bool onEndChain(RenderObject* endObject);
    123     virtual int placeBoxesHorizontally(int x, bool& needsWordSpacing);
    124     void computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
    125                                   int& maxAscent, int& maxDescent, bool strictMode);
    126     void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
    127                                    int maxPositionTop, int maxPositionBottom);
    128     void placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom);
    129     void computeVerticalOverflow(int lineTop, int lineBottom, bool strictMode);
    130 
    131     void removeChild(InlineBox* child);
    132 
    133     virtual RenderObject::SelectionState selectionState();
    134 
    135     virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth);
    136     virtual int placeEllipsisBox(bool ltr, int blockLeftEdge, int blockRightEdge, int ellipsisWidth, bool&);
    137 
    138     bool hasTextChildren() const { return m_hasTextChildren; }
    139 
    140     void checkConsistency() const;
    141     void setHasBadChildList();
    142 
    143     int topVisibleOverflow() const { return std::min(topLayoutOverflow(), topVisualOverflow()); }
    144     int bottomVisibleOverflow() const { return std::max(bottomLayoutOverflow(), bottomVisualOverflow()); }
    145     int leftVisibleOverflow() const { return std::min(leftLayoutOverflow(), leftVisualOverflow()); }
    146     int rightVisibleOverflow() const { return std::max(rightLayoutOverflow(), rightVisualOverflow()); }
    147     IntRect visibleOverflowRect() const { return m_overflow ? m_overflow->visibleOverflowRect() : IntRect(m_x, m_y, m_width, height());  }
    148 
    149     int topLayoutOverflow() const { return m_overflow ? m_overflow->topLayoutOverflow() : m_y; }
    150     int bottomLayoutOverflow() const { return m_overflow ? m_overflow->bottomLayoutOverflow() : m_y + height(); }
    151     int leftLayoutOverflow() const { return m_overflow ? m_overflow->leftLayoutOverflow() : m_x; }
    152     int rightLayoutOverflow() const { return m_overflow ? m_overflow->rightLayoutOverflow() : m_x + m_width; }
    153     IntRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : IntRect(m_x, m_y, m_width, height()); }
    154 
    155     int topVisualOverflow() const { return m_overflow ? m_overflow->topVisualOverflow() : m_y; }
    156     int bottomVisualOverflow() const { return m_overflow ? m_overflow->bottomVisualOverflow() : m_y + height(); }
    157     int leftVisualOverflow() const { return m_overflow ? m_overflow->leftVisualOverflow() : m_x; }
    158     int rightVisualOverflow() const { return m_overflow ? m_overflow->rightVisualOverflow() : m_x + m_width; }
    159     IntRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : IntRect(m_x, m_y, m_width, height()); }
    160 
    161     void setHorizontalOverflowPositions(int leftLayoutOverflow, int rightLayoutOverflow, int leftVisualOverflow, int rightVisualOverflow);
    162     void setVerticalOverflowPositions(int topLayoutOverflow, int bottomLayoutOverflow, int topVisualOverflow, int bottomVisualOverflow, int boxHeight);
    163 
    164 protected:
    165     OwnPtr<RenderOverflow> m_overflow;
    166 
    167 private:
    168     virtual bool isInlineFlowBox() const { return true; }
    169 
    170     InlineBox* m_firstChild;
    171     InlineBox* m_lastChild;
    172 
    173     bool m_includeLeftEdge : 1;
    174     bool m_includeRightEdge : 1;
    175     bool m_hasTextChildren : 1;
    176 
    177 #ifndef NDEBUG
    178     bool m_hasBadChildList;
    179 #endif
    180 };
    181 
    182 inline void InlineFlowBox::setHorizontalOverflowPositions(int leftLayoutOverflow, int rightLayoutOverflow, int leftVisualOverflow, int rightVisualOverflow)
    183 {
    184     if (!m_overflow) {
    185         if (leftLayoutOverflow == m_x && rightLayoutOverflow == m_x + m_width && leftVisualOverflow == m_x && rightVisualOverflow == m_x + m_width)
    186             return;
    187         m_overflow.set(new RenderOverflow(IntRect(m_x, m_y, m_width, m_renderer->style(m_firstLine)->font().height())));
    188     }
    189 
    190     m_overflow->setLeftLayoutOverflow(leftLayoutOverflow);
    191     m_overflow->setRightLayoutOverflow(rightLayoutOverflow);
    192     m_overflow->setLeftVisualOverflow(leftVisualOverflow);
    193     m_overflow->setRightVisualOverflow(rightVisualOverflow);
    194 }
    195 
    196 inline void InlineFlowBox::setVerticalOverflowPositions(int topLayoutOverflow, int bottomLayoutOverflow, int topVisualOverflow, int bottomVisualOverflow, int boxHeight)
    197 {
    198     if (!m_overflow) {
    199         if (topLayoutOverflow == m_y && bottomLayoutOverflow == m_y + boxHeight && topVisualOverflow == m_y && bottomVisualOverflow == m_y + boxHeight)
    200             return;
    201         m_overflow.set(new RenderOverflow(IntRect(m_x, m_y, m_width, boxHeight)));
    202     }
    203 
    204     m_overflow->setTopLayoutOverflow(topLayoutOverflow);
    205     m_overflow->setBottomLayoutOverflow(bottomLayoutOverflow);
    206     m_overflow->setTopVisualOverflow(topVisualOverflow);
    207     m_overflow->setBottomVisualOverflow(bottomVisualOverflow);
    208 }
    209 
    210 #ifdef NDEBUG
    211 inline void InlineFlowBox::checkConsistency() const
    212 {
    213 }
    214 #endif
    215 
    216 inline void InlineFlowBox::setHasBadChildList()
    217 {
    218 #ifndef NDEBUG
    219     m_hasBadChildList = true;
    220 #endif
    221 }
    222 
    223 } // namespace WebCore
    224 
    225 #ifndef NDEBUG
    226 // Outside the WebCore namespace for ease of invocation from gdb.
    227 void showTree(const WebCore::InlineFlowBox*);
    228 #endif
    229 
    230 #endif // InlineFlowBox_h
    231