static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const SVGTextFragment& fragment, int startPosition, FloatRect& extent) { float scalingFactor = queryData->textRenderer->scalingFactor(); ASSERT(scalingFactor); extent.setLocation(FloatPoint(fragment.x, fragment.y - queryData->textRenderer->scaledFont().fontMetrics().floatAscent() / scalingFactor)); if (startPosition) { SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset, startPosition); if (queryData->isVerticalText) extent.move(0, metrics.height()); else extent.move(metrics.width(), 0); } SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset + startPosition, 1); extent.setSize(FloatSize(metrics.width(), metrics.height())); AffineTransform fragmentTransform; fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength); if (fragmentTransform.isIdentity()) return; extent = fragmentTransform.mapRect(extent); }
static inline void calculateGlyphBoundaries(const QueryData* queryData, const SVGTextFragment& fragment, int startPosition, FloatRect& extent) { float scalingFactor = queryData->textLayoutObject->scalingFactor(); ASSERT(scalingFactor); FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition); glyphPosition.move(0, -queryData->textLayoutObject->scaledFont().fontMetrics().floatAscent() / scalingFactor); extent.setLocation(glyphPosition); // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends // time attempting to compute more correct glyph bounds already, handling // cursive scripts to some degree.) const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLayoutObject->layoutAttributes()->textMetricsValues(); const SVGTextMetrics& metrics = findMetricsForCharacter(textMetricsValues, fragment, startPosition); // TODO(fs): Negative glyph extents seems kind of weird to have, but // presently it can occur in some cases (like Arabic.) FloatSize glyphSize(std::max<float>(metrics.width(), 0), std::max<float>(metrics.height(), 0)); extent.setSize(glyphSize); // If RTL, adjust the starting point to align with the LHS of the glyph bounding box. if (!queryData->textBox->isLeftToRightDirection()) { if (queryData->isVerticalText) extent.move(0, -glyphSize.height()); else extent.move(-glyphSize.width(), 0); } AffineTransform fragmentTransform; fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength); extent = fragmentTransform.mapRect(extent); }
void FindIndicator::draw(GraphicsContext& graphicsContext, const IntRect& /*dirtyRect*/) { #if ENABLE(LEGACY_FIND_INDICATOR_STYLE) for (size_t i = 0; i < m_textRectsInSelectionRectCoordinates.size(); ++i) { FloatRect textRect = m_textRectsInSelectionRectCoordinates[i]; textRect.move(leftBorderThickness, topBorderThickness); FloatRect outerPathRect = inflateRect(textRect, horizontalOutsetToCenterOfLightBorder, verticalOutsetToCenterOfLightBorder); FloatRect innerPathRect = inflateRect(textRect, horizontalPaddingInsideLightBorder, verticalPaddingInsideLightBorder); { GraphicsContextStateSaver stateSaver(graphicsContext); graphicsContext.setShadow(FloatSize(shadowOffsetX, shadowOffsetY), shadowBlurRadius, shadowColor(), ColorSpaceSRGB); graphicsContext.setFillColor(lightBorderColor(), ColorSpaceDeviceRGB); graphicsContext.fillPath(pathWithRoundedRect(outerPathRect, cornerRadius)); } { GraphicsContextStateSaver stateSaver(graphicsContext); graphicsContext.clip(pathWithRoundedRect(innerPathRect, cornerRadius)); RefPtr<Gradient> gradient = Gradient::create(FloatPoint(innerPathRect.x(), innerPathRect.y()), FloatPoint(innerPathRect.x(), innerPathRect.maxY())); gradient->addColorStop(0, gradientLightColor()); gradient->addColorStop(1, gradientDarkColor()); graphicsContext.setFillGradient(gradient.releaseNonNull()); graphicsContext.fillRect(outerPathRect); } { GraphicsContextStateSaver stateSaver(graphicsContext); graphicsContext.translate(FloatSize(roundf(leftBorderThickness), roundf(topBorderThickness))); IntRect contentImageRect = enclosingIntRect(m_textRectsInSelectionRectCoordinates[i]); m_contentImage->paint(graphicsContext, m_contentImageScaleFactor, contentImageRect.location(), contentImageRect); } } #else for (auto& textRect : m_textRectsInSelectionRectCoordinates) { FloatRect blurRect = textRect; blurRect.move(flatShadowBlurRadius + flatStyleHorizontalBorder, flatShadowBlurRadius + flatStyleVerticalBorder); FloatRect outerPathRect = inflateRect(blurRect, flatStyleHorizontalBorder, flatStyleVerticalBorder); { GraphicsContextStateSaver stateSaver(graphicsContext); graphicsContext.setShadow(FloatSize(), flatRimShadowBlurRadius, flatRimShadowColor(), ColorSpaceSRGB); graphicsContext.setFillColor(flatHighlightColor(), ColorSpaceSRGB); graphicsContext.fillRect(outerPathRect); graphicsContext.setShadow(FloatSize(flatShadowOffsetX, flatShadowOffsetY), flatShadowBlurRadius, flatDropShadowColor(), ColorSpaceSRGB); graphicsContext.fillRect(outerPathRect); } { GraphicsContextStateSaver stateSaver(graphicsContext); graphicsContext.translate(FloatSize(flatShadowBlurRadius + flatStyleHorizontalBorder, flatShadowBlurRadius + flatStyleVerticalBorder)); IntRect contentImageRect = enclosingIntRect(textRect); m_contentImage->paint(graphicsContext, m_contentImageScaleFactor, contentImageRect.location(), contentImageRect); } } #endif }
FloatRect FEOffset::mapRect(const FloatRect& rect, bool forward) { FloatRect result = rect; if (forward) result.move(filter()->applyHorizontalScale(m_dx), filter()->applyVerticalScale(m_dy)); else result.move(-filter()->applyHorizontalScale(m_dx), -filter()->applyVerticalScale(m_dy)); return result; }
FloatRect VisualViewport::rootFrameToViewport( const FloatRect& rectInRootFrame) const { FloatRect rectInViewport = rectInRootFrame; rectInViewport.move(-getScrollOffset()); rectInViewport.scale(scale()); return rectInViewport; }
FloatRect VisualViewport::viewportToRootFrame( const FloatRect& rectInViewport) const { FloatRect rectInRootFrame = rectInViewport; rectInRootFrame.scale(1 / scale()); rectInRootFrame.move(getScrollOffset()); return rectInRootFrame; }
bool RenderEmbeddedObject::getReplacementTextGeometry(int tx, int ty, FloatRect& contentRect, Path& path, FloatRect& replacementTextRect, Font& font, TextRun& run, float& textWidth) { contentRect = contentBoxRect(); contentRect.move(tx, ty); FontDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); Settings* settings = document()->settings(); ASSERT(settings); if (!settings) return false; fontDescription.setRenderingMode(settings->fontRenderingMode()); fontDescription.setComputedSize(fontDescription.specifiedSize()); font = Font(fontDescription, 0, 0); font.update(0); run = TextRun(m_replacementText.characters(), m_replacementText.length()); run.disableRoundingHacks(); textWidth = font.floatWidth(run); replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftRightTextMargin * 2, replacementTextRoundedRectHeight)); float x = (contentRect.size().width() / 2 - replacementTextRect.size().width() / 2) + contentRect.location().x(); float y = (contentRect.size().height() / 2 - replacementTextRect.size().height() / 2) + contentRect.location().y(); replacementTextRect.setLocation(FloatPoint(x, y)); path.addRoundedRect(replacementTextRect, FloatSize(replacementTextRoundedRectRadius, replacementTextRoundedRectRadius)); return true; }
void FindIndicator::draw(GraphicsContext& graphicsContext, const IntRect& dirtyRect) { for (size_t i = 0; i < m_textRects.size(); ++i) { FloatRect textRect = m_textRects[i]; textRect.move(leftBorderThickness, topBorderThickness); graphicsContext.save(); FloatRect outerPathRect = inflateRect(textRect, horizontalOutsetToCenterOfLightBorder, verticalOutsetToCenterOfLightBorder); graphicsContext.setShadow(FloatSize(shadowOffsetX, shadowOffsetY), shadowBlurRadius, shadowColor(), ColorSpaceSRGB); graphicsContext.addPath(pathWithRoundedRect(outerPathRect, cornerRadius)); graphicsContext.setFillColor(lightBorderColor(), ColorSpaceDeviceRGB); graphicsContext.fillPath(); graphicsContext.restore(); graphicsContext.save(); FloatRect innerPathRect = inflateRect(textRect, horizontalPaddingInsideLightBorder, verticalPaddingInsideLightBorder); graphicsContext.clip(pathWithRoundedRect(innerPathRect, cornerRadius)); RefPtr<Gradient> gradient = Gradient::create(FloatPoint(innerPathRect.x(), innerPathRect.y()), FloatPoint(innerPathRect.x(), innerPathRect.bottom())); gradient->addColorStop(0, gradientLightColor()); gradient->addColorStop(1, gradientDarkColor()); graphicsContext.setFillGradient(gradient); graphicsContext.fillRect(outerPathRect); graphicsContext.restore(); graphicsContext.save(); graphicsContext.translate(FloatSize(roundf(leftBorderThickness), roundf(topBorderThickness) + m_contentImage->bounds().height())); graphicsContext.scale(FloatSize(1, -1)); m_contentImage->paint(&graphicsContext, m_contentImage->bounds()); graphicsContext.restore(); } }
SkImageFilter::CropRect FilterEffect::getCropRect(const FloatSize& cropOffset) const { FloatRect rect = filter()->filterRegion(); uint32_t flags = 0; FloatRect boundaries = effectBoundaries(); boundaries.move(cropOffset); if (hasX()) { rect.setX(boundaries.x()); flags |= SkImageFilter::CropRect::kHasLeft_CropEdge; flags |= SkImageFilter::CropRect::kHasRight_CropEdge; } if (hasY()) { rect.setY(boundaries.y()); flags |= SkImageFilter::CropRect::kHasTop_CropEdge; flags |= SkImageFilter::CropRect::kHasBottom_CropEdge; } if (hasWidth()) { rect.setWidth(boundaries.width()); flags |= SkImageFilter::CropRect::kHasRight_CropEdge; } if (hasHeight()) { rect.setHeight(boundaries.height()); flags |= SkImageFilter::CropRect::kHasBottom_CropEdge; } rect.scale(filter()->absoluteTransform().a(), filter()->absoluteTransform().d()); return SkImageFilter::CropRect(rect, flags); }
static inline void expandRectWithFilters(FloatRect& rect, const WebKit::WebFilterOperations& filters) { int top, right, bottom, left; filters.getOutsets(top, right, bottom, left); rect.move(-left, -top); rect.expand(left + right, top + bottom); }
static FloatRect toNormalizedRect(const FloatRect& absoluteRect, const RenderObject* renderer, const RenderBlock* container) { ASSERT(renderer); ASSERT(container || renderer->isRenderView()); if (!container) return FloatRect(); // We want to normalize by the max layout overflow size instead of only the visible bounding box. // Quads and their enclosing bounding boxes need to be used in order to keep results transform-friendly. FloatPoint scrolledOrigin; // For overflow:scroll we need to get where the actual origin is independently of the scroll. if (container->hasOverflowClip()) scrolledOrigin = -IntPoint(container->scrolledContentOffset()); FloatRect overflowRect(scrolledOrigin, container->maxLayoutOverflow()); FloatRect containerRect = container->localToAbsoluteQuad(FloatQuad(overflowRect)).enclosingBoundingBox(); if (containerRect.isEmpty()) return FloatRect(); // Make the coordinates relative to the container enclosing bounding box. // Since we work with rects enclosing quad unions this is still transform-friendly. FloatRect normalizedRect = absoluteRect; normalizedRect.moveBy(-containerRect.location()); // Fixed positions do not make sense in this coordinate system, but need to leave consistent tickmarks. // So, use their position when the view is not scrolled, like an absolute position. if (renderer->style()->position() == FixedPosition && container->isRenderView()) normalizedRect.move(-toRenderView(container)->frameView()->scrollOffsetForFixedPosition()); normalizedRect.scale(1 / containerRect.width(), 1 / containerRect.height()); return normalizedRect; }
SkImageFilter::CropRect FilterEffect::getCropRect(const FloatSize& cropOffset) const { FloatRect rect; uint32_t flags = 0; if (!hasConnectedInput() && !filter()->filterRegion().isEmpty()) { rect = filter()->filterRegion(); flags = SkImageFilter::CropRect::kHasAll_CropEdge; } FloatRect boundaries = effectBoundaries(); boundaries.move(cropOffset); if (hasX()) { rect.setX(boundaries.x()); flags |= SkImageFilter::CropRect::kHasLeft_CropEdge; } if (hasY()) { rect.setY(boundaries.y()); flags |= SkImageFilter::CropRect::kHasTop_CropEdge; } if (hasWidth()) { rect.setWidth(boundaries.width()); flags |= SkImageFilter::CropRect::kHasWidth_CropEdge; } if (hasHeight()) { rect.setHeight(boundaries.height()); flags |= SkImageFilter::CropRect::kHasHeight_CropEdge; } rect.scale(filter()->scale()); return SkImageFilter::CropRect(rect, flags); }
FloatQuad RenderGeometryMap::mapToContainer(const FloatRect& rect, const RenderLayerModelObject* container) const { FloatRect result; if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep() && (!container || (m_mapping.size() && container == m_mapping[0].m_renderer))) { result = rect; result.move(m_accumulatedOffset); } else { TransformState transformState(TransformState::ApplyTransformDirection, rect.center(), rect); mapToContainer(transformState, container); result = transformState.lastPlanarQuad().boundingBox(); } #if !ASSERT_DISABLED if (m_mapping.size() > 0) { const RenderObject* lastRenderer = m_mapping.last().m_renderer; const RenderLayer* layer = lastRenderer->enclosingLayer(); // Bounds for invisible layers are intentionally not calculated, and are // therefore not necessarily expected to be correct here. This is ok, // because they will be recomputed if the layer becomes visible. if (!layer->subtreeIsInvisible() && lastRenderer->style()->visibility() == VISIBLE) { FloatRect rendererMappedResult = lastRenderer->localToContainerQuad(rect, container, m_mapCoordinatesFlags).boundingBox(); // Inspector creates renderers with negative width <https://bugs.webkit.org/show_bug.cgi?id=87194>. // Taking FloatQuad bounds avoids spurious assertions because of that. ASSERT(enclosingIntRect(rendererMappedResult) == enclosingIntRect(FloatQuad(result).boundingBox())); } } #endif return result; }
FloatRect RenderSVGText::relativeBBox(bool includeStroke) const { FloatRect repaintRect; for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height())); } // SVG needs to include the strokeWidth(), not the textStrokeWidth(). if (includeStroke && style()->svgStyle()->hasStroke()) { float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f); #if ENABLE(SVG_FONTS) const Font& font = style()->font(); if (font.primaryFont()->isSVGFont()) { float scale = font.unitsPerEm() > 0 ? font.size() / font.unitsPerEm() : 0.0f; if (scale != 0.0f) strokeWidth /= scale; } #endif repaintRect.inflate(strokeWidth); } repaintRect.move(xPos(), yPos()); return repaintRect; }
void FEOffset::determineAbsolutePaintRect() { FloatRect paintRect = inputEffect(0)->absolutePaintRect(); Filter* filter = this->filter(); paintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); paintRect.intersect(maxEffectRect()); setAbsolutePaintRect(enclosingIntRect(paintRect)); }
LayoutRect FilterEffectRenderer::computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect) { if (hasCustomShaderFilter()) { // When we have at least a custom shader in the chain, we need to compute the whole source image, because the shader can // reference any pixel and we cannot control that. return filterBoxRect; } // The result of this function is the area in the "filterBoxRect" that needs to be repainted, so that we fully cover the "dirtyRect". FloatRect rectForRepaint = dirtyRect; rectForRepaint.move(-filterBoxRect.location().x(), -filterBoxRect.location().y()); float inf = std::numeric_limits<float>::infinity(); FloatRect clipRect = FloatRect(FloatPoint(-inf, -inf), FloatSize(inf, inf)); rectForRepaint = lastEffect()->getSourceRect(rectForRepaint, clipRect); rectForRepaint.move(filterBoxRect.location().x(), filterBoxRect.location().y()); rectForRepaint.intersect(filterBoxRect); return LayoutRect(rectForRepaint); }
FloatSize StickyPositionViewportConstraints::computeStickyOffset(const FloatRect& viewportRect) const { FloatRect boxRect = m_absoluteStickyBoxRect; if (hasAnchorEdge(AnchorEdgeRight)) { float rightLimit = viewportRect.maxX() - m_rightOffset; float rightDelta = std::min<float>(0, rightLimit - m_absoluteStickyBoxRect.maxX()); float availableSpace = std::min<float>(0, m_absoluteContainingBlockRect.x() - m_absoluteStickyBoxRect.x()); if (rightDelta < availableSpace) rightDelta = availableSpace; boxRect.move(rightDelta, 0); } if (hasAnchorEdge(AnchorEdgeLeft)) { float leftLimit = viewportRect.x() + m_leftOffset; float leftDelta = std::max<float>(0, leftLimit - m_absoluteStickyBoxRect.x()); float availableSpace = std::max<float>(0, m_absoluteContainingBlockRect.maxX() - m_absoluteStickyBoxRect.maxX()); if (leftDelta > availableSpace) leftDelta = availableSpace; boxRect.move(leftDelta, 0); } if (hasAnchorEdge(AnchorEdgeBottom)) { float bottomLimit = viewportRect.maxY() - m_bottomOffset; float bottomDelta = std::min<float>(0, bottomLimit - m_absoluteStickyBoxRect.maxY()); float availableSpace = std::min<float>(0, m_absoluteContainingBlockRect.y() - m_absoluteStickyBoxRect.y()); if (bottomDelta < availableSpace) bottomDelta = availableSpace; boxRect.move(0, bottomDelta); } if (hasAnchorEdge(AnchorEdgeTop)) { float topLimit = viewportRect.y() + m_topOffset; float topDelta = std::max<float>(0, topLimit - m_absoluteStickyBoxRect.y()); float availableSpace = std::max<float>(0, m_absoluteContainingBlockRect.maxY() - m_absoluteStickyBoxRect.maxY()); if (topDelta > availableSpace) topDelta = availableSpace; boxRect.move(0, topDelta); } return boxRect.location() - m_absoluteStickyBoxRect.location(); }
void TextureMapperLayer::computeOverlapRegions(Region& overlapRegion, Region& nonOverlapRegion, ResolveSelfOverlapMode mode) { if (!m_state.visible || !m_state.contentsVisible) return; FloatRect boundingRect; if (m_backingStore || m_state.masksToBounds || m_state.maskLayer || hasFilters()) boundingRect = layerRect(); else if (m_contentsLayer || m_state.solidColor.alpha()) boundingRect = m_state.contentsRect; if (m_currentFilters.hasOutsets()) { FilterOutsets outsets = m_currentFilters.outsets(); IntRect unfilteredTargetRect(boundingRect); boundingRect.move(std::max(0, -outsets.left()), std::max(0, -outsets.top())); boundingRect.expand(outsets.left() + outsets.right(), outsets.top() + outsets.bottom()); boundingRect.unite(unfilteredTargetRect); } TransformationMatrix replicaMatrix; if (m_state.replicaLayer) { replicaMatrix = replicaTransform(); boundingRect.unite(replicaMatrix.mapRect(boundingRect)); } boundingRect = m_currentTransform.combined().mapRect(boundingRect); // Count all masks and filters as overlap layers. if (hasFilters() || m_state.maskLayer || (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)) { Region newOverlapRegion(enclosingIntRect(boundingRect)); nonOverlapRegion.subtract(newOverlapRegion); overlapRegion.unite(newOverlapRegion); return; } Region newOverlapRegion; Region newNonOverlapRegion(enclosingIntRect(boundingRect)); if (!m_state.masksToBounds) { for (auto* child : m_children) child->computeOverlapRegions(newOverlapRegion, newNonOverlapRegion, ResolveSelfOverlapIfNeeded); } if (m_state.replicaLayer) { newOverlapRegion.unite(replicaMatrix.mapRect(newOverlapRegion.bounds())); Region replicaRegion(replicaMatrix.mapRect(newNonOverlapRegion.bounds())); resolveOverlaps(replicaRegion, newOverlapRegion, newNonOverlapRegion); } if ((mode != ResolveSelfOverlapAlways) && shouldBlend()) { newNonOverlapRegion.unite(newOverlapRegion); newOverlapRegion = Region(); } overlapRegion.unite(newOverlapRegion); resolveOverlaps(newNonOverlapRegion, overlapRegion, nonOverlapRegion); }
void BeginFilterDisplayItem::replay(GraphicsContext* context) { context->save(); FloatRect boundaries = mapImageFilterRect(m_imageFilter.get(), m_bounds); context->translate(m_bounds.x().toFloat(), m_bounds.y().toFloat()); boundaries.move(-m_bounds.x().toFloat(), -m_bounds.y().toFloat()); context->beginLayer(1, CompositeSourceOver, &boundaries, ColorFilterNone, m_imageFilter.get()); context->translate(-m_bounds.x().toFloat(), -m_bounds.y().toFloat()); }
FloatRect FEDropShadow::mapRect(const FloatRect& rect, bool forward) { FloatRect result = rect; Filter* filter = this->filter(); ASSERT(filter); FloatRect offsetRect = rect; if (forward) offsetRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); else offsetRect.move(-filter->applyHorizontalScale(m_dx), -filter->applyVerticalScale(m_dy)); result.unite(offsetRect); IntSize kernelSize = FEGaussianBlur::calculateKernelSize(filter, FloatPoint(m_stdX, m_stdY)); // We take the half kernel size and multiply it with three, because we run box blur three times. result.inflateX(3 * kernelSize.width() * 0.5f); result.inflateY(3 * kernelSize.height() * 0.5f); return result; }
void FEOffset::determineAbsolutePaintRect() { FloatRect paintRect = inputEffect(0)->absolutePaintRect(); Filter& filter = this->filter(); paintRect.move(filter.applyHorizontalScale(m_dx), filter.applyVerticalScale(m_dy)); if (clipsToBounds()) paintRect.intersect(maxEffectRect()); else paintRect.unite(maxEffectRect()); setAbsolutePaintRect(enclosingIntRect(paintRect)); }
void ShadowList::adjustRectForShadow(FloatRect& rect) const { float shadowLeft = 0; float shadowRight = 0; float shadowTop = 0; float shadowBottom = 0; calculateShadowExtent(this, shadowLeft, shadowRight, shadowTop, shadowBottom); rect.move(shadowLeft, shadowTop); rect.setWidth(rect.width() - shadowLeft + shadowRight); rect.setHeight(rect.height() - shadowTop + shadowBottom); }
static FloatRect outsetIndicatorRectIncludingShadow(const FloatRect rect) { #if ENABLE(LEGACY_FIND_INDICATOR_STYLE) FloatRect outsetRect = rect; outsetRect.move(-leftBorderThickness, -topBorderThickness); outsetRect.expand(leftBorderThickness + rightBorderThickness, topBorderThickness + bottomBorderThickness); return outsetRect; #else return inflateRect(rect, flatShadowBlurRadius + flatStyleHorizontalBorder, flatShadowBlurRadius + flatStyleVerticalBorder); #endif }
FloatRect RenderSVGText::objectBoundingBox() const { FloatRect boundingBox; for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) { for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height())); } boundingBox.move(x(), y()); return boundingBox; }
void ShadowData::adjustRectForShadow(FloatRect& rect, int additionalOutlineSize) const { int shadowLeft = 0; int shadowRight = 0; int shadowTop = 0; int shadowBottom = 0; calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom); rect.move(shadowLeft, shadowTop); rect.setWidth(rect.width() - shadowLeft + shadowRight); rect.setHeight(rect.height() - shadowTop + shadowBottom); }
void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const { FloatRect intersectRect = intersection(m_bitmapRect, *srcRect); FloatRect newSrcRect = intersectRect; newSrcRect.move(m_bitmapOffset - m_bitmapRect.location()); FloatRect newDstRect(FloatPoint(intersectRect.location() - srcRect->location()), m_bitmapRect.size()); newDstRect.scale(dstRect->width() / srcRect->width() * intersectRect.width() / m_bitmapRect.width(), dstRect->height() / srcRect->height() * intersectRect.height() / m_bitmapRect.height()); newDstRect.moveBy(dstRect->location()); *srcRect = newSrcRect; *dstRect = newDstRect; }
void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, int tx, int ty) { if (!m_replacementText) return; if (paintInfo.phase == PaintPhaseSelection) return; GraphicsContext* context = paintInfo.context; if (context->paintingDisabled()) return; FloatRect pluginRect = contentBoxRect(); pluginRect.move(tx, ty); FontDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); Settings* settings = document()->settings(); ASSERT(settings); if (!settings) return; fontDescription.setRenderingMode(settings->fontRenderingMode()); fontDescription.setComputedSize(fontDescription.specifiedSize()); Font font(fontDescription, 0, 0); font.update(0); TextRun run(m_replacementText.characters(), m_replacementText.length()); run.disableRoundingHacks(); float textWidth = font.floatWidth(run); FloatRect replacementTextRect; replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftRightTextMargin * 2, replacementTextRoundedRectHeight)); replacementTextRect.setLocation(FloatPoint((pluginRect.size().width() / 2 - replacementTextRect.size().width() / 2) + pluginRect.location().x(), (pluginRect.size().height() / 2 - replacementTextRect.size().height() / 2) + pluginRect.location().y())); Path path = Path::createRoundedRectangle(replacementTextRect, FloatSize(replacementTextRoundedRectRadius, replacementTextRoundedRectRadius)); context->save(); context->clip(pluginRect); context->beginPath(); context->addPath(path); context->setAlpha(replacementTextRoundedRectOpacity); context->setFillColor(Color::white, style()->colorSpace()); context->fillPath(); FloatPoint labelPoint(roundf(replacementTextRect.location().x() + (replacementTextRect.size().width() - textWidth) / 2), roundf(replacementTextRect.location().y()+ (replacementTextRect.size().height() - font.height()) / 2 + font.ascent())); context->setAlpha(replacementTextTextOpacity); context->setFillColor(Color::black, style()->colorSpace()); context->drawBidiText(font, run, labelPoint); context->restore(); }
void FEImage::platformApplySoftware() { RenderObject* renderer = referencedRenderer(); if (!m_image && !renderer) return; ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; SVGFilter* svgFilter = static_cast<SVGFilter*>(filter()); FloatRect destRect = svgFilter->absoluteTransform().mapRect(filterPrimitiveSubregion()); FloatRect srcRect; if (renderer) srcRect = svgFilter->absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates()); else { srcRect = FloatRect(FloatPoint(), m_image->size()); m_preserveAspectRatio.transformRect(destRect, srcRect); } IntPoint paintLocation = absolutePaintRect().location(); destRect.move(-paintLocation.x(), -paintLocation.y()); // FEImage results are always in ColorSpaceDeviceRGB setResultColorSpace(ColorSpaceDeviceRGB); if (renderer) { const AffineTransform& absoluteTransform = svgFilter->absoluteTransform(); resultImage->context()->concatCTM(absoluteTransform); SVGElement* contextNode = static_cast<SVGElement*>(renderer->node()); if (contextNode->isStyled() && static_cast<SVGStyledElement*>(contextNode)->hasRelativeLengths()) { SVGLengthContext lengthContext(contextNode); float width = 0; float height = 0; // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport. // Build up a transformation that maps from the viewport space to the filter primitive subregion. if (lengthContext.determineViewport(width, height)) resultImage->context()->concatCTM(makeMapBetweenRects(FloatRect(0, 0, width, height), destRect)); } AffineTransform contentTransformation; SVGRenderingContext::renderSubtreeToImageBuffer(resultImage, renderer, contentTransformation); return; } resultImage->context()->drawImage(m_image.get(), ColorSpaceDeviceRGB, destRect, srcRect); }
void FEOffset::applySoftware() { FilterEffect* in = inputEffect(0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; setIsAlphaImage(in->isAlphaImage()); FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); Filter* filter = this->filter(); drawingRegion.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); resultImage->context()->drawImageBuffer(in->asImageBuffer(), drawingRegion); }
FloatRect RenderSVGText::objectBoundingBox() const { FloatRect boundingBox; for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height())); } boundingBox.move(x(), y()); return boundingBox; }