📄 render_layer.cpp
字号:
else parentLayer = parent(); if (!parentLayer) return; parentLayer->convertToLayerCoords(ancestorLayer, x, y); if (m_object->style()->position() == ABSOLUTE && parentLayer->renderer()->style()->position() == RELATIVE && parentLayer->renderer()->isInline() && !parentLayer->renderer()->isReplaced()) { // 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*>(parentLayer->renderer()); if (flow->firstLineBox()) { bool isInlineType = m_object->style()->isOriginalDisplayInlineType(); if (!m_object->hasStaticX() || (m_object->hasStaticX() && !isInlineType)) x += flow->firstLineBox()->xPos(); if (!m_object->hasStaticY()) y += flow->firstLineBox()->yPos(); } } x += xPos(); y += yPos();}voidRenderLayer::scrollOffset(int& x, int& y){ x += scrollXOffset(); y += scrollYOffset();}voidRenderLayer::subtractScrollOffset(int& x, int& y){ x -= scrollXOffset(); y -= scrollYOffset();}voidRenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint){ if (renderer()->style()->overflow() != OMARQUEE) { if (x < 0) x = 0; if (y < 0) y = 0; // Call the scrollWidth/Height functions so that the dimensions will be computed if they need // to be (for overflow:hidden blocks). int maxX = scrollWidth() - m_object->clientWidth(); int maxY = scrollHeight() - m_object->clientHeight(); if (x > maxX) x = maxX; if (y > maxY) y = maxY; } // FIXME: Eventually, we will want to perform a blit. For now never // blit, since the check for blitting is going to be very // complicated (since it will involve testing whether our layer // is either occluded by another layer or clipped by an enclosing // layer or contains fixed backgrounds, etc.). m_scrollX = x; m_scrollY = y; // Update the positions of our child layers. for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) child->updateLayerPositions(); #if APPLE_CHANGES // Move our widgets. m_object->updateWidgetPositions();#endif // Fire the scroll DOM event. m_object->element()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false); // Just schedule a full repaint of our object. if (repaint) m_object->repaint(true); if (updateScrollbars) { if (m_hBar) m_hBar->setValue(m_scrollX); if (m_vBar) m_vBar->setValue(m_scrollY); }}voidRenderLayer::updateScrollPositionFromScrollbars(){ bool needUpdate = false; int newX = m_scrollX; int newY = m_scrollY; if (m_hBar) { newX = m_hBar->value(); if (newX != m_scrollX) needUpdate = true; } if (m_vBar) { newY = m_vBar->value(); if (newY != m_scrollY) needUpdate = true; } if (needUpdate) scrollToOffset(newX, newY, false);}voidRenderLayer::setHasHorizontalScrollbar(bool hasScrollbar){ if (hasScrollbar && !m_hBar) { QScrollView* scrollView = m_object->element()->getDocument()->view(); m_hBar = new QScrollBar(Qt::Horizontal, scrollView); scrollView->addChild(m_hBar, 0, -50000); if (!m_scrollMediator) m_scrollMediator = new RenderScrollMediator(this); m_scrollMediator->connect(m_hBar, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int))); } else if (!hasScrollbar && m_hBar) { m_scrollMediator->disconnect(m_hBar, SIGNAL(valueChanged(int)), m_scrollMediator, SLOT(slotValueChanged(int))); delete m_hBar; m_hBar = 0; }}voidRenderLayer::setHasVerticalScrollbar(bool hasScrollbar){ if (hasScrollbar && !m_vBar) { QScrollView* scrollView = m_object->element()->getDocument()->view(); m_vBar = new QScrollBar(Qt::Vertical, scrollView); scrollView->addChild(m_vBar, 0, -50000); if (!m_scrollMediator) m_scrollMediator = new RenderScrollMediator(this); m_scrollMediator->connect(m_vBar, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int))); } else if (!hasScrollbar && m_vBar) { m_scrollMediator->disconnect(m_vBar, SIGNAL(valueChanged(int)), m_scrollMediator, SLOT(slotValueChanged(int))); delete m_vBar; m_vBar = 0; }}intRenderLayer::verticalScrollbarWidth(){ if (!m_vBar) return 0; return m_vBar->width();}intRenderLayer::horizontalScrollbarHeight(){ if (!m_hBar) return 0; return m_hBar->height();}voidRenderLayer::moveScrollbarsAside(){ if (m_hBar) m_hBar->move(0, -50000); if (m_vBar) m_vBar->move(0, -50000);}voidRenderLayer::positionScrollbars(const QRect& absBounds){ if (m_vBar) { m_vBar->move(absBounds.x()+absBounds.width()-m_object->borderRight()-m_vBar->width(), absBounds.y()+m_object->borderTop()); m_vBar->resize(m_vBar->width(), absBounds.height() - (m_object->borderTop()+m_object->borderBottom()) - (m_hBar ? m_hBar->height()-1 : 0)); } if (m_hBar) { m_hBar->move(absBounds.x()+m_object->borderLeft(), absBounds.y()+absBounds.height()-m_object->borderBottom()-m_hBar->height()); m_hBar->resize(absBounds.width() - (m_object->borderLeft()+m_object->borderRight()) - (m_vBar ? m_vBar->width()-1 : 0), m_hBar->height()); }}#define LINE_STEP 10#define PAGE_KEEP 40int RenderLayer::scrollWidth(){ if (m_scrollDimensionsDirty) computeScrollDimensions(); return m_scrollWidth;}int RenderLayer::scrollHeight(){ if (m_scrollDimensionsDirty) computeScrollDimensions(); return m_scrollHeight;}void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar){ m_scrollDimensionsDirty = false; int rightPos = m_object->rightmostPosition(true, false) - m_object->borderLeft(); int bottomPos = m_object->lowestPosition(true, false) - m_object->borderTop(); int clientWidth = m_object->clientWidth(); int clientHeight = m_object->clientHeight(); m_scrollWidth = kMax(rightPos, clientWidth); m_scrollHeight = kMax(bottomPos, clientHeight); if (needHBar) *needHBar = rightPos > clientWidth; if (needVBar) *needVBar = bottomPos > clientHeight;}voidRenderLayer::updateScrollInfoAfterLayout(){ m_scrollDimensionsDirty = true; if (m_object->style()->overflow() == OHIDDEN) return; // All we had to do was dirty. bool needHorizontalBar, needVerticalBar; computeScrollDimensions(&needHorizontalBar, &needVerticalBar); bool haveHorizontalBar = m_hBar; bool haveVerticalBar = m_vBar; // overflow:scroll should just enable/disable. if (m_object->style()->overflow() == OSCROLL) { m_hBar->setEnabled(needHorizontalBar); m_vBar->setEnabled(needVerticalBar); } // overflow:auto may need to lay out again if scrollbars got added/removed. bool scrollbarsChanged = (m_object->hasAutoScrollbars()) && (haveHorizontalBar != needHorizontalBar || haveVerticalBar != needVerticalBar); if (scrollbarsChanged) { setHasHorizontalScrollbar(needHorizontalBar); setHasVerticalScrollbar(needVerticalBar); m_object->repaint(); if (m_object->style()->overflow() == OAUTO) { // Our proprietary overflow: overlay value doesn't trigger a layout. m_object->setNeedsLayout(true); if (m_object->isRenderBlock()) static_cast<RenderBlock*>(m_object)->layoutBlock(true); else m_object->layout(); return; } } // Set up the range (and page step/line step). if (m_hBar) { int clientWidth = m_object->clientWidth(); int pageStep = (clientWidth-PAGE_KEEP); if (pageStep < 0) pageStep = clientWidth; m_hBar->setSteps(LINE_STEP, pageStep);#ifdef APPLE_CHANGES m_hBar->setKnobProportion(clientWidth, m_scrollWidth);#else m_hBar->setRange(0, m_scrollWidth-clientWidth); m_object->repaintRectangle(QRect(m_object->borderLeft(), m_object->borderTop() + clientHeight(), horizontalScrollbarHeight(), m_object->width() - m_object->borderLeft() - m_object->borderRight()));#endif } if (m_vBar) { int clientHeight = m_object->clientHeight(); int pageStep = (clientHeight-PAGE_KEEP); if (pageStep < 0) pageStep = clientHeight; m_vBar->setSteps(LINE_STEP, pageStep);#ifdef APPLE_CHANGES m_vBar->setKnobProportion(clientHeight, m_scrollHeight);#else m_vBar->setRange(0, m_scrollHeight-clientHeight);#endif m_object->repaintRectangle(QRect(m_object->borderLeft() + m_object->clientWidth(), m_object->borderTop(), verticalScrollbarWidth(), m_object->height() - m_object->borderTop() - m_object->borderBottom())); } m_object->repaint();}#if APPLE_CHANGESvoidRenderLayer::paintScrollbars(QPainter* p, const QRect& damageRect){ if (m_hBar) m_hBar->paint(p, damageRect); if (m_vBar) m_vBar->paint(p, damageRect);}#endifvoidRenderLayer::paint(QPainter *p, const QRect& damageRect, bool selectionOnly, RenderObject *paintingRoot){ paintLayer(this, p, damageRect, false, selectionOnly, paintingRoot);}static void setClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect){ if (paintDirtyRect == clipRect) return; p->save(); #if APPLE_CHANGES p->addClip(clipRect);#else QRect clippedRect = p->xForm(clipRect); QRegion creg(clippedRect); QRegion old = p->clipRegion(); if (!old.isNull()) creg = old.intersect(creg); p->setClipRegion(creg);#endif }static void restoreClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect){ if (paintDirtyRect == clipRect) return; p->restore();}voidRenderLayer::paintLayer(RenderLayer* rootLayer, QPainter *p, const QRect& paintDirtyRect, bool haveTransparency, bool selectionOnly, RenderObject *paintingRoot){ // Calculate the clip rects we should use. QRect layerBounds, damageRect, clipRectToApply; calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply); int x = layerBounds.x(); int y = layerBounds.y(); // Ensure our z-order lists are up-to-date. updateZOrderLists();#if APPLE_CHANGES if (isTransparent()) haveTransparency = true;#endif // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set). // Else, our renderer tree may or may not contain the painting root, so we pass that root along // so it will be tested against as we decend through the renderers. RenderObject *paintingRootForRenderer = 0; if (paintingRoot && !m_object->hasAncestor(paintingRoot)) { paintingRootForRenderer = paintingRoot; } // We want to paint our layer, but only if we intersect the damage rect. bool shouldPaint = intersectsDamageRect(layerBounds, damageRect); if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) {#if APPLE_CHANGES // Begin transparency layers lazily now that we know we have to paint something. if (haveTransparency) beginTransparencyLayers(p);#endif // Paint our background first, before painting any child layers. // Establish the clip used to paint our background. setClip(p, paintDirtyRect, damageRect); // Paint the background. RenderObject::PaintInfo info(p, damageRect, PaintActionElementBackground, paintingRootForRenderer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -