IntRect RenderVideo::videoBox() const { if (m_cachedImageSize.isEmpty() && videoElement()->shouldDisplayPosterImage()) return IntRect(); LayoutSize elementSize; if (videoElement()->shouldDisplayPosterImage()) elementSize = m_cachedImageSize; else elementSize = intrinsicSize(); IntRect contentRect = pixelSnappedIntRect(contentBoxRect()); if (elementSize.isEmpty() || contentRect.isEmpty()) return IntRect(); LayoutRect renderBox = contentRect; LayoutUnit ratio = renderBox.width() * elementSize.height() - renderBox.height() * elementSize.width(); if (ratio > 0) { LayoutUnit newWidth = renderBox.height() * elementSize.width() / elementSize.height(); // Just fill the whole area if the difference is one pixel or less (in both sides) if (renderBox.width() - newWidth > 2) renderBox.setWidth(newWidth); renderBox.move((contentRect.width() - renderBox.width()) / 2, 0); } else if (ratio < 0) { LayoutUnit newHeight = renderBox.width() * elementSize.height() / elementSize.width(); if (renderBox.height() - newHeight > 2) renderBox.setHeight(newHeight); renderBox.move(0, (contentRect.height() - renderBox.height()) / 2); } return pixelSnappedIntRect(renderBox); }
LayoutUnit LayoutMedia::computePanelWidth(const LayoutRect& mediaRect) const { // TODO(mlamouri): we don't know if the main frame has an horizontal scrollbar // if it is out of process. See https://crbug.com/662480 if (document().page()->mainFrame()->isRemoteFrame()) return mediaRect.width(); FrameHost* frameHost = document().frameHost(); LocalFrame* mainFrame = document().page()->deprecatedLocalMainFrame(); FrameView* pageView = mainFrame ? mainFrame->view() : nullptr; if (!frameHost || !mainFrame || !pageView) return mediaRect.width(); if (pageView->horizontalScrollbarMode() != ScrollbarAlwaysOff) return mediaRect.width(); // On desktop, this will include scrollbars when they stay visible. const LayoutUnit visibleWidth(frameHost->visualViewport().visibleWidth()); const LayoutUnit absoluteXOffset( localToAbsolute( FloatPoint(mediaRect.location()), UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries) .x()); DCHECK_GE(visibleWidth - absoluteXOffset, 0); return std::min(mediaRect.width(), visibleWidth - absoluteXOffset); }
void MediaPlayerPrivate::resizeSourceDimensions() { if (!m_webCorePlayer) return; if (!m_webCorePlayer->mediaPlayerClient()->mediaPlayerIsVideo()) return; // If we have an HTMLVideoElement but the source has no video, then we need to resize the media element. if (!hasVideo() && PlatformPlayer::MediaOK == m_platformPlayer->error()) { LayoutRect rect = m_webCorePlayer->mediaPlayerClient()->mediaPlayerContentBoxRect(); static const int playbookMinAudioElementWidth = 300; static const int playbookMinAudioElementHeight = 32; // If the rect dimensions are less than the allowed minimum, use the minimum instead. int newWidth = max(rect.width().toInt(), playbookMinAudioElementWidth); int newHeight = max(rect.height().toInt(), playbookMinAudioElementHeight); m_webCorePlayer->mediaPlayerClient()->mediaPlayerSetSize(IntSize(newWidth, newHeight)); } // If we don't know what the width and height of the video source is, then we need to set it to something sane. if (m_platformPlayer->sourceWidth() && m_platformPlayer->sourceHeight()) return; LayoutRect rect = m_webCorePlayer->mediaPlayerClient()->mediaPlayerContentBoxRect(); m_platformPlayer->setSourceDimension(rect.width().toUnsigned(), rect.height().toUnsigned()); }
LayoutRect RenderReplaced::replacedContentRect(const LayoutSize& intrinsicSize) const { LayoutRect contentRect = contentBoxRect(); ObjectFit objectFit = style().objectFit(); if (objectFit == ObjectFitFill) return contentRect; if (!intrinsicSize.width() || !intrinsicSize.height()) return contentRect; LayoutRect finalRect = contentRect; switch (objectFit) { case ObjectFitContain: case ObjectFitScaleDown: case ObjectFitCover: finalRect.setSize(finalRect.size().fitToAspectRatio(intrinsicSize, objectFit == ObjectFitCover ? AspectRatioFitGrow : AspectRatioFitShrink)); if (objectFit != ObjectFitScaleDown || finalRect.width() <= intrinsicSize.width()) break; // fall through case ObjectFitNone: finalRect.setSize(intrinsicSize); break; case ObjectFitFill: ASSERT_NOT_REACHED(); } // FIXME: This is where object-position should be taken into account, but since it's not // implemented yet, assume the initial value of "50% 50%". LayoutUnit xOffset = (contentRect.width() - finalRect.width()) / 2; LayoutUnit yOffset = (contentRect.height() - finalRect.height()) / 2; finalRect.move(xOffset, yOffset); return finalRect; }
static LayoutRect clipRectForNinePieceImageStrip(const InlineFlowBox& box, const NinePieceImage& image, const LayoutRect& paintRect) { LayoutRect clipRect(paintRect); const ComputedStyle& style = box.lineLayoutItem().styleRef(); LayoutRectOutsets outsets = style.imageOutsets(image); if (box.isHorizontal()) { clipRect.setY(paintRect.y() - outsets.top()); clipRect.setHeight(paintRect.height() + outsets.top() + outsets.bottom()); if (box.includeLogicalLeftEdge()) { clipRect.setX(paintRect.x() - outsets.left()); clipRect.setWidth(paintRect.width() + outsets.left()); } if (box.includeLogicalRightEdge()) clipRect.setWidth(clipRect.width() + outsets.right()); } else { clipRect.setX(paintRect.x() - outsets.left()); clipRect.setWidth(paintRect.width() + outsets.left() + outsets.right()); if (box.includeLogicalLeftEdge()) { clipRect.setY(paintRect.y() - outsets.top()); clipRect.setHeight(paintRect.height() + outsets.top()); } if (box.includeLogicalRightEdge()) clipRect.setHeight(clipRect.height() + outsets.bottom()); } return clipRect; }
LayoutRect RenderReplaced::replacedContentRect(const LayoutSize& intrinsicSize) const { LayoutRect contentRect = contentBoxRect(); if (intrinsicSize.isEmpty()) return contentRect; ObjectFit objectFit = style().objectFit(); LayoutRect finalRect = contentRect; switch (objectFit) { case ObjectFitContain: case ObjectFitScaleDown: case ObjectFitCover: finalRect.setSize(finalRect.size().fitToAspectRatio(intrinsicSize, objectFit == ObjectFitCover ? AspectRatioFitGrow : AspectRatioFitShrink)); if (objectFit != ObjectFitScaleDown || finalRect.width() <= intrinsicSize.width()) break; FALLTHROUGH; case ObjectFitNone: finalRect.setSize(intrinsicSize); break; case ObjectFitFill: break; } LengthPoint objectPosition = style().objectPosition(); LayoutUnit xOffset = minimumValueForLength(objectPosition.x(), contentRect.width() - finalRect.width()); LayoutUnit yOffset = minimumValueForLength(objectPosition.y(), contentRect.height() - finalRect.height()); finalRect.move(xOffset, yOffset); return finalRect; }
void RoundedRect::inflateWithRadii(const LayoutUnit& size) { LayoutRect old = m_rect; m_rect.inflate(size); // Considering the inflation factor of shorter size to scale the radii seems appropriate here float factor; if (m_rect.width() < m_rect.height()) factor = old.width() ? (float)m_rect.width() / old.width() : int(0); else factor = old.height() ? (float)m_rect.height() / old.height() : int(0); m_radii.scale(factor); }
void IntersectionObserver::applyRootMargin(LayoutRect& rect) const { // TODO(szager): Make sure the spec is clear that left/right margins are resolved against // width and not height. LayoutUnit topMargin = computeMargin(m_topMargin, rect.height()); LayoutUnit rightMargin = computeMargin(m_rightMargin, rect.width()); LayoutUnit bottomMargin = computeMargin(m_bottomMargin, rect.height()); LayoutUnit leftMargin = computeMargin(m_leftMargin, rect.width()); rect.setX(rect.x() - leftMargin); rect.setWidth(rect.width() + leftMargin + rightMargin); rect.setY(rect.y() - topMargin); rect.setHeight(rect.height() + topMargin + bottomMargin); }
static void deflateIfOverlapped(LayoutRect& a, LayoutRect& b) { if (!a.intersects(b) || a.contains(b) || b.contains(a)) return; LayoutUnit deflateFactor = -fudgeFactor(); // Avoid negative width or height values. if ((a.width() + 2 * deflateFactor > 0) && (a.height() + 2 * deflateFactor > 0)) a.inflate(deflateFactor); if ((b.width() + 2 * deflateFactor > 0) && (b.height() + 2 * deflateFactor > 0)) b.inflate(deflateFactor); }
LayoutRect LayoutReplaced::computeObjectFit( const LayoutSize* overriddenIntrinsicSize) const { LayoutRect contentRect = contentBoxRect(); ObjectFit objectFit = style()->getObjectFit(); if (objectFit == ObjectFitFill && style()->objectPosition() == ComputedStyle::initialObjectPosition()) { return contentRect; } // TODO(davve): intrinsicSize doubles as both intrinsic size and intrinsic // ratio. In the case of SVG images this isn't correct since they can have // intrinsic ratio but no intrinsic size. In order to maintain aspect ratio, // the intrinsic size for SVG might be faked from the aspect ratio, // see SVGImage::containerSize(). LayoutSize intrinsicSize = overriddenIntrinsicSize ? *overriddenIntrinsicSize : this->intrinsicSize(); if (!intrinsicSize.width() || !intrinsicSize.height()) return contentRect; LayoutRect finalRect = contentRect; switch (objectFit) { case ObjectFitContain: case ObjectFitScaleDown: case ObjectFitCover: finalRect.setSize(finalRect.size().fitToAspectRatio( intrinsicSize, objectFit == ObjectFitCover ? AspectRatioFitGrow : AspectRatioFitShrink)); if (objectFit != ObjectFitScaleDown || finalRect.width() <= intrinsicSize.width()) break; // fall through case ObjectFitNone: finalRect.setSize(intrinsicSize); break; case ObjectFitFill: break; default: ASSERT_NOT_REACHED(); } LayoutUnit xOffset = minimumValueForLength( style()->objectPosition().x(), contentRect.width() - finalRect.width()); LayoutUnit yOffset = minimumValueForLength( style()->objectPosition().y(), contentRect.height() - finalRect.height()); finalRect.move(xOffset, yOffset); return finalRect; }
void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect) { if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() || rect.width() <= 0 || rect.height() <= 0) return; RefPtr<Image> img = m_imageResource->image(rect.width(), rect.height()); if (!img || img->isNull()) return; HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(node()) : 0; CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver; Image* image = m_imageResource->image().get(); bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, rect.size()); context->drawImage(m_imageResource->image(rect.width(), rect.height()).get(), style()->colorSpace(), rect, compositeOperator, useLowQualityScaling); }
void TimelineRecordFactory::addRectData(InspectorObject* data, const LayoutRect& rect) { data->setNumber("x", rect.x()); data->setNumber("y", rect.y()); data->setNumber("width", rect.width()); data->setNumber("height", rect.height()); }
LayoutPoint ScrollableArea::constrainScrollPositionForOverhang(const LayoutRect& visibleContentRect, const LayoutSize& totalContentsSize, const LayoutPoint& scrollPosition, const LayoutPoint& scrollOrigin, int headerHeight, int footerHeight) { // The viewport rect that we're scrolling shouldn't be larger than our document. LayoutSize idealScrollRectSize(std::min(visibleContentRect.width(), totalContentsSize.width()), std::min(visibleContentRect.height(), totalContentsSize.height())); LayoutRect scrollRect(scrollPosition + scrollOrigin - LayoutSize(0, headerHeight), idealScrollRectSize); LayoutRect documentRect(LayoutPoint(), LayoutSize(totalContentsSize.width(), totalContentsSize.height() - headerHeight - footerHeight)); // Use intersection to constrain our ideal scroll rect by the document rect. scrollRect.intersect(documentRect); if (scrollRect.size() != idealScrollRectSize) { // If the rect was clipped, restore its size, effectively pushing it "down" from the top left. scrollRect.setSize(idealScrollRectSize); // If we still clip, push our rect "up" from the bottom right. scrollRect.intersect(documentRect); if (scrollRect.width() < idealScrollRectSize.width()) scrollRect.move(-(idealScrollRectSize.width() - scrollRect.width()), 0); if (scrollRect.height() < idealScrollRectSize.height()) scrollRect.move(0, -(idealScrollRectSize.height() - scrollRect.height())); } return scrollRect.location() - toLayoutSize(scrollOrigin); }
Vector<IntRect> RenderTextLineBoxes::absoluteRectsForRange(const RenderText& renderer, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed) const { Vector<IntRect> rects; for (auto box = m_first; box; box = box->nextTextBox()) { // Note: box->end() returns the index of the last character, not the index past it if (start <= box->start() && box->end() < end) { FloatRect boundaries = box->calculateBoundaries(); if (useSelectionHeight) { LayoutRect selectionRect = box->localSelectionRect(start, end); if (box->isHorizontal()) { boundaries.setHeight(selectionRect.height()); boundaries.setY(selectionRect.y()); } else { boundaries.setWidth(selectionRect.width()); boundaries.setX(selectionRect.x()); } } rects.append(renderer.localToAbsoluteQuad(boundaries, 0, wasFixed).enclosingBoundingBox()); continue; } // FIXME: This code is wrong. It's converting local to absolute twice. http://webkit.org/b/65722 FloatRect rect = localQuadForTextBox(*box, start, end, useSelectionHeight); if (!rect.isZero()) rects.append(renderer.localToAbsoluteQuad(rect, 0, wasFixed).enclosingBoundingBox()); } return rects; }
bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* magnifierObject, const PaintInfo& paintInfo, const IntRect& r) { // Get the renderer of <input> element. if (!magnifierObject->node()) return false; Node* input = magnifierObject->node()->shadowHost(); RenderObject* baseRenderer = input ? input->renderer() : magnifierObject; if (!baseRenderer->isBox()) return false; RenderBox* inputRenderBox = toRenderBox(baseRenderer); LayoutRect inputContentBox = inputRenderBox->contentBoxRect(); // Make sure the scaled decoration stays square and will fit in its parent's box. LayoutUnit magnifierSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), r.height())); // Calculate decoration's coordinates relative to the input element. // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will // be one pixel closer to the bottom of the field. This tends to look better with the text. LayoutRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(), inputContentBox.y() + (inputContentBox.height() - magnifierSize + 1) / 2, magnifierSize, magnifierSize); IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r); DEFINE_STATIC_REF(Image, magnifierImage, (Image::loadPlatformResource("searchMagnifier"))); paintInfo.context->drawImage(magnifierImage, paintingRect); return false; }
ScrollAnchor::ExamineResult ScrollAnchor::examine( const LayoutObject* candidate) const { if (candidate->isLayoutInline()) return ExamineResult(Continue); // Anonymous blocks are not in the DOM tree and it may be hard for // developers to reason about the anchor node. if (candidate->isAnonymous()) return ExamineResult(Continue); if (!candidate->isText() && !candidate->isBox()) return ExamineResult(Skip); if (!candidateMayMoveWithScroller(candidate, m_scroller)) return ExamineResult(Skip); if (candidate->style()->overflowAnchor() == AnchorNone) return ExamineResult(Skip); LayoutRect candidateRect = relativeBounds(candidate, m_scroller); LayoutRect visibleRect = scrollerLayoutBoxItem(m_scroller).overflowClipRect(LayoutPoint()); bool occupiesSpace = candidateRect.width() > 0 && candidateRect.height() > 0; if (occupiesSpace && visibleRect.intersects(candidateRect)) { return ExamineResult( visibleRect.contains(candidateRect) ? Return : Constrain, cornerToAnchor(m_scroller)); } else { return ExamineResult(Skip); } }
bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const PaintInfo& paintInfo, const IntRect& r) { // Get the renderer of <input> element. Node* input = cancelButtonObject->node()->shadowHost(); RenderObject* baseRenderer = input ? input->renderer() : cancelButtonObject; if (!baseRenderer->isBox()) return false; RenderBox* inputRenderBox = toRenderBox(baseRenderer); LayoutRect inputContentBox = inputRenderBox->contentBoxRect(); // Make sure the scaled button stays square and will fit in its parent's box. LayoutUnit cancelButtonSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), r.height())); // Calculate cancel button's coordinates relative to the input element. // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will // be one pixel closer to the bottom of the field. This tends to look better with the text. LayoutRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(inputRenderBox).width(), inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1) / 2, cancelButtonSize, cancelButtonSize); IntRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r); static Image* cancelImage = Image::loadPlatformResource("searchCancel").leakRef(); static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").leakRef(); paintInfo.context->drawImage(isPressed(cancelButtonObject) ? cancelPressedImage : cancelImage, cancelButtonObject->style()->colorSpace(), paintingRect); return false; }
Vector<FloatQuad> RenderTextLineBoxes::absoluteQuadsForRange(const RenderText& renderer, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed) const { Vector<FloatQuad> quads; for (auto box = m_first; box; box = box->nextTextBox()) { // Note: box->end() returns the index of the last character, not the index past it if (start <= box->start() && box->end() < end) { FloatRect boundaries = box->calculateBoundaries(); if (useSelectionHeight) { LayoutRect selectionRect = box->localSelectionRect(start, end); if (box->isHorizontal()) { boundaries.setHeight(selectionRect.height()); boundaries.setY(selectionRect.y()); } else { boundaries.setWidth(selectionRect.width()); boundaries.setX(selectionRect.x()); } } quads.append(renderer.localToAbsoluteQuad(boundaries, 0, wasFixed)); continue; } FloatRect rect = localQuadForTextBox(*box, start, end, useSelectionHeight); if (!rect.isZero()) quads.append(renderer.localToAbsoluteQuad(rect, 0, wasFixed)); } return quads; }
static LayoutRect relevantViewRect(RenderView* view) { // DidHitRelevantRepaintedObjectsAreaThreshold is a LayoutMilestone intended to indicate that // a certain relevant amount of content has been drawn to the screen. This is the rect that // has been determined to be relevant in the context of this goal. We may choose to tweak // the rect over time, much like we may choose to tweak gMinimumPaintedAreaRatio and // gMaximumUnpaintedAreaRatio. But this seems to work well right now. LayoutRect relevantViewRect = LayoutRect(0, 0, 980, 1300); LayoutRect viewRect = view->viewRect(); // If the viewRect is wider than the relevantViewRect, center the relevantViewRect. if (viewRect.width() > relevantViewRect.width()) relevantViewRect.setX((viewRect.width() - relevantViewRect.width()) / 2); return relevantViewRect; }
bool canScrollInDirection(const Frame* frame, FocusDirection direction) { if (!frame->view()) return false; ScrollbarMode verticalMode; ScrollbarMode horizontalMode; frame->view()->calculateScrollbarModesForLayout(horizontalMode, verticalMode); if ((direction == FocusDirectionLeft || direction == FocusDirectionRight) && ScrollbarAlwaysOff == horizontalMode) return false; if ((direction == FocusDirectionUp || direction == FocusDirectionDown) && ScrollbarAlwaysOff == verticalMode) return false; LayoutSize size = frame->view()->totalContentsSize(); LayoutSize offset = frame->view()->scrollOffset(); LayoutRect rect = frame->view()->visibleContentRectIncludingScrollbars(); switch (direction) { case FocusDirectionLeft: return offset.width() > 0; case FocusDirectionUp: return offset.height() > 0; case FocusDirectionRight: return rect.width() + offset.width() < size.width(); case FocusDirectionDown: return rect.height() + offset.height() < size.height(); default: ASSERT_NOT_REACHED(); return false; } }
void LayoutTextControlSingleLine::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const { LayoutTextControl::paint(paintInfo, paintOffset); if (shouldPaintSelfBlockBackground(paintInfo.phase) && m_shouldDrawCapsLockIndicator) { if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible( paintInfo.context, *this, paintInfo.phase)) return; LayoutRect contentsRect = contentBoxRect(); // Center in the block progression direction. if (isHorizontalWritingMode()) contentsRect.setY((size().height() - contentsRect.height()) / 2); else contentsRect.setX((size().width() - contentsRect.width()) / 2); // Convert the rect into the coords used for painting the content contentsRect.moveBy(paintOffset + location()); IntRect snappedRect = pixelSnappedIntRect(contentsRect); LayoutObjectDrawingRecorder recorder(paintInfo.context, *this, paintInfo.phase, snappedRect); LayoutTheme::theme().painter().paintCapsLockIndicator(*this, paintInfo, snappedRect); } }
bool canScrollInDirection(const LocalFrame* frame, FocusType type) { if (!frame->view()) return false; ScrollbarMode verticalMode; ScrollbarMode horizontalMode; frame->view()->calculateScrollbarModesForLayoutAndSetViewportRenderer(horizontalMode, verticalMode); if ((type == FocusTypeLeft || type == FocusTypeRight) && ScrollbarAlwaysOff == horizontalMode) return false; if ((type == FocusTypeUp || type == FocusTypeDown) && ScrollbarAlwaysOff == verticalMode) return false; LayoutSize size = frame->view()->contentsSize(); LayoutSize offset = frame->view()->scrollOffset(); LayoutRect rect = frame->view()->visibleContentRect(IncludeScrollbars); switch (type) { case FocusTypeLeft: return offset.width() > 0; case FocusTypeUp: return offset.height() > 0; case FocusTypeRight: return rect.width() + offset.width() < size.width(); case FocusTypeDown: return rect.height() + offset.height() < size.height(); default: ASSERT_NOT_REACHED(); return false; } }
LayoutPoint MultiColumnFragmentainerGroup::visualPointToFlowThreadPoint( const LayoutPoint& visualPoint) const { unsigned columnIndex = columnIndexAtVisualPoint(visualPoint); LayoutRect columnRect = columnRectAt(columnIndex); LayoutPoint localPoint(visualPoint); localPoint.moveBy(-columnRect.location()); // Before converting to a flow thread position, if the block direction // coordinate is outside the column, snap to the bounds of the column, and // reset the inline direction coordinate to the start position in the column. // The effect of this is that if the block position is before the column // rectangle, we'll get to the beginning of this column, while if the block // position is after the column rectangle, we'll get to the beginning of the // next column. if (!m_columnSet.isHorizontalWritingMode()) { LayoutUnit columnStart = m_columnSet.style()->isLeftToRightDirection() ? LayoutUnit() : columnRect.height(); if (localPoint.x() < 0) localPoint = LayoutPoint(LayoutUnit(), columnStart); else if (localPoint.x() > logicalHeight()) localPoint = LayoutPoint(logicalHeight(), columnStart); return LayoutPoint(localPoint.x() + logicalTopInFlowThreadAt(columnIndex), localPoint.y()); } LayoutUnit columnStart = m_columnSet.style()->isLeftToRightDirection() ? LayoutUnit() : columnRect.width(); if (localPoint.y() < 0) localPoint = LayoutPoint(columnStart, LayoutUnit()); else if (localPoint.y() > logicalHeight()) localPoint = LayoutPoint(columnStart, logicalHeight()); return LayoutPoint(localPoint.x(), localPoint.y() + logicalTopInFlowThreadAt(columnIndex)); }
LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos) const { int sPos = std::max(startPos - m_start, 0); int ePos = std::min(endPos - m_start, (int)m_len); if (sPos > ePos) return LayoutRect(); FontCachePurgePreventer fontCachePurgePreventer; LayoutUnit selTop = root().selectionTop(); LayoutUnit selHeight = root().selectionHeight(); const ComputedStyle& styleToUse = lineLayoutItem().styleRef(isFirstLineStyle()); const Font& font = styleToUse.font(); StringBuilder charactersWithHyphen; bool respectHyphen = ePos == m_len && hasHyphen(); TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charactersWithHyphen : 0); LayoutPoint startingPoint = LayoutPoint(logicalLeft(), selTop); LayoutRect r; if (sPos || ePos != static_cast<int>(m_len)) { r = LayoutRect(enclosingIntRect(font.selectionRectForText(textRun, FloatPoint(startingPoint), selHeight, sPos, ePos))); } else { // Avoid computing the font width when the entire line box is selected as an optimization. // FIXME: the call to rawValue() below is temporary and should be removed once the transition // to LayoutUnit-based types is complete (crbug.com/321237) r = LayoutRect(enclosingIntRect(LayoutRect(startingPoint, LayoutSize(m_logicalWidth, selHeight)))); } LayoutUnit logicalWidth = r.width(); if (r.x() > logicalRight()) logicalWidth = 0; else if (r.maxX() > logicalRight()) logicalWidth = logicalRight() - r.x(); LayoutPoint topPoint; LayoutUnit width; LayoutUnit height; if (isHorizontal()) { topPoint = LayoutPoint(r.x(), selTop); width = logicalWidth; height = selHeight; if (hasWrappedSelectionNewline()) { if (!isLeftToRightDirection()) topPoint.setX(topPoint.x() - newlineSpaceWidth()); width += newlineSpaceWidth(); } } else { topPoint = LayoutPoint(selTop, r.x()); width = selHeight; height = logicalWidth; // TODO(wkorman): RTL text embedded in top-to-bottom text can create // bottom-to-top situations. Add tests and ensure we handle correctly. if (hasWrappedSelectionNewline()) height += newlineSpaceWidth(); } return LayoutRect(topPoint, LayoutSize(width, height)); }
// FIXME: Move this somewhere more generic. void PrintTo(const LayoutRect& rect, std::ostream* os) { *os << "LayoutRect(" << rect.x().toFloat() << ", " << rect.y().toFloat() << ", " << rect.width().toFloat() << ", " << rect.height().toFloat() << ")"; }
void LayoutImage::updateInnerContentRect() { // Propagate container size to the image resource. LayoutRect containerRect = replacedContentRect(); IntSize containerSize(containerRect.width(), containerRect.height()); if (!containerSize.isEmpty()) m_imageResource->setContainerSizeForLayoutObject(containerSize); }
IntRect enclosingIntRect(const LayoutRect& rect) { // Empty rects with fractional x, y values turn into non-empty rects when converting to enclosing. // We need to ensure that empty rects stay empty after the conversion, because the selection code expects them to be empty. IntPoint location = flooredIntPoint(rect.minXMinYCorner()); IntPoint maxPoint = IntPoint(rect.width() ? rect.maxX().ceil() : location.x(), rect.height() ? rect.maxY().ceil() : location.y()); return IntRect(location, maxPoint - location); }
// Checks if |node| is offscreen the visible area (viewport) of its container // document. In case it is, one can scroll in direction or take any different // desired action later on. bool hasOffscreenRect(Node* node, FocusType type) { // Get the FrameView in which |node| is (which means the current viewport if |node| // is not in an inner document), so we can check if its content rect is visible // before we actually move the focus to it. FrameView* frameView = node->document().view(); if (!frameView) return true; ASSERT(!frameView->needsLayout()); LayoutRect containerViewportRect = frameView->visibleContentRect(); // We want to select a node if it is currently off screen, but will be // exposed after we scroll. Adjust the viewport to post-scrolling position. // If the container has overflow:hidden, we cannot scroll, so we do not pass direction // and we do not adjust for scrolling. switch (type) { case FocusTypeLeft: containerViewportRect.setX(containerViewportRect.x() - ScrollableArea::pixelsPerLineStep()); containerViewportRect.setWidth(containerViewportRect.width() + ScrollableArea::pixelsPerLineStep()); break; case FocusTypeRight: containerViewportRect.setWidth(containerViewportRect.width() + ScrollableArea::pixelsPerLineStep()); break; case FocusTypeUp: containerViewportRect.setY(containerViewportRect.y() - ScrollableArea::pixelsPerLineStep()); containerViewportRect.setHeight(containerViewportRect.height() + ScrollableArea::pixelsPerLineStep()); break; case FocusTypeDown: containerViewportRect.setHeight(containerViewportRect.height() + ScrollableArea::pixelsPerLineStep()); break; default: break; } RenderObject* render = node->renderer(); if (!render) return true; LayoutRect rect(render->absoluteClippedOverflowRect()); if (rect.isEmpty()) return true; return !containerViewportRect.intersects(rect); }
static LayoutSize itemOffsetForAlignment(TextRun textRun, RenderStyle* itemStyle, Font itemFont, LayoutRect itemBoudingBox) { ETextAlign actualAlignment = itemStyle->textAlign(); // FIXME: Firefox doesn't respect JUSTIFY. Should we? if (actualAlignment == TAAUTO || actualAlignment == JUSTIFY) actualAlignment = itemStyle->isLeftToRightDirection() ? LEFT : RIGHT; LayoutSize offset = LayoutSize(0, itemFont.fontMetrics().ascent()); if (actualAlignment == RIGHT || actualAlignment == WEBKIT_RIGHT) { float textWidth = itemFont.width(textRun); offset.setWidth(itemBoudingBox.width() - textWidth - optionsSpacingHorizontal); } else if (actualAlignment == CENTER || actualAlignment == WEBKIT_CENTER) { float textWidth = itemFont.width(textRun); offset.setWidth((itemBoudingBox.width() - textWidth) / 2); } else offset.setWidth(optionsSpacingHorizontal); return offset; }
static bool isValidRasterShapeRect(const LayoutRect& rect) { static double maxImageSizeBytes = 0; if (!maxImageSizeBytes) { size_t size32MaxBytes = 0xFFFFFFFF / 4; // Some platforms don't limit maxDecodedImageBytes. maxImageSizeBytes = std::min(size32MaxBytes, Platform::current()->maxDecodedImageBytes()); } return (rect.width().toFloat() * rect.height().toFloat() * 4.0) < maxImageSizeBytes; }