?? render_box.cpp
字號:
void RenderBox::calcVerticalMargins()
{
if( isTableCell() ) {
// table margins are basically infinite
m_marginTop = TABLECELLMARGIN;
m_marginBottom = TABLECELLMARGIN;
return;
}
Length tm = style()->marginTop();
Length bm = style()->marginBottom();
// margins are calculated with respect to the _width_ of
// the containing block (8.3)
int cw = containingBlock()->contentWidth();
m_marginTop = tm.minWidth(cw);
m_marginBottom = bm.minWidth(cw);
}
void RenderBox::setStaticX(int staticX)
{
m_staticX = staticX;
}
void RenderBox::setStaticY(int staticY)
{
m_staticY = staticY;
}
void RenderBox::calcAbsoluteHorizontal()
{
const int AUTO = -666666;
int l,r,w,ml,mr,cw;
int pab = borderLeft()+ borderRight()+ paddingLeft()+ paddingRight();
l=r=ml=mr=w=AUTO;
// We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
RenderObject* cb = container();
cw = containingBlockWidth() + cb->paddingLeft() + cb->paddingRight();
if(!style()->left().isVariable())
l = style()->left().width(cw);
if(!style()->right().isVariable())
r = style()->right().width(cw);
if(!style()->width().isVariable())
w = style()->width().width(cw);
else if (isReplaced())
w = intrinsicWidth();
if(!style()->marginLeft().isVariable())
ml = style()->marginLeft().width(cw);
if(!style()->marginRight().isVariable())
mr = style()->marginRight().width(cw);
// printf("h1: w=%d, l=%d, r=%d, ml=%d, mr=%d\n",w,l,r,ml,mr);
int static_distance=0;
if ((parent()->style()->direction()==LTR && (l==AUTO && r==AUTO ))
|| style()->left().isStatic())
{
static_distance = m_staticX - cb->borderLeft(); // Should already have been set through layout of the parent().
RenderObject* po = parent();
for (; po && po != cb; po = po->parent())
static_distance += po->xPos();
if (l==AUTO || style()->left().isStatic())
l = static_distance;
}
else if ((parent()->style()->direction()==RTL && (l==AUTO && r==AUTO ))
|| style()->right().isStatic())
{
RenderObject* po = parent();
static_distance = m_staticX - cb->borderLeft(); // Should already have been set through layout of the parent().
while (po && po!=containingBlock()) {
static_distance+=po->xPos();
po=po->parent();
}
if (r==AUTO || style()->right().isStatic())
r = static_distance;
}
if (l!=AUTO && w!=AUTO && r!=AUTO)
{
// left, width, right all given, play with margins
int ot = l + w + r + pab;
if (ml==AUTO && mr==AUTO)
{
// both margins auto, solve for equality
ml = (cw - ot)/2;
mr = cw - ot - ml;
}
else if (ml==AUTO)
// solve for left margin
ml = cw - ot - mr;
else if (mr==AUTO)
// solve for right margin
mr = cw - ot - ml;
else
{
// overconstrained, solve according to dir
if (style()->direction()==LTR)
r = cw - ( l + w + ml + mr + pab);
else
l = cw - ( r + w + ml + mr + pab);
}
}
else
{
// one or two of (left, width, right) missing, solve
// auto margins are ignored
if (ml==AUTO) ml = 0;
if (mr==AUTO) mr = 0;
//1. solve left & width.
if (l==AUTO && w==AUTO && r!=AUTO)
{
// From section 10.3.7 of the CSS2.1 specification.
// "The shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width)."
w = QMIN(QMAX(m_minWidth-pab, cw - ( r + ml + mr + pab)), m_maxWidth-pab);
l = cw - ( r + w + ml + mr + pab);
}
else
//2. solve left & right. use static positioning.
if (l==AUTO && w!=AUTO && r==AUTO)
{
if (style()->direction()==RTL)
{
r = static_distance;
l = cw - ( r + w + ml + mr + pab);
}
else
{
l = static_distance;
r = cw - ( l + w + ml + mr + pab);
}
}
else
//3. solve width & right.
if (l!=AUTO && w==AUTO && r==AUTO)
{
// From section 10.3.7 of the CSS2.1 specification.
// "The shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width)."
w = QMIN(QMAX(m_minWidth-pab, cw - ( l + ml + mr + pab)), m_maxWidth-pab);
r = cw - ( l + w + ml + mr + pab);
}
else
//4. solve left
if (l==AUTO && w!=AUTO && r!=AUTO)
l = cw - ( r + w + ml + mr + pab);
else
//5. solve width
if (l!=AUTO && w==AUTO && r!=AUTO)
w = cw - ( r + l + ml + mr + pab);
else
//6. solve right
if (l!=AUTO && w!=AUTO && r==AUTO)
r = cw - ( l + w + ml + mr + pab);
}
m_width = w + pab;
m_marginLeft = ml;
m_marginRight = mr;
m_x = l + ml + cb->borderLeft();
// printf("h: w=%d, l=%d, r=%d, ml=%d, mr=%d\n",w,l,r,ml,mr);
}
void RenderBox::calcAbsoluteVertical()
{
// css2 spec 10.6.4 & 10.6.5
// based on
// http://www.w3.org/Style/css2-updates/REC-CSS2-19980512-errata
// (actually updated 2000-10-24)
// that introduces static-position value for top, left & right
const int AUTO = -666666;
int t,b,h,mt,mb,ch;
t=b=h=mt=mb=AUTO;
int pab = borderTop()+borderBottom()+paddingTop()+paddingBottom();
// We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
RenderObject* cb = container();
if (cb->isRoot()) // Even in strict mode (where we don't grow the root to fill the viewport) other browsers
// position as though the root fills the viewport.
ch = cb->availableHeight();
else
ch = cb->height() - cb->borderTop() - cb->borderBottom();
if(!style()->top().isVariable())
t = style()->top().width(ch);
if(!style()->bottom().isVariable())
b = style()->bottom().width(ch);
if (isTable() && style()->height().isVariable())
// Height is never unsolved for tables. "auto" means shrink to fit. Use our
// height instead.
h = m_height - pab;
else if(!style()->height().isVariable())
{
h = style()->height().width(ch);
if (m_height-pab > h) {
setOverflowHeight(m_height + pab - (paddingBottom() + borderBottom()));
m_height = h+pab;
}
}
else if (isReplaced())
h = intrinsicHeight();
if(!style()->marginTop().isVariable())
mt = style()->marginTop().width(ch);
if(!style()->marginBottom().isVariable())
mb = style()->marginBottom().width(ch);
int static_top=0;
if ((t==AUTO && b==AUTO ) || style()->top().isStatic())
{
// calc hypothetical location in the normal flow
// used for 1) top=static-position
// 2) top, bottom, height are all auto -> calc top -> 3.
// 3) precalc for case 2 below
static_top = m_staticY - cb->borderTop(); // Should already have been set through layout of the parent().
RenderObject* po = parent();
for (; po && po != cb; po = po->parent())
static_top += po->yPos();
if (h==AUTO || style()->top().isStatic())
t = static_top;
}
if (t!=AUTO && h!=AUTO && b!=AUTO)
{
// top, height, bottom all given, play with margins
int ot = h + t + b + pab;
if (mt==AUTO && mb==AUTO)
{
// both margins auto, solve for equality
mt = (ch - ot)/2;
mb = ch - ot - mt;
}
else if (mt==AUTO)
// solve for top margin
mt = ch - ot - mb;
else if (mb==AUTO)
// solve for bottom margin
mb = ch - ot - mt;
else
// overconstrained, solve for bottom
b = ch - ( h+t+mt+mb+pab);
}
else
{
// one or two of (top, height, bottom) missing, solve
// auto margins are ignored
if (mt==AUTO) mt = 0;
if (mb==AUTO) mb = 0;
//1. solve top & height. use content height.
if (t==AUTO && h==AUTO && b!=AUTO)
{
h = m_height-pab;
t = ch - ( h+b+mt+mb+pab);
}
else
//2. solve top & bottom. use static positioning.
if (t==AUTO && h!=AUTO && b==AUTO)
{
t = static_top;
b = ch - ( h+t+mt+mb+pab);
}
else
//3. solve height & bottom. use content height.
if (t!=AUTO && h==AUTO && b==AUTO)
{
h = m_height-pab;
b = ch - ( h+t+mt+mb+pab);
}
else
//4. solve top
if (t==AUTO && h!=AUTO && b!=AUTO)
t = ch - ( h+b+mt+mb+pab);
else
//5. solve height
if (t!=AUTO && h==AUTO && b!=AUTO)
h = ch - ( t+b+mt+mb+pab);
else
//6. solve bottom
if (t!=AUTO && h!=AUTO && b==AUTO)
b = ch - ( h+t+mt+mb+pab);
}
if (m_height<h+pab) //content must still fit
m_height = h+pab;
if (hasOverflowClip() && m_height > h+pab)
m_height = h+pab;
// Do not allow the height to be negative. This can happen when someone specifies both top and bottom
// but the containing block height is less than top, e.g., top:20px, bottom:0, containing block height 16.
m_height = kMax(0, m_height);
m_marginTop = mt;
m_marginBottom = mb;
m_y = t + mt + cb->borderTop();
// printf("v: h=%d, t=%d, b=%d, mt=%d, mb=%d, m_y=%d\n",h,t,b,mt,mb,m_y);
}
QRect RenderBox::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
{
// FIXME: Is it OK to check only first child instead of picking
// right child based on offset? Is it OK to pass the same offset
// along to the child instead of offset 0 or whatever?
// propagate it downwards to its children, someone will feel responsible
RenderObject *child = firstChild();
if (child) {
QRect result = child->caretRect(offset, affinity, extraWidthToEndOfLine);
// FIXME: in-band signalling!
if (result.isEmpty())
return result;
}
int _x, _y, height;
// if not, use the extents of this box
// offset 0 means left, offset 1 means right
_x = xPos() + (offset == 0 ? 0 : m_width);
InlineBox *box = inlineBoxWrapper();
if (box) {
height = box->root()->bottomOverflow() - box->root()->topOverflow();
_y = box->root()->topOverflow();
}
else {
_y = yPos();
height = m_height;
}
// If height of box is smaller than font height, use the latter one,
// otherwise the caret might become invisible.
//
// Also, if the box is not a replaced element, always use the font height.
// This prevents the "big caret" bug described in:
// <rdar://problem/3777804> Deleting all content in a document can result in giant tall-as-window insertion point
// FIXME: ignoring :first-line, missing good reason to take care of
int fontHeight = style()->fontMetrics().height();
if (fontHeight > height || !isReplaced())
height = fontHeight;
int absx, absy;
RenderObject *cb = containingBlock();
if (cb && cb != this && cb->absolutePosition(absx,absy)) {
_x += absx;
_y += absy;
}
else {
// we don't know our absolute position, and there is no point returning
// just a relative one
return QRect();
}
if (extraWidthToEndOfLine)
*extraWidthToEndOfLine = m_width - _x;
return QRect(_x, _y, 1, height);
}
int RenderBox::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
{
return includeSelf ? m_height : 0;
}
int RenderBox::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
return includeSelf ? m_width : 0;
}
int RenderBox::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
return includeSelf ? 0 : m_width;
}
#undef DEBUG_LAYOUT
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -