?? render_layer.cpp
字號:
/*
* Copyright (C) 2003 Apple Computer, Inc.
*
* Portions are Copyright (C) 1998 Netscape Communications Corporation.
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
* David Baron <dbaron@fas.harvard.edu>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
* Josh Soref <timeless@mac.com>
* Boris Zbarsky <bzbarsky@mit.edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Alternatively, the contents of this file may be used under the terms
* of either the Mozilla Public License Version 1.1, found at
* http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
* License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
* (the "GPL"), in which case the provisions of the MPL or the GPL are
* applicable instead of those above. If you wish to allow use of your
* version of this file only under the terms of one of those two
* licenses (the MPL or the GPL) and not to allow others to use your
* version of this file under the LGPL, indicate your decision by
* deletingthe provisions above and replace them with the notice and
* other provisions required by the MPL or the GPL, as the case may be.
* If you do not delete the provisions above, a recipient may use your
* version of this file under any of the LGPL, the MPL or the GPL.
*/
#include "render_layer.h"
#include <kdebug.h>
#include <assert.h>
#include "khtmlview.h"
#include "render_canvas.h"
#include "render_arena.h"
#include "xml/dom_docimpl.h"
#include "xml/dom2_eventsimpl.h"
#include "misc/htmltags.h"
#include "html/html_blockimpl.h"
#include <qscrollbar.h>
#include <qptrvector.h>
#if APPLE_CHANGES
#include "KWQKHTMLPart.h" // For Dashboard.
#endif
using namespace DOM;
using namespace khtml;
#ifdef APPLE_CHANGES
QScrollBar* RenderLayer::gScrollBar = 0;
#endif
#ifndef NDEBUG
static bool inRenderLayerDetach;
#endif
void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw()
{
return renderArena->allocate(sz);
}
void ClipRects::operator delete(void* ptr, size_t sz)
{
// Stash size where detach can find it.
*(size_t *)ptr = sz;
}
void ClipRects::detach(RenderArena* renderArena)
{
delete this;
// Recover the size left there for us by operator delete and free the memory.
renderArena->free(*(size_t *)this, this);
}
void
RenderScrollMediator::slotValueChanged(int val)
{
m_layer->updateScrollPositionFromScrollbars();
}
RenderLayer::RenderLayer(RenderObject* object)
: m_object( object ),
m_parent( 0 ),
m_previous( 0 ),
m_next( 0 ),
m_first( 0 ),
m_last( 0 ),
m_relX( 0 ),
m_relY( 0 ),
m_x( 0 ),
m_y( 0 ),
m_width( 0 ),
m_height( 0 ),
m_scrollX( 0 ),
m_scrollY( 0 ),
m_scrollWidth( 0 ),
m_scrollHeight( 0 ),
m_hBar( 0 ),
m_vBar( 0 ),
m_scrollMediator( 0 ),
m_posZOrderList( 0 ),
m_negZOrderList( 0 ),
m_clipRects( 0 ) ,
m_scrollDimensionsDirty( true ),
m_zOrderListsDirty( true ),
m_usedTransparency( false ),
m_marquee( 0 )
{
}
RenderLayer::~RenderLayer()
{
// Child layers will be deleted by their corresponding render objects, so
// our destructor doesn't have to do anything.
delete m_hBar;
delete m_vBar;
delete m_scrollMediator;
delete m_posZOrderList;
delete m_negZOrderList;
delete m_marquee;
// Make sure we have no lingering clip rects.
assert(!m_clipRects);
}
void RenderLayer::computeRepaintRects()
{
// FIXME: Child object could override visibility.
if (m_object->style()->visibility() == VISIBLE)
m_object->getAbsoluteRepaintRectIncludingFloats(m_repaintRect, m_fullRepaintRect);
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
child->computeRepaintRects();
}
void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
{
if (doFullRepaint) {
m_object->repaint();
checkForRepaint = doFullRepaint = false;
}
updateLayerPosition(); // For relpositioned layers or non-positioned layers,
// we need to keep in sync, since we may have shifted relative
// to our parent layer.
if (m_hBar || m_vBar) {
// Need to position the scrollbars.
int x = 0;
int y = 0;
convertToLayerCoords(root(), x, y);
QRect layerBounds = QRect(x,y,width(),height());
positionScrollbars(layerBounds);
}
// FIXME: Child object could override visibility.
if (checkForRepaint && (m_object->style()->visibility() == VISIBLE))
m_object->repaintAfterLayoutIfNeeded(m_repaintRect, m_fullRepaintRect);
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
child->updateLayerPositions(doFullRepaint, checkForRepaint);
// With all our children positioned, now update our marquee if we need to.
if (m_marquee)
m_marquee->updateMarqueePosition();
}
void RenderLayer::updateLayerPosition()
{
// Clear our cached clip rect information.
clearClipRect();
// The canvas is sized to the docWidth/Height over in RenderCanvas::layout, so we
// don't need to ever update our layer position here.
if (renderer()->isCanvas())
return;
int x = m_object->xPos();
int y = m_object->yPos();
if (!m_object->isPositioned()) {
// We must adjust our position by walking up the render tree looking for the
// nearest enclosing object with a layer.
RenderObject* curr = m_object->parent();
while (curr && !curr->layer()) {
x += curr->xPos();
y += curr->yPos();
curr = curr->parent();
}
}
m_relX = m_relY = 0;
if (m_object->isRelPositioned()) {
static_cast<RenderBox*>(m_object)->relativePositionOffset(m_relX, m_relY);
x += m_relX; y += m_relY;
}
// Subtract our parent's scroll offset.
if (m_object->isPositioned() && enclosingPositionedAncestor()) {
RenderLayer* positionedParent = enclosingPositionedAncestor();
// For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
positionedParent->subtractScrollOffset(x, y);
if (m_object->isPositioned() && positionedParent->renderer()->isRelPositioned() &&
positionedParent->renderer()->isInlineFlow()) {
// When we have an enclosing relpositioned inline, we need to add in the offset of the first line
// box from the rest of the content, but only in the cases where we know we're positioned
// relative to the inline itself.
RenderFlow* flow = static_cast<RenderFlow*>(positionedParent->renderer());
int sx = 0, sy = 0;
if (flow->firstLineBox()) {
sx = flow->firstLineBox()->xPos();
sy = flow->firstLineBox()->yPos();
}
else {
sx = flow->staticX();
sy = flow->staticY();
}
bool isInlineType = m_object->style()->isOriginalDisplayInlineType();
if (!m_object->hasStaticX())
x += sx;
// This is not terribly intuitive, but we have to match other browsers. Despite being a block display type inside
// an inline, we still keep our x locked to the left of the relative positioned inline. Arguably the correct
// behavior would be to go flush left to the block that contains the inline, but that isn't what other browsers
// do.
if (m_object->hasStaticX() && !isInlineType)
// Avoid adding in the left border/padding of the containing block twice. Subtract it out.
x += sx - (m_object->containingBlock()->borderLeft() + m_object->containingBlock()->paddingLeft());
if (!m_object->hasStaticY())
y += sy;
}
}
else if (parent())
parent()->subtractScrollOffset(x, y);
setPos(x,y);
setWidth(m_object->width());
setHeight(m_object->height());
if (!m_object->hasOverflowClip()) {
if (m_object->overflowWidth() > m_object->width())
setWidth(m_object->overflowWidth());
if (m_object->overflowHeight() > m_object->height())
setHeight(m_object->overflowHeight());
}
}
RenderLayer *RenderLayer::stackingContext() const
{
RenderLayer* curr = parent();
for ( ; curr && !curr->m_object->isCanvas() && !curr->m_object->isRoot() &&
curr->m_object->style()->hasAutoZIndex();
curr = curr->parent());
return curr;
}
RenderLayer*
RenderLayer::enclosingPositionedAncestor() const
{
RenderLayer* curr = parent();
for ( ; curr && !curr->m_object->isCanvas() && !curr->m_object->isRoot() &&
!curr->m_object->isPositioned() && !curr->m_object->isRelPositioned();
curr = curr->parent());
return curr;
}
#if APPLE_CHANGES
bool
RenderLayer::isTransparent()
{
return m_object->style()->opacity() < 1.0f;
}
RenderLayer*
RenderLayer::transparentAncestor()
{
RenderLayer* curr = parent();
for ( ; curr && curr->m_object->style()->opacity() == 1.0f; curr = curr->parent());
return curr;
}
void RenderLayer::beginTransparencyLayers(QPainter* p)
{
if (isTransparent() && m_usedTransparency)
return;
RenderLayer* ancestor = transparentAncestor();
if (ancestor)
ancestor->beginTransparencyLayers(p);
if (isTransparent()) {
m_usedTransparency = true;
p->beginTransparencyLayer(renderer()->style()->opacity());
}
}
#endif
void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
{
return renderArena->allocate(sz);
}
void RenderLayer::operator delete(void* ptr, size_t sz)
{
assert(inRenderLayerDetach);
// Stash size where detach can find it.
*(size_t *)ptr = sz;
}
void RenderLayer::detach(RenderArena* renderArena)
{
#ifndef NDEBUG
inRenderLayerDetach = true;
#endif
delete this;
#ifndef NDEBUG
inRenderLayerDetach = false;
#endif
// Recover the size left there for us by operator delete and free the memory.
renderArena->free(*(size_t *)this, this);
}
void RenderLayer::addChild(RenderLayer *child, RenderLayer* beforeChild)
{
RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
if (prevSibling) {
child->setPreviousSibling(prevSibling);
prevSibling->setNextSibling(child);
}
else
setFirstChild(child);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -