void CompositingInputsUpdater::updateRecursive(DeprecatedPaintLayer* layer, UpdateType updateType, AncestorInfo info) { if (!layer->childNeedsCompositingInputsUpdate() && updateType != ForceUpdate) return; m_geometryMap.pushMappingsToAncestor(layer, layer->parent()); if (layer->hasCompositedDeprecatedPaintLayerMapping()) info.enclosingCompositedLayer = layer; if (layer->needsCompositingInputsUpdate()) { if (info.enclosingCompositedLayer) info.enclosingCompositedLayer->compositedDeprecatedPaintLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree); updateType = ForceUpdate; } if (updateType == ForceUpdate) { DeprecatedPaintLayer::AncestorDependentCompositingInputs properties; if (!layer->isRootLayer()) { properties.clippedAbsoluteBoundingBox = enclosingIntRect(m_geometryMap.absoluteRect(layer->boundingBoxForCompositingOverlapTest())); // FIXME: Setting the absBounds to 1x1 instead of 0x0 makes very little sense, // but removing this code will make JSGameBench sad. // See https://codereview.chromium.org/13912020/ if (properties.clippedAbsoluteBoundingBox.isEmpty()) properties.clippedAbsoluteBoundingBox.setSize(IntSize(1, 1)); IntRect clipRect = pixelSnappedIntRect(layer->clipper().backgroundClipRect(ClipRectsContext(m_rootLayer, AbsoluteClipRects)).rect()); properties.clippedAbsoluteBoundingBox.intersect(clipRect); const DeprecatedPaintLayer* parent = layer->parent(); properties.opacityAncestor = parent->isTransparent() ? parent : parent->opacityAncestor(); properties.transformAncestor = parent->hasTransformRelatedProperty() ? parent : parent->transformAncestor(); properties.filterAncestor = parent->hasFilter() ? parent : parent->filterAncestor(); bool layerIsFixedPosition = layer->layoutObject()->style()->position() == FixedPosition; properties.nearestFixedPositionLayer = layerIsFixedPosition ? layer : parent->nearestFixedPositionLayer(); if (info.hasAncestorWithClipOrOverflowClip) { const DeprecatedPaintLayer* parentLayerOnClippingContainerChain = findParentLayerOnClippingContainerChain(layer); const bool parentHasClipOrOverflowClip = parentLayerOnClippingContainerChain->layoutObject()->hasClipOrOverflowClip(); properties.clippingContainer = parentHasClipOrOverflowClip ? parentLayerOnClippingContainerChain->layoutObject() : parentLayerOnClippingContainerChain->clippingContainer(); } if (info.lastScrollingAncestor) { const LayoutObject* containingBlock = layer->layoutObject()->containingBlock(); const DeprecatedPaintLayer* parentLayerOnContainingBlockChain = findParentLayerOnContainingBlockChain(containingBlock); properties.ancestorScrollingLayer = parentLayerOnContainingBlockChain->ancestorScrollingLayer(); if (parentLayerOnContainingBlockChain->scrollsOverflow()) properties.ancestorScrollingLayer = parentLayerOnContainingBlockChain; if (layer->layoutObject()->isOutOfFlowPositioned() && !layer->subtreeIsInvisible()) { const DeprecatedPaintLayer* clippingLayer = properties.clippingContainer ? properties.clippingContainer->enclosingLayer() : layer->compositor()->rootLayer(); if (hasClippedStackingAncestor(layer, clippingLayer)) properties.clipParent = clippingLayer; } if (layer->stackingNode()->isTreatedAsStackingContextForPainting() && properties.ancestorScrollingLayer && !info.ancestorStackingContext->layoutObject()->isDescendantOf(properties.ancestorScrollingLayer->layoutObject())) properties.scrollParent = properties.ancestorScrollingLayer; } } properties.hasAncestorWithClipPath = info.hasAncestorWithClipPath; layer->updateAncestorDependentCompositingInputs(properties); } if (layer->stackingNode()->isStackingContext()) info.ancestorStackingContext = layer; if (layer->scrollsOverflow()) info.lastScrollingAncestor = layer; if (layer->layoutObject()->hasClipOrOverflowClip()) info.hasAncestorWithClipOrOverflowClip = true; if (layer->layoutObject()->hasClipPath()) info.hasAncestorWithClipPath = true; DeprecatedPaintLayer::DescendantDependentCompositingInputs descendantProperties; for (DeprecatedPaintLayer* child = layer->firstChild(); child; child = child->nextSibling()) { updateRecursive(child, updateType, info); descendantProperties.hasDescendantWithClipPath |= child->hasDescendantWithClipPath() || child->layoutObject()->hasClipPath(); descendantProperties.hasNonIsolatedDescendantWithBlendMode |= (!child->stackingNode()->isStackingContext() && child->hasNonIsolatedDescendantWithBlendMode()) || child->layoutObject()->style()->hasBlendMode(); } layer->updateDescendantDependentCompositingInputs(descendantProperties); layer->didUpdateCompositingInputs(); m_geometryMap.popMappingsToAncestor(layer->parent()); }
bool TextFinder::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, bool* activeNow) { if (!options.findNext) unmarkAllTextMatches(); else setMarkerActive(m_activeMatch.get(), false); if (m_activeMatch && &m_activeMatch->ownerDocument() != ownerFrame().frame()->document()) m_activeMatch = nullptr; // If the user has selected something since the last Find operation we want // to start from there. Otherwise, we start searching from where the last Find // operation left off (either a Find or a FindNext operation). VisibleSelection selection(ownerFrame().frame()->selection().selection()); bool activeSelection = !selection.isNone(); if (activeSelection) { m_activeMatch = firstRangeOf(selection); ownerFrame().frame()->selection().clear(); } DCHECK(ownerFrame().frame()); DCHECK(ownerFrame().frame()->view()); const FindOptions findOptions = (options.forward ? 0 : Backwards) | (options.matchCase ? 0 : CaseInsensitive) | (wrapWithinFrame ? WrapAround : 0) | (options.wordStart ? AtWordStarts : 0) | (options.medialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0) | (options.findNext ? 0 : StartInSelection); m_activeMatch = ownerFrame().frame()->editor().findStringAndScrollToVisible( searchText, m_activeMatch.get(), findOptions); if (!m_activeMatch) { // If we're finding next the next active match might not be in the current // frame. In this case we don't want to clear the matches cache. if (!options.findNext) clearFindMatchesCache(); ownerFrame().frameView()->invalidatePaintForTickmarks(); return false; } // If the user is browsing a page with autosizing, adjust the zoom to the // column where the next hit has been found. Doing this when autosizing is // not set will result in a zoom reset on small devices. if (ownerFrame() .frame() ->document() ->textAutosizer() ->pageNeedsAutosizing()) { ownerFrame().viewImpl()->zoomToFindInPageRect( ownerFrame().frameView()->contentsToRootFrame( enclosingIntRect(LayoutObject::absoluteBoundingBoxRectForRange( m_activeMatch.get())))); } bool wasActiveFrame = m_currentActiveMatchFrame; m_currentActiveMatchFrame = true; bool isActive = setMarkerActive(m_activeMatch.get(), true); if (activeNow) *activeNow = isActive; // Make sure no node is focused. See http://crbug.com/38700. ownerFrame().frame()->document()->clearFocusedElement(); // Set this frame as focused. ownerFrame().viewImpl()->setFocusedFrame(&ownerFrame()); if (!options.findNext || activeSelection || !isActive) { // This is either an initial Find operation, a Find-next from a new // start point due to a selection, or new matches were found during // Find-next due to DOM alteration (that couldn't be set as active), so // we set the flag to ask the scoping effort to find the active rect for // us and report it back to the UI. m_locatingActiveRect = true; } else { if (!wasActiveFrame) { if (options.forward) m_activeMatchIndex = 0; else m_activeMatchIndex = m_lastMatchCount - 1; } else { if (options.forward) ++m_activeMatchIndex; else --m_activeMatchIndex; if (m_activeMatchIndex + 1 > m_lastMatchCount) m_activeMatchIndex = 0; else if (m_activeMatchIndex < 0) m_activeMatchIndex = m_lastMatchCount - 1; } WebRect selectionRect = ownerFrame().frameView()->contentsToRootFrame( m_activeMatch->boundingBox()); reportFindInPageSelection(selectionRect, m_activeMatchIndex + 1, identifier); } return true; }
static TextStream& writePositionAndStyle(TextStream& ts, const RenderObject& object) { ts << " " << enclosingIntRect(const_cast<RenderObject&>(object).absoluteClippedOverflowRect()); writeStyle(ts, object); return ts; }
IntRect VisualViewport::rootFrameToViewport(const IntRect& rectInRootFrame) const { // FIXME: How to snap to pixels? return enclosingIntRect(rootFrameToViewport(FloatRect(rectInRootFrame))); }
IntRect RenderSVGInlineText::linesBoundingBox() const { return enclosingIntRect(floatLinesBoundingBox()); }
void ImageBufferDataPrivateAccelerated::clip(GraphicsContext* context, const FloatRect& floatRect) const { QPixmap alphaMask = QPixmap::fromImage(toQImage()); IntRect rect = enclosingIntRect(floatRect); context->pushTransparencyLayerInternal(rect, 1.0, alphaMask); }
IntRect VisualViewport::visibleContentRect(IncludeScrollbarsInRect scrollbarInclusion) const { return enclosingIntRect(visibleContentRectDouble(scrollbarInclusion)); }
void BufferedImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp) { IntRect intDstRect = enclosingIntRect(dstRect); IntRect intSrcRect(srcRect); m_data->m_bitmap->draw(ctxt, intDstRect, intSrcRect, styleColorSpace, compositeOp); }
IntRect TiledDrawingAreaProxy::webViewVisibleRect() { return enclosingIntRect(FloatRect(m_webView->visibleRect())); }
bool SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObject* object) { m_ownerElement->buildFilter(object->objectBoundingBox()); const SVGRenderBase* renderer = object->toSVGRenderBase(); if (!renderer) return false; FloatRect paintRect = renderer->strokeBoundingBox(); paintRect.unite(renderer->markerBoundingBox()); if (shouldProcessFilter(this, m_filterBBox)) return false; // clip sourceImage to filterRegion FloatRect clippedSourceRect = paintRect; clippedSourceRect.intersect(m_filterBBox); // scale filter size to filterRes FloatRect tempSourceRect = clippedSourceRect; if (m_filterRes) { m_scaleX = m_filterResSize.width() / m_filterBBox.width(); m_scaleY = m_filterResSize.height() / m_filterBBox.height(); } // scale to big sourceImage size to kMaxFilterSize tempSourceRect.scale(m_scaleX, m_scaleY); fitsInMaximumImageSize(tempSourceRect.size()); // prepare Filters m_filter = SVGFilter::create(paintRect, m_filterBBox, m_effectBBoxMode); m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY)); FilterEffect* lastEffect = m_filterBuilder->lastEffect(); if (lastEffect) { lastEffect->calculateEffectRect(m_filter.get()); // at least one FilterEffect has a too big image size, // recalculate the effect sizes with new scale factors if (!fitsInMaximumImageSize(m_filter->maxImageSize())) { m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY)); lastEffect->calculateEffectRect(m_filter.get()); } } else return false; clippedSourceRect.scale(m_scaleX, m_scaleY); // Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic. // The size of the SourceGraphic is clipped to the size of the filterRegion. IntRect bufferRect = enclosingIntRect(clippedSourceRect); OwnPtr<ImageBuffer> sourceGraphic(ImageBuffer::create(bufferRect.size(), LinearRGB)); if (!sourceGraphic.get()) return false; GraphicsContext* sourceGraphicContext = sourceGraphic->context(); sourceGraphicContext->translate(-clippedSourceRect.x(), -clippedSourceRect.y()); sourceGraphicContext->scale(FloatSize(m_scaleX, m_scaleY)); sourceGraphicContext->clearRect(FloatRect(FloatPoint(), paintRect.size())); m_sourceGraphicBuffer.set(sourceGraphic.release()); m_savedContext = context; context = sourceGraphicContext; return true; }
void NativeImageSkia::drawPattern( GraphicsContext* context, const FloatRect& floatSrcRect, const FloatSize& scale, const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect, WebBlendMode blendMode, const IntSize& repeatSpacing) const { FloatRect normSrcRect = floatSrcRect; normSrcRect.intersect(FloatRect(0, 0, bitmap().width(), bitmap().height())); if (destRect.isEmpty() || normSrcRect.isEmpty()) return; // nothing to draw SkMatrix totalMatrix = context->getTotalMatrix(); AffineTransform ctm = context->getCTM(); SkScalar ctmScaleX = ctm.xScale(); SkScalar ctmScaleY = ctm.yScale(); totalMatrix.preScale(scale.width(), scale.height()); // Figure out what size the bitmap will be in the destination. The // destination rect is the bounds of the pattern, we need to use the // matrix to see how big it will be. SkRect destRectTarget; totalMatrix.mapRect(&destRectTarget, normSrcRect); float destBitmapWidth = SkScalarToFloat(destRectTarget.width()); float destBitmapHeight = SkScalarToFloat(destRectTarget.height()); bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap()); // Compute the resampling mode. InterpolationQuality resampling; if (context->isAccelerated()) resampling = InterpolationLow; else if (isLazyDecoded) resampling = InterpolationHigh; else resampling = computeInterpolationQuality(totalMatrix, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight, isDataComplete()); resampling = limitInterpolationQuality(context, resampling); SkMatrix localMatrix; // We also need to translate it such that the origin of the pattern is the // origin of the destination rect, which is what WebKit expects. Skia uses // the coordinate system origin as the base for the pattern. If WebKit wants // a shifted image, it will shift it from there using the localMatrix. const float adjustedX = phase.x() + normSrcRect.x() * scale.width(); const float adjustedY = phase.y() + normSrcRect.y() * scale.height(); localMatrix.setTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjustedY)); RefPtr<SkShader> shader; SkFilterQuality filterLevel = static_cast<SkFilterQuality>(resampling); // Bicubic filter is only applied to defer-decoded images, see // NativeImageSkia::draw for details. if (resampling == InterpolationHigh && !isLazyDecoded) { // Do nice resampling. filterLevel = kNone_SkFilterQuality; float scaleX = destBitmapWidth / normSrcRect.width(); float scaleY = destBitmapHeight / normSrcRect.height(); SkRect scaledSrcRect; // Since we are resizing the bitmap, we need to remove the scale // applied to the pixels in the bitmap shader. This means we need // CTM * localMatrix to have identity scale. Since we // can't modify CTM (or the rectangle will be drawn in the wrong // place), we must set localMatrix's scale to the inverse of // CTM scale. localMatrix.preScale(ctmScaleX ? 1 / ctmScaleX : 1, ctmScaleY ? 1 / ctmScaleY : 1); // The image fragment generated here is not exactly what is // requested. The scale factor used is approximated and image // fragment is slightly larger to align to integer // boundaries. SkBitmap resampled = extractScaledImageFragment(normSrcRect, scaleX, scaleY, &scaledSrcRect); if (repeatSpacing.isZero()) { shader = adoptRef(SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix)); } else { shader = adoptRef(SkShader::CreateBitmapShader( createBitmapWithSpace(resampled, repeatSpacing.width() * ctmScaleX, repeatSpacing.height() * ctmScaleY), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix)); } } else { // Because no resizing occurred, the shader transform should be // set to the pattern's transform, which just includes scale. localMatrix.preScale(scale.width(), scale.height()); // No need to resample before drawing. SkBitmap srcSubset; bitmap().extractSubset(&srcSubset, enclosingIntRect(normSrcRect)); if (repeatSpacing.isZero()) { shader = adoptRef(SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix)); } else { shader = adoptRef(SkShader::CreateBitmapShader( createBitmapWithSpace(srcSubset, repeatSpacing.width() * ctmScaleX, repeatSpacing.height() * ctmScaleY), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix)); } } SkPaint paint; paint.setShader(shader.get()); paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp, blendMode)); paint.setColorFilter(context->colorFilter()); paint.setFilterQuality(filterLevel); context->drawRect(destRect, paint); }
IntRect EllipsisBox::selectionRect() { RenderStyle* style = renderer().style(isFirstLineStyle()); const Font& font = style->font(); return enclosingIntRect(font.selectionRectForText(constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(logicalLeft(), logicalTop() + root().selectionTopAdjustedForPrecedingBlock()), root().selectionHeightAdjustedForPrecedingBlock())); }
bool TextFinder::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, WebRect* selectionRect) { if (!m_ownerFrame.frame() || !m_ownerFrame.frame()->page()) return false; WebLocalFrameImpl* mainFrameImpl = m_ownerFrame.viewImpl()->mainFrameImpl(); if (!options.findNext) m_ownerFrame.frame()->page()->unmarkAllTextMatches(); else setMarkerActive(m_activeMatch.get(), false); if (m_activeMatch && &m_activeMatch->ownerDocument() != m_ownerFrame.frame()->document()) m_activeMatch = nullptr; // If the user has selected something since the last Find operation we want // to start from there. Otherwise, we start searching from where the last Find // operation left off (either a Find or a FindNext operation). VisibleSelection selection(m_ownerFrame.frame()->selection().selection()); bool activeSelection = !selection.isNone(); if (activeSelection) { m_activeMatch = selection.firstRange().get(); m_ownerFrame.frame()->selection().clear(); } ASSERT(m_ownerFrame.frame() && m_ownerFrame.frame()->view()); const FindOptions findOptions = (options.forward ? 0 : Backwards) | (options.matchCase ? 0 : CaseInsensitive) | (wrapWithinFrame ? WrapAround : 0) | (options.wordStart ? AtWordStarts : 0) | (options.medialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0) | (options.findNext ? 0 : StartInSelection); m_activeMatch = m_ownerFrame.frame()->editor().findStringAndScrollToVisible(searchText, m_activeMatch.get(), findOptions); if (!m_activeMatch) { // If we're finding next the next active match might not be in the current frame. // In this case we don't want to clear the matches cache. if (!options.findNext) clearFindMatchesCache(); m_ownerFrame.invalidateAll(); return false; } #if OS(ANDROID) m_ownerFrame.viewImpl()->zoomToFindInPageRect(m_ownerFrame.frameView()->contentsToWindow(enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get())))); #endif setMarkerActive(m_activeMatch.get(), true); WebLocalFrameImpl* oldActiveFrame = mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame; mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame = &m_ownerFrame; // Make sure no node is focused. See http://crbug.com/38700. m_ownerFrame.frame()->document()->setFocusedElement(nullptr); if (!options.findNext || activeSelection) { // This is either a Find operation or a Find-next from a new start point // due to a selection, so we set the flag to ask the scoping effort // to find the active rect for us and report it back to the UI. m_locatingActiveRect = true; } else { if (oldActiveFrame != &m_ownerFrame) { if (options.forward) m_activeMatchIndexInCurrentFrame = 0; else m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1; } else { if (options.forward) ++m_activeMatchIndexInCurrentFrame; else --m_activeMatchIndexInCurrentFrame; if (m_activeMatchIndexInCurrentFrame + 1 > m_lastMatchCount) m_activeMatchIndexInCurrentFrame = 0; if (m_activeMatchIndexInCurrentFrame == -1) m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1; } if (selectionRect) { *selectionRect = m_ownerFrame.frameView()->contentsToWindow(m_activeMatch->boundingBox()); reportFindInPageSelection(*selectionRect, m_activeMatchIndexInCurrentFrame + 1, identifier); } } return true; }
FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect* effect, SVGFilter* filter) { FloatRect uniteRect; FloatRect subregionBoundingBox = effect->effectBoundaries(); FloatRect subregion = subregionBoundingBox; if (effect->filterEffectType() != FilterEffectTypeTile) { // FETurbulence, FEImage and FEFlood don't have input effects, take the filter region as unite rect. if (unsigned numberOfInputEffects = effect->inputEffects().size()) { for (unsigned i = 0; i < numberOfInputEffects; ++i) uniteRect.unite(determineFilterPrimitiveSubregion(effect->inputEffect(i), filter)); } else uniteRect = filter->filterRegionInUserSpace(); } else { determineFilterPrimitiveSubregion(effect->inputEffect(0), filter); uniteRect = filter->filterRegionInUserSpace(); } if (filter->effectBoundingBoxMode()) { subregion = uniteRect; // Avoid the calling of a virtual method several times. FloatRect targetBoundingBox = filter->targetBoundingBox(); if (effect->hasX()) subregion.setX(targetBoundingBox.x() + subregionBoundingBox.x() * targetBoundingBox.width()); if (effect->hasY()) subregion.setY(targetBoundingBox.y() + subregionBoundingBox.y() * targetBoundingBox.height()); if (effect->hasWidth()) subregion.setWidth(subregionBoundingBox.width() * targetBoundingBox.width()); if (effect->hasHeight()) subregion.setHeight(subregionBoundingBox.height() * targetBoundingBox.height()); } else { if (!effect->hasX()) subregion.setX(uniteRect.x()); if (!effect->hasY()) subregion.setY(uniteRect.y()); if (!effect->hasWidth()) subregion.setWidth(uniteRect.width()); if (!effect->hasHeight()) subregion.setHeight(uniteRect.height()); } effect->setFilterPrimitiveSubregion(subregion); FloatRect absoluteSubregion = filter->mapLocalRectToAbsoluteRect(subregion); FloatSize filterResolution = filter->filterResolution(); absoluteSubregion.scale(filterResolution.width(), filterResolution.height()); // FEImage needs the unclipped subregion in absolute coordinates to determine the correct // destination rect in combination with preserveAspectRatio. if (effect->filterEffectType() == FilterEffectTypeImage) reinterpret_cast<FEImage*>(effect)->setAbsoluteSubregion(absoluteSubregion); // Clip every filter effect to the filter region. FloatRect absoluteScaledFilterRegion = filter->filterRegion(); absoluteScaledFilterRegion.scale(filterResolution.width(), filterResolution.height()); absoluteSubregion.intersect(absoluteScaledFilterRegion); effect->setMaxEffectRect(enclosingIntRect(absoluteSubregion)); return subregion; }
IntRect AffineTransform::mapRect(const IntRect &rect) const { return enclosingIntRect(mapRect(FloatRect(rect))); }
bool CullRect::intersectsCullRect(const LayoutRect& rectArg) const { return m_rect.intersects(enclosingIntRect(rectArg)); }
void Image::drawPattern(GraphicsContext* context, const FloatRect& floatSrcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, const FloatRect& destRect) { FloatRect normSrcRect = normalizeRect(floatSrcRect); if (destRect.isEmpty() || normSrcRect.isEmpty()) return; // nothing to draw NativeImageSkia* bitmap = nativeImageForCurrentFrame(); if (!bitmap) return; // This is a very inexpensive operation. It will generate a new bitmap but // it will internally reference the old bitmap's pixels, adjusting the row // stride so the extra pixels appear as padding to the subsetted bitmap. SkBitmap srcSubset; SkIRect srcRect = enclosingIntRect(normSrcRect); bitmap->extractSubset(&srcSubset, srcRect); SkBitmap resampled; SkShader* shader; // Figure out what size the bitmap will be in the destination. The // destination rect is the bounds of the pattern, we need to use the // matrix to see how bit it will be. float destBitmapWidth, destBitmapHeight; TransformDimensions(patternTransform, srcRect.width(), srcRect.height(), &destBitmapWidth, &destBitmapHeight); // Compute the resampling mode. ResamplingMode resampling; if (context->platformContext()->isPrinting()) resampling = RESAMPLE_LINEAR; else { resampling = computeResamplingMode(*bitmap, srcRect.width(), srcRect.height(), destBitmapWidth, destBitmapHeight); } // Load the transform WebKit requested. SkMatrix matrix(patternTransform); if (resampling == RESAMPLE_AWESOME) { // Do nice resampling. SkBitmap resampled = skia::ImageOperations::Resize(srcSubset, skia::ImageOperations::RESIZE_LANCZOS3, static_cast<int>(destBitmapWidth), static_cast<int>(destBitmapHeight)); shader = SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); // Since we just resized the bitmap, we need to undo the scale set in // the image transform. matrix.setScaleX(SkIntToScalar(1)); matrix.setScaleY(SkIntToScalar(1)); } else { // No need to do nice resampling. shader = SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); } // We also need to translate it such that the origin of the pattern is the // origin of the destination rect, which is what WebKit expects. Skia uses // the coordinate system origin as the base for the patter. If WebKit wants // a shifted image, it will shift it from there using the patternTransform. float adjustedX = phase.x() + normSrcRect.x() * narrowPrecisionToFloat(patternTransform.a()); float adjustedY = phase.y() + normSrcRect.y() * narrowPrecisionToFloat(patternTransform.d()); matrix.postTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjustedY)); shader->setLocalMatrix(matrix); SkPaint paint; paint.setShader(shader)->unref(); paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp)); paint.setFilterBitmap(resampling == RESAMPLE_LINEAR); context->platformContext()->paintSkPaint(destRect, paint); }
void CompositingCoordinator::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& graphicsContext, GraphicsLayerPaintingPhase, const FloatRect& clipRect) { m_client->paintLayerContents(graphicsLayer, graphicsContext, enclosingIntRect(clipRect)); }
void SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter) { #if !ENABLE(FILTERS) UNUSED_PARAM(filter); UNUSED_PARAM(rootFilter); #endif ASSERT(object); SVGElement* svgElement = static_cast<SVGElement*>(object->node()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); const RenderStyle* style = object->style(); ASSERT(style); const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); // Setup transparency layers before setting up filters! float opacity = style->opacity(); if (opacity < 1.0f) { paintInfo.context->clip(enclosingIntRect(boundingBox)); paintInfo.context->beginTransparencyLayer(opacity); } #if ENABLE(FILTERS) AtomicString filterId(svgStyle->filter()); #endif AtomicString clipperId(svgStyle->clipPath()); AtomicString maskerId(svgStyle->maskElement()); Document* document = object->document(); #if ENABLE(FILTERS) SVGResourceFilter* newFilter = getFilterById(document, filterId); if (newFilter == rootFilter) { // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>. // The filter is NOT meant to be applied twice in that case! filter = 0; filterId = String(); } else filter = newFilter; #endif SVGResourceClipper* clipper = getClipperById(document, clipperId); SVGResourceMasker* masker = getMaskerById(document, maskerId); #if ENABLE(FILTERS) if (filter) { filter->addClient(styledElement); filter->prepareFilter(paintInfo.context, object); } else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); #endif if (clipper) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, boundingBox); } else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); if (masker) { masker->addClient(styledElement); masker->applyMask(paintInfo.context, boundingBox); } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); }
// This method is called from inside paintOutline() since we call paintOutline() // while transformed to our coord system, return local coords void RenderPath::addFocusRingRects(Vector<IntRect>& rects, int, int) { IntRect rect = enclosingIntRect(repaintRectInLocalCoordinates()); if (!rect.isEmpty()) rects.append(rect); }
IntRect VisualViewport::viewportToRootFrame(const IntRect& rectInViewport) const { // FIXME: How to snap to pixels? return enclosingIntRect(viewportToRootFrame(FloatRect(rectInViewport))); }
void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const { IntRect rect = enclosingIntRect(strokeBoundingBox()); rect.moveBy(roundedIntPoint(accumulatedOffset)); rects.append(rect); }
IntRect GraphicsContext::clipBounds() const { double x1, x2, y1, y2; cairo_clip_extents(platformContext()->cr(), &x1, &y1, &x2, &y2); return enclosingIntRect(FloatRect(x1, y1, x2 - x1, y2 - y1)); }
IntRect EllipsisBox::selectionRect() { const ComputedStyle& style = lineLayoutItem().styleRef(isFirstLineStyle()); const Font& font = style.font(); return enclosingIntRect(font.selectionRectForText(constructTextRun(font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(logicalLeft(), logicalTop() + root().selectionTopAdjustedForPrecedingBlock()), root().selectionHeightAdjustedForPrecedingBlock())); }
WebCore::IntRect DumpRenderTreeSupportEfl::selectionRectangle(const Evas_Object* ewkFrame) { DRT_SUPPORT_FRAME_GET_OR_RETURN(ewkFrame, frame, WebCore::IntRect()); return enclosingIntRect(frame->selection()->bounds()); }
// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); if (!paintRectInParent.isEmpty()) rects.append(paintRectInParent); }
// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, int, int) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); if (!paintRectInParent.isEmpty()) rects.append(paintRectInParent); }
virtual void drawInContext(PlatformGraphicsContext* context) { if (!m_owner) return; CGContextSaveGState(context); CGRect layerBounds = bounds(); if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) { CGContextScaleCTM(context, 1, -1); CGContextTranslateCTM(context, 0, -layerBounds.size.height); } if (m_owner->client()) { GraphicsContext graphicsContext(context); // It's important to get the clip from the context, because it may be significantly // smaller than the layer bounds (e.g. tiled layers) CGRect clipBounds = CGContextGetClipBoundingBox(context); IntRect clip(enclosingIntRect(clipBounds)); m_owner->paintGraphicsLayerContents(graphicsContext, clip); } #ifndef NDEBUG else { ASSERT_NOT_REACHED(); // FIXME: ideally we'd avoid calling -setNeedsDisplay on a layer that is a plain color, // so CA never makes backing store for it (which is what -setNeedsDisplay will do above). CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 1.0f); CGContextFillRect(context, layerBounds); } #endif if (m_owner->showRepaintCounter()) { String text = String::format("%d", m_owner->incrementRepaintCount());; CGContextSaveGState(context); CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f); CGRect aBounds = layerBounds; aBounds.size.width = 10 + 12 * text.length(); aBounds.size.height = 25; CGContextFillRect(context, aBounds); FontDescription desc; NONCLIENTMETRICS metrics; metrics.cbSize = sizeof(metrics); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0); FontFamily family; family.setFamily(metrics.lfSmCaptionFont.lfFaceName); desc.setFamily(family); desc.setComputedSize(22); Font font = Font(desc, 0, 0); font.update(0); GraphicsContext cg(context); cg.setFillColor(Color::black, DeviceColorSpace); cg.drawText(font, TextRun(text), IntPoint(aBounds.origin.x + 3, aBounds.origin.y + 20)); CGContextRestoreGState(context); } CGContextRestoreGState(context); }
bool FindController::updateFindIndicator(Frame& selectedFrame, bool isShowingOverlay, bool shouldAnimate) { IntRect selectionRect; ShareableBitmap::Handle handle; if (!getFindIndicatorBitmapAndRect(selectedFrame, handle, selectionRect)) return false; // We want the selection rect in window coordinates. IntRect selectionRectInWindowCoordinates = selectedFrame.view()->contentsToWindow(selectionRect); Vector<FloatRect> textRects; selectedFrame.selection().getClippedVisibleTextRectangles(textRects); // We want the text rects in selection rect coordinates. Vector<FloatRect> textRectsInSelectionRectCoordinates; for (size_t i = 0; i < textRects.size(); ++i) { IntRect textRectInSelectionRectCoordinates = selectedFrame.view()->contentsToWindow(enclosingIntRect(textRects[i])); textRectInSelectionRectCoordinates.move(-selectionRectInWindowCoordinates.x(), -selectionRectInWindowCoordinates.y()); textRectsInSelectionRectCoordinates.append(textRectInSelectionRectCoordinates); } m_webPage->send(Messages::WebPageProxy::SetFindIndicator(selectionRectInWindowCoordinates, textRectsInSelectionRectCoordinates, m_webPage->corePage()->deviceScaleFactor(), handle, !isShowingOverlay, shouldAnimate)); m_findIndicatorRect = selectionRectInWindowCoordinates; m_isShowingFindIndicator = true; return true; }
void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool) { FloatRect absoluteRect = absoluteTransform().mapRect(FloatRect(tx, ty, width(), height())); rects.append(enclosingIntRect(absoluteRect)); }