void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!pluginCrashedOrWasMissing()) return; if (paintInfo.phase == PaintPhaseSelection) return; GraphicsContext* context = paintInfo.context; if (context->paintingDisabled()) return; FloatRect contentRect; Path path; FloatRect replacementTextRect; Font font; TextRun run(""); float textWidth; if (!getReplacementTextGeometry(paintOffset, contentRect, path, replacementTextRect, font, run, textWidth)) return; GraphicsContextStateSaver stateSaver(*context); context->clip(contentRect); context->setAlpha(m_missingPluginIndicatorIsPressed ? replacementTextPressedRoundedRectOpacity : replacementTextRoundedRectOpacity); context->setFillColor(m_missingPluginIndicatorIsPressed ? replacementTextRoundedRectPressedColor() : Color::white, style()->colorSpace()); context->fillPath(path); const FontMetrics& fontMetrics = font.fontMetrics(); float labelX = roundf(replacementTextRect.location().x() + (replacementTextRect.size().width() - textWidth) / 2); float labelY = roundf(replacementTextRect.location().y() + (replacementTextRect.size().height() - fontMetrics.height()) / 2 + fontMetrics.ascent()); context->setAlpha(m_missingPluginIndicatorIsPressed ? replacementTextPressedTextOpacity : replacementTextTextOpacity); context->setFillColor(Color::black, style()->colorSpace()); context->drawBidiText(font, run, FloatPoint(labelX, labelY)); }
void RenderEmbeddedObject::paintReplaced(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!showsUnavailablePluginIndicator()) return; if (paintInfo.phase == PaintPhaseSelection) return; FloatRect contentRect; Path path; FloatRect replacementTextRect; Font font; TextRun run(""); float textWidth; if (!getReplacementTextGeometry(paintOffset, contentRect, path, replacementTextRect, font, run, textWidth)) return; GraphicsContext* context = paintInfo.context; GraphicsContextStateSaver stateSaver(*context); context->clip(contentRect); context->setAlphaAsFloat(replacementTextRoundedRectOpacity); context->setFillColor(Color::white); context->fillPath(path); const FontMetrics& fontMetrics = font.fontMetrics(); float labelX = roundf(replacementTextRect.location().x() + (replacementTextRect.size().width() - textWidth) / 2); float labelY = roundf(replacementTextRect.location().y() + (replacementTextRect.size().height() - fontMetrics.height()) / 2 + fontMetrics.ascent()); TextRunPaintInfo runInfo(run); runInfo.bounds = replacementTextRect; context->setAlphaAsFloat(replacementTextTextOpacity); context->setFillColor(Color::black); context->drawBidiText(font, runInfo, FloatPoint(labelX, labelY)); }
bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path& path, FloatRect& replacementTextRect, Font& font, TextRun& run, float& textWidth) const { contentRect = contentBoxRect(); contentRect.moveBy(roundedIntPoint(accumulatedOffset)); FontDescription fontDescription; RenderTheme::theme().systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); Settings* settings = document().settings(); ASSERT(settings); if (!settings) return false; fontDescription.setComputedSize(fontDescription.specifiedSize()); font = Font(fontDescription, 0, 0); font.update(0); run = TextRun(m_unavailablePluginReplacementText); textWidth = font.width(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 drawNativeImage(const NativeImagePtr& image, GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, const IntSize&, CompositeOperator op, BlendMode mode, const ImageOrientation& orientation) { context.save(); // Set the compositing operation. if (op == CompositeSourceOver && mode == BlendModeNormal && !nativeImageHasAlpha(image)) context.setCompositeOperation(CompositeCopy); else context.setCompositeOperation(op, mode); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) IntSize scaledSize = nativeImageSize(image); FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(srcRect, scaledSize); #else FloatRect adjustedSrcRect(srcRect); #endif FloatRect adjustedDestRect = destRect; if (orientation != DefaultImageOrientation) { // ImageOrientation expects the origin to be at (0, 0). context.translate(destRect.x(), destRect.y()); adjustedDestRect.setLocation(FloatPoint()); context.concatCTM(orientation.transformFromDefault(adjustedDestRect.size())); if (orientation.usesWidthAsHeight()) { // The destination rectangle will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. adjustedDestRect.setSize(adjustedDestRect.size().transposedSize()); } } context.platformContext()->drawSurfaceToContext(image.get(), adjustedDestRect, adjustedSrcRect, context); context.restore(); }
bool SVGRenderingContext::bufferForeground(std::unique_ptr<ImageBuffer>& imageBuffer) { ASSERT(m_paintInfo); ASSERT(is<RenderSVGImage>(*m_renderer)); FloatRect boundingBox = m_renderer->objectBoundingBox(); // Invalidate an existing buffer if the scale is not correct. if (imageBuffer) { AffineTransform transform = m_paintInfo->context().getCTM(GraphicsContext::DefinitelyIncludeDeviceScale); IntSize expandedBoundingBox = expandedIntSize(boundingBox.size()); IntSize bufferSize(static_cast<int>(ceil(expandedBoundingBox.width() * transform.xScale())), static_cast<int>(ceil(expandedBoundingBox.height() * transform.yScale()))); if (bufferSize != imageBuffer->internalSize()) imageBuffer.reset(); } // Create a new buffer and paint the foreground into it. if (!imageBuffer) { if ((imageBuffer = ImageBuffer::createCompatibleBuffer(expandedIntSize(boundingBox.size()), ColorSpaceSRGB, m_paintInfo->context()))) { GraphicsContext& bufferedRenderingContext = imageBuffer->context(); bufferedRenderingContext.translate(-boundingBox.x(), -boundingBox.y()); PaintInfo bufferedInfo(*m_paintInfo); bufferedInfo.setContext(bufferedRenderingContext); downcast<RenderSVGImage>(*m_renderer).paintForeground(bufferedInfo); } else return false; } m_paintInfo->context().drawImageBuffer(*imageBuffer, boundingBox); return true; }
bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, FloatRect& indicatorRect, FloatRect& replacementTextRect, FloatRect& arrowRect, FontCascade& font, TextRun& run, float& textWidth) const { bool includesArrow = shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason); contentRect = contentBoxRect(); contentRect.moveBy(roundedIntPoint(accumulatedOffset)); FontCascadeDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); fontDescription.setWeight(FontWeightBold); fontDescription.setRenderingMode(frame().settings().fontRenderingMode()); fontDescription.setComputedSize(12); font = FontCascade(fontDescription, 0, 0); font.update(0); run = TextRun(m_unavailablePluginReplacementText); textWidth = font.width(run); replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftTextMargin + (includesArrow ? replacementTextRoundedRectRightTextMarginWithArrow : replacementTextRoundedRectRightTextMargin), 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)); indicatorRect = replacementTextRect; // Expand the background rect to include the arrow, if it will be used. if (includesArrow) { arrowRect = indicatorRect; arrowRect.setX(ceilf(arrowRect.maxX() + replacementArrowLeftMargin)); arrowRect.setWidth(arrowRect.height()); indicatorRect.unite(arrowRect); } return true; }
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; }
static void drawDeferredFilter(GraphicsContext* context, FilterData* filterData, SVGFilterElement* filterElement) { SkiaImageFilterBuilder builder(context); SourceGraphic* sourceGraphic = static_cast<SourceGraphic*>(filterData->builder->getEffectById(SourceGraphic::effectName())); ASSERT(sourceGraphic); builder.setSourceGraphic(sourceGraphic); RefPtr<ImageFilter> imageFilter = builder.build(filterData->builder->lastEffect(), ColorSpaceDeviceRGB); FloatRect boundaries = filterData->boundaries; context->save(); FloatSize deviceSize = context->getCTM().mapSize(boundaries.size()); float scaledArea = deviceSize.width() * deviceSize.height(); // If area of scaled size is bigger than the upper limit, adjust the scale // to fit. Note that this only really matters in the non-impl-side painting // case, since the impl-side case never allocates a full-sized backing // store, only tile-sized. // FIXME: remove this once all platforms are using impl-side painting. // crbug.com/169282. if (scaledArea > FilterEffect::maxFilterArea()) { float scale = sqrtf(FilterEffect::maxFilterArea() / scaledArea); context->scale(scale, scale); } // Clip drawing of filtered image to the minimum required paint rect. FilterEffect* lastEffect = filterData->builder->lastEffect(); context->clipRect(lastEffect->determineAbsolutePaintRect(lastEffect->maxEffectRect())); if (filterElement->hasAttribute(SVGNames::filterResAttr)) { // Get boundaries in device coords. // FIXME: See crbug.com/382491. Is the use of getCTM OK here, given it does not include device // zoom or High DPI adjustments? FloatSize size = context->getCTM().mapSize(boundaries.size()); // Compute the scale amount required so that the resulting offscreen is exactly filterResX by filterResY pixels. float filterResScaleX = filterElement->filterResX()->currentValue()->value() / size.width(); float filterResScaleY = filterElement->filterResY()->currentValue()->value() / size.height(); // Scale the CTM so the primitive is drawn to filterRes. context->scale(filterResScaleX, filterResScaleY); // Create a resize filter with the inverse scale. AffineTransform resizeMatrix; resizeMatrix.scale(1 / filterResScaleX, 1 / filterResScaleY); imageFilter = builder.buildTransform(resizeMatrix, imageFilter.get()); } // If the CTM contains rotation or shearing, apply the filter to // the unsheared/unrotated matrix, and do the shearing/rotation // as a final pass. AffineTransform ctm = context->getCTM(); if (ctm.b() || ctm.c()) { AffineTransform scaleAndTranslate; scaleAndTranslate.translate(ctm.e(), ctm.f()); scaleAndTranslate.scale(ctm.xScale(), ctm.yScale()); ASSERT(scaleAndTranslate.isInvertible()); AffineTransform shearAndRotate = scaleAndTranslate.inverse(); shearAndRotate.multiply(ctm); context->setCTM(scaleAndTranslate); imageFilter = builder.buildTransform(shearAndRotate, imageFilter.get()); } context->beginLayer(1, CompositeSourceOver, &boundaries, ColorFilterNone, imageFilter.get()); context->endLayer(); context->restore(); }
void Theme::drawNamedImage(const String& name, GraphicsContext& context, const FloatRect& rect) const { // We only handle one icon at the moment. if (name != "wireless-playback") return; GraphicsContextStateSaver stateSaver(context); context.setFillColor(Color::black, ColorSpaceDeviceRGB); // Draw a generic Wireless Playback icon. context.scale(FloatSize(rect.size().width() / 100, rect.size().height() / 100)); context.translate(8, 1); Path outline; outline.moveTo(FloatPoint(59, 58.7)); outline.addBezierCurveTo(FloatPoint(58.1, 58.7), FloatPoint(57.2, 58.4), FloatPoint(56.4, 57.7)); outline.addLineTo(FloatPoint(42, 45.5)); outline.addLineTo(FloatPoint(27.6, 57.8)); outline.addBezierCurveTo(FloatPoint(25.9, 59.2), FloatPoint(23.4, 59), FloatPoint(22, 57.3)); outline.addBezierCurveTo(FloatPoint(20.6, 55.6), FloatPoint(20.8, 53.1), FloatPoint(22.5, 51.7)); outline.addLineTo(FloatPoint(39.5, 37.3)); outline.addBezierCurveTo(FloatPoint(41, 36), FloatPoint(43.2, 36), FloatPoint(44.7, 37.3)); outline.addLineTo(FloatPoint(61.7, 51.7)); outline.addBezierCurveTo(FloatPoint(63.4, 53.1), FloatPoint(63.6, 55.7), FloatPoint(62.2, 57.3)); outline.addBezierCurveTo(FloatPoint(61.3, 58.2), FloatPoint(60.1, 58.7), FloatPoint(59, 58.7)); outline.addLineTo(FloatPoint(59, 58.7)); outline.closeSubpath(); outline.moveTo(FloatPoint(42, 98)); outline.addBezierCurveTo(FloatPoint(39.8, 98), FloatPoint(38, 96.3), FloatPoint(38, 94.2)); outline.addLineTo(FloatPoint(38, 43.6)); outline.addBezierCurveTo(FloatPoint(38, 41.5), FloatPoint(39.8, 39.8), FloatPoint(42, 39.8)); outline.addBezierCurveTo(FloatPoint(44.2, 39.8), FloatPoint(46, 41.5), FloatPoint(46, 43.6)); outline.addLineTo(FloatPoint(46, 94.2)); outline.addBezierCurveTo(FloatPoint(46, 96.3), FloatPoint(44.2, 98), FloatPoint(42, 98)); outline.addLineTo(FloatPoint(42, 98)); outline.closeSubpath(); outline.moveTo(FloatPoint(83.6, 41.6)); outline.addBezierCurveTo(FloatPoint(83.6, 18.6), FloatPoint(65, 0), FloatPoint(42, 0)); outline.addBezierCurveTo(FloatPoint(19, 0), FloatPoint(0.4, 18.6), FloatPoint(0.4, 41.6)); outline.addBezierCurveTo(FloatPoint(0.4, 62.2), FloatPoint(15, 79.2), FloatPoint(35, 82.6)); outline.addLineTo(FloatPoint(35, 74.5)); outline.addBezierCurveTo(FloatPoint(20, 71.2), FloatPoint(8.4, 57.7), FloatPoint(8.4, 41.6)); outline.addBezierCurveTo(FloatPoint(8.4, 23.1), FloatPoint(23.5, 8), FloatPoint(42, 8)); outline.addBezierCurveTo(FloatPoint(60.5, 8), FloatPoint(75.5, 23.1), FloatPoint(75.5, 41.6)); outline.addBezierCurveTo(FloatPoint(75.6, 57.7), FloatPoint(64, 71.2), FloatPoint(49, 74.5)); outline.addLineTo(FloatPoint(49, 82.6)); outline.addBezierCurveTo(FloatPoint(69, 79.3), FloatPoint(83.6, 62.2), FloatPoint(83.6, 41.6)); outline.addLineTo(FloatPoint(83.6, 41.6)); outline.closeSubpath(); context.fillPath(outline); }
void GeneratorGeneratedImage::draw(GraphicsContext* destContext, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp, BlendMode blendMode) { GraphicsContextStateSaver stateSaver(*destContext); destContext->setCompositeOperation(compositeOp, blendMode); destContext->clip(destRect); destContext->translate(destRect.x(), destRect.y()); if (destRect.size() != srcRect.size()) destContext->scale(FloatSize(destRect.width() / srcRect.width(), destRect.height() / srcRect.height())); destContext->translate(-srcRect.x(), -srcRect.y()); destContext->fillRect(FloatRect(FloatPoint(), m_size), *m_gradient.get()); }
void GeneratorGeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp) { GraphicsContextStateSaver stateSaver(*context); context->setCompositeOperation(compositeOp); context->clip(dstRect); context->translate(dstRect.x(), dstRect.y()); if (dstRect.size() != srcRect.size()) context->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height())); context->translate(-srcRect.x(), -srcRect.y()); context->fillRect(FloatRect(FloatPoint(), m_size), *m_generator.get()); }
void GradientImage::draw(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, ImageOrientationDescription) { GraphicsContextStateSaver stateSaver(destContext); destContext.setCompositeOperation(compositeOp, blendMode); destContext.clip(destRect); destContext.translate(destRect.x(), destRect.y()); if (destRect.size() != srcRect.size()) destContext.scale(FloatSize(destRect.width() / srcRect.width(), destRect.height() / srcRect.height())); destContext.translate(-srcRect.x(), -srcRect.y()); destContext.fillRect(FloatRect(FloatPoint(), size()), *m_gradient.get()); }
void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox) { ASSERT(path.isEmpty()); FloatPoint center = floatPointForCenterCoordinate(m_centerX, m_centerY, boundingBox.size()); float radius = floatValueForRadiusInBox(boundingBox.size()); path.addEllipse(FloatRect( center.x() - radius + boundingBox.x(), center.y() - radius + boundingBox.y(), radius * 2, radius * 2 )); }
void GradientGeneratedImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& destRect, const FloatRect& srcRect, RespectImageOrientationEnum, ImageClampingMode) { SkAutoCanvasRestore ar(canvas, true); canvas->clipRect(destRect); canvas->translate(destRect.x(), destRect.y()); if (destRect.size() != srcRect.size()) canvas->scale(destRect.width() / srcRect.width(), destRect.height() / srcRect.height()); canvas->translate(-srcRect.x(), -srcRect.y()); SkPaint gradientPaint(paint); gradientPaint.setShader(m_gradient->shader()); canvas->drawRect(SkRect::MakeWH(m_size.width(), m_size.height()), gradientPaint); }
void CrossfadeGeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp, BlendMode blendMode, ImageOrientationDescription) { GraphicsContextStateSaver stateSaver(*context); context->setCompositeOperation(compositeOp, blendMode); context->clip(dstRect); context->translate(dstRect.x(), dstRect.y()); if (dstRect.size() != srcRect.size()) context->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height())); context->translate(-srcRect.x(), -srcRect.y()); drawCrossfade(context); }
void TileCoverageMap::update() { FloatRect containerBounds = m_controller.bounds(); FloatRect visibleRect = m_controller.visibleRect(); FloatRect coverageRect = m_controller.coverageRect(); visibleRect.contract(4, 4); // Layer is positioned 2px from top and left edges. float widthScale = 1; float scale = 1; if (!containerBounds.isEmpty()) { widthScale = std::min<float>(visibleRect.width() / containerBounds.width(), 0.1); float visibleHeight = visibleRect.height() - std::min(m_controller.topContentInset(), visibleRect.y()); scale = std::min(widthScale, visibleHeight / containerBounds.height()); } float indicatorScale = scale * m_controller.tileGrid().scale(); FloatRect mapBounds = containerBounds; mapBounds.scale(indicatorScale, indicatorScale); m_layer.get().setPosition(m_position + FloatPoint(2, 2)); m_layer.get().setBounds(mapBounds); m_layer.get().setNeedsDisplay(); visibleRect.scale(indicatorScale, indicatorScale); visibleRect.expand(2, 2); m_visibleRectIndicatorLayer->setPosition(visibleRect.location()); m_visibleRectIndicatorLayer->setBounds(FloatRect(FloatPoint(), visibleRect.size())); coverageRect.scale(indicatorScale, indicatorScale); coverageRect.expand(2, 2); m_coverageRectIndicatorLayer->setPosition(coverageRect.location()); m_coverageRectIndicatorLayer->setBounds(FloatRect(FloatPoint(), coverageRect.size())); Color visibleRectIndicatorColor; switch (m_controller.indicatorMode()) { case SynchronousScrollingBecauseOfStyleIndication: visibleRectIndicatorColor = Color(255, 0, 0); break; case SynchronousScrollingBecauseOfEventHandlersIndication: visibleRectIndicatorColor = Color(255, 255, 0); break; case AsyncScrollingIndication: visibleRectIndicatorColor = Color(0, 200, 0); break; } m_visibleRectIndicatorLayer.get().setBorderColor(visibleRectIndicatorColor); }
PassRefPtr<DisplayList> RenderSVGResourcePattern::asDisplayList(const FloatRect& tileBounds, const AffineTransform& tileTransform) const { ASSERT(!m_shouldCollectPatternAttributes); AffineTransform contentTransform; if (m_attributes.patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) contentTransform = tileTransform; // Draw the content into a DisplayList. GraphicsContext recordingContext(nullptr); recordingContext.beginRecording(FloatRect(FloatPoint(), tileBounds.size())); recordingContext.concatCTM(tileTransform); ASSERT(m_attributes.patternContentElement()); RenderSVGResourceContainer* patternRenderer = toRenderSVGResourceContainer(m_attributes.patternContentElement()->renderer()); ASSERT(patternRenderer); ASSERT(!patternRenderer->needsLayout()); SubtreeContentTransformScope contentTransformScope(contentTransform); for (RenderObject* child = patternRenderer->firstChild(); child; child = child->nextSibling()) SVGRenderingContext::renderSubtree(&recordingContext, child); return recordingContext.endRecording(); }
void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& transform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode) { if (tileRect.isEmpty()) return; if (!ctxt->drawLuminanceMask()) { Image::drawPattern(ctxt, tileRect, transform, phase, styleColorSpace, op, destRect, blendMode); return; } if (!m_cachedImage) { OwnPtr<ImageBuffer> buffer = ImageBuffer::create(expandedIntSize(tileRect.size())); ASSERT(buffer.get()); ImageObserver* observer = imageObserver(); ASSERT(observer); // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout. setImageObserver(0); draw(buffer->context(), tileRect, tileRect, styleColorSpace, op, blendMode); setImageObserver(observer); buffer->convertToLuminanceMask(); m_cachedImage = buffer->copyImage(DontCopyBackingStore, Unscaled); m_cachedImage->setSpaceSize(spaceSize()); setImageObserver(observer); } ctxt->setDrawLuminanceMask(false); m_cachedImage->drawPattern(ctxt, tileRect, transform, phase, styleColorSpace, op, destRect, blendMode); }
void PDFDocumentImage::updateCachedImageIfNeeded(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect) { // If we have an existing image, reuse it if we're doing a low-quality paint, even if cache parameters don't match; // we'll rerender when we do the subsequent high-quality paint. InterpolationQuality interpolationQuality = context->imageInterpolationQuality(); bool useLowQualityInterpolation = interpolationQuality == InterpolationNone || interpolationQuality == InterpolationLow; if (!m_cachedImageBuffer || (!cacheParametersMatch(context, dstRect, srcRect) && !useLowQualityInterpolation)) { m_cachedImageBuffer = context->createCompatibleBuffer(enclosingIntRect(dstRect).size()); if (!m_cachedImageBuffer) return; GraphicsContext* bufferContext = m_cachedImageBuffer->context(); if (!bufferContext) { m_cachedImageBuffer = nullptr; return; } transformContextForPainting(bufferContext, dstRect, srcRect); drawPDFPage(bufferContext); m_cachedTransform = context->getCTM(GraphicsContext::DefinitelyIncludeDeviceScale); m_cachedDestinationSize = dstRect.size(); m_cachedSourceRect = srcRect; IntSize internalSize = m_cachedImageBuffer->internalSize(); size_t oldCachedBytes = m_cachedBytes; m_cachedBytes = internalSize.width() * internalSize.height() * 4; if (imageObserver()) imageObserver()->decodedSizeChanged(this, safeCast<int>(m_cachedBytes) - safeCast<int>(oldCachedBytes)); } }
void PlatformCALayerRemote::setBounds(const FloatRect& value) { m_properties.size = value.size(); m_properties.notePropertiesChanged(RemoteLayerTreeTransaction::SizeChanged); ensureBackingStore(); }
void WebInspectorClient::showPaintRect(const FloatRect& rect) { if (!m_paintRectOverlay) { m_paintRectOverlay = PageOverlay::create(this, PageOverlay::OverlayType::Document); m_page->installPageOverlay(m_paintRectOverlay, PageOverlay::FadeMode::DoNotFade); } if (!m_paintIndicatorLayerClient) m_paintIndicatorLayerClient = std::make_unique<RepaintIndicatorLayerClient>(*this); std::unique_ptr<GraphicsLayer> paintLayer = GraphicsLayer::create(m_page->drawingArea()->graphicsLayerFactory(), *m_paintIndicatorLayerClient); paintLayer->setAnchorPoint(FloatPoint3D()); paintLayer->setPosition(rect.location()); paintLayer->setSize(rect.size()); paintLayer->setBackgroundColor(Color(1.0f, 0.0f, 0.0f, 0.2f)); KeyframeValueList fadeKeyframes(AnimatedPropertyOpacity); OwnPtr<AnimationValue> intialValue = FloatAnimationValue::create(0, 1); fadeKeyframes.insert(intialValue.release()); OwnPtr<AnimationValue> finalValue = FloatAnimationValue::create(0.25, 0); fadeKeyframes.insert(finalValue.release()); RefPtr<Animation> opacityAnimation = Animation::create(); opacityAnimation->setDuration(0.25); paintLayer->addAnimation(fadeKeyframes, FloatSize(), opacityAnimation.get(), ASCIILiteral("opacity"), 0); m_paintRectLayers.add(paintLayer.get()); GraphicsLayer* overlayRootLayer = m_paintRectOverlay->layer(); overlayRootLayer->addChild(paintLayer.release()); }
void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace colorSpace, CompositeOperator compositeOp, const FloatRect& dstRect) { FloatRect zoomedContainerRect = FloatRect(FloatPoint(), containerSize); zoomedContainerRect.scale(zoom); // The ImageBuffer size needs to be scaled to match the final resolution. AffineTransform transform = context->getCTM(); FloatSize imageBufferScale = FloatSize(transform.xScale(), transform.yScale()); ASSERT(imageBufferScale.width()); ASSERT(imageBufferScale.height()); FloatRect imageBufferSize = zoomedContainerRect; imageBufferSize.scale(imageBufferScale.width(), imageBufferScale.height()); OwnPtr<ImageBuffer> buffer = ImageBuffer::create(expandedIntSize(imageBufferSize.size()), 1); if (!buffer) // Failed to allocate buffer. return; drawForContainer(buffer->context(), containerSize, zoom, imageBufferSize, zoomedContainerRect, ColorSpaceDeviceRGB, CompositeSourceOver, BlendModeNormal); RefPtr<Image> image = buffer->copyImage(DontCopyBackingStore, Unscaled); // Adjust the source rect and transform due to the image buffer's scaling. FloatRect scaledSrcRect = srcRect; scaledSrcRect.scale(imageBufferScale.width(), imageBufferScale.height()); AffineTransform unscaledPatternTransform(patternTransform); unscaledPatternTransform.scale(1 / imageBufferScale.width(), 1 / imageBufferScale.height()); image->drawPattern(context, scaledSrcRect, unscaledPatternTransform, phase, colorSpace, compositeOp, dstRect); }
void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& srcRect, const FloatSize& scale, const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& dstRect, blink::WebBlendMode blendMode, const IntSize& repeatSpacing) { FloatRect zoomedContainerRect = FloatRect(FloatPoint(), containerSize); zoomedContainerRect.scale(zoom); // The ImageBuffer size needs to be scaled to match the final resolution. // FIXME: No need to get the full CTM here, we just need the scale. AffineTransform transform = context->getCTM(); FloatSize imageBufferScale = FloatSize(transform.xScale(), transform.yScale()); ASSERT(imageBufferScale.width()); ASSERT(imageBufferScale.height()); FloatSize scaleWithoutCTM(scale.width() / imageBufferScale.width(), scale.height() / imageBufferScale.height()); FloatRect imageBufferSize = zoomedContainerRect; imageBufferSize.scale(imageBufferScale.width(), imageBufferScale.height()); OwnPtr<ImageBuffer> buffer = ImageBuffer::create(expandedIntSize(imageBufferSize.size())); if (!buffer) // Failed to allocate buffer. return; drawForContainer(buffer->context(), containerSize, zoom, imageBufferSize, zoomedContainerRect, CompositeSourceOver, blink::WebBlendModeNormal); RefPtr<Image> image = buffer->copyImage(DontCopyBackingStore, Unscaled); // Adjust the source rect and transform due to the image buffer's scaling. FloatRect scaledSrcRect = srcRect; scaledSrcRect.scale(imageBufferScale.width(), imageBufferScale.height()); image->drawPattern(context, scaledSrcRect, scaleWithoutCTM, phase, compositeOp, dstRect, blendMode, repeatSpacing); }
static inline void clipToTextMask(GraphicsContext* context, OwnPtr<ImageBuffer>& imageBuffer, const RenderObject* object, const SVGPaintServerGradient* gradientServer) { FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->relativeBBox(false); // Fixup transformations to be able to clip to mask TransformationMatrix transform = object->absoluteTransform(); FloatRect textBoundary = transform.mapRect(maskBBox); IntSize maskSize(lroundf(textBoundary.width()), lroundf(textBoundary.height())); clampImageBufferSizeToViewport(object->document()->renderer(), maskSize); textBoundary.setSize(textBoundary.size().shrunkTo(maskSize)); // Clip current context to mask image (gradient) context->concatCTM(transform.inverse()); context->clipToImageBuffer(textBoundary, imageBuffer.get()); context->concatCTM(transform); if (gradientServer->boundingBoxMode()) { context->translate(maskBBox.x(), maskBBox.y()); context->scale(FloatSize(maskBBox.width(), maskBBox.height())); } context->concatCTM(gradientServer->gradientTransform()); }
void SVGImagePainter::paintForeground(const PaintInfo& paintInfo) { const LayoutImageResource* imageResource = m_layoutSVGImage.imageResource(); IntSize imageViewportSize = expandedIntSize(computeImageViewportSize()); if (imageViewportSize.isEmpty()) return; RefPtr<Image> image = imageResource->image( imageViewportSize, m_layoutSVGImage.style()->effectiveZoom()); FloatRect destRect = m_layoutSVGImage.objectBoundingBox(); FloatRect srcRect(0, 0, image->width(), image->height()); SVGImageElement* imageElement = toSVGImageElement(m_layoutSVGImage.element()); imageElement->preserveAspectRatio()->currentValue()->transformRect(destRect, srcRect); InterpolationQuality interpolationQuality = InterpolationDefault; interpolationQuality = ImageQualityController::imageQualityController() ->chooseInterpolationQuality( m_layoutSVGImage, image.get(), image.get(), LayoutSize(destRect.size())); InterpolationQuality previousInterpolationQuality = paintInfo.context.imageInterpolationQuality(); paintInfo.context.setImageInterpolationQuality(interpolationQuality); paintInfo.context.drawImage(image.get(), destRect, &srcRect); paintInfo.context.setImageInterpolationQuality(previousInterpolationQuality); }
void FullscreenVideoController::LayerClient::platformCALayerLayoutSublayersOfLayer(PlatformCALayer* layer) { ASSERT_ARG(layer, layer == m_parent->m_rootChild); HTMLVideoElement* videoElement = m_parent->m_videoElement.get(); if (!videoElement) return; PlatformCALayer* videoLayer = PlatformCALayer::platformCALayer(videoElement->platformLayer()); if (!videoLayer || videoLayer->superlayer() != layer) return; FloatRect layerBounds = layer->bounds(); FloatSize videoSize = videoElement->player()->naturalSize(); float scaleFactor; if (videoSize.aspectRatio() > layerBounds.size().aspectRatio()) scaleFactor = layerBounds.width() / videoSize.width(); else scaleFactor = layerBounds.height() / videoSize.height(); videoSize.scale(scaleFactor); // Calculate the centered position based on the videoBounds and layerBounds: FloatPoint videoPosition; FloatPoint videoOrigin; videoOrigin.setX((layerBounds.width() - videoSize.width()) * 0.5); videoOrigin.setY((layerBounds.height() - videoSize.height()) * 0.5); videoLayer->setPosition(videoOrigin); videoLayer->setBounds(FloatRect(FloatPoint(), videoSize)); }
void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp, BlendMode blendMode) { if (!m_page) return; ImageObserver* observer = imageObserver(); ASSERT(observer); // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout. setImageObserver(0); IntSize roundedContainerSize = roundedIntSize(containerSize); setContainerSize(roundedContainerSize); FloatRect scaledSrc = srcRect; scaledSrc.scale(1 / zoom); // Compensate for the container size rounding by adjusting the source rect. FloatSize adjustedSrcSize = scaledSrc.size(); adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height()); scaledSrc.setSize(adjustedSrcSize); draw(context, dstRect, scaledSrc, colorSpace, compositeOp, blendMode); setImageObserver(observer); }
PassRefPtr<SkPicture> LayoutSVGResourcePattern::asPicture(const FloatRect& tileBounds, const AffineTransform& tileTransform) const { ASSERT(!m_shouldCollectPatternAttributes); AffineTransform contentTransform; if (attributes().patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) contentTransform = tileTransform; FloatRect bounds(FloatPoint(), tileBounds.size()); SkPictureBuilder pictureBuilder(bounds); const LayoutSVGResourceContainer* patternLayoutObject = resolveContentElement(); ASSERT(patternLayoutObject && !patternLayoutObject->needsLayout()); SubtreeContentTransformScope contentTransformScope(contentTransform); { TransformRecorder transformRecorder(pictureBuilder.context(), *patternLayoutObject, tileTransform); for (LayoutObject* child = patternLayoutObject->firstChild(); child; child = child->nextSibling()) SVGPaintContext::paintSubtree(pictureBuilder.context(), child); } return pictureBuilder.endRecording(); }
void BitmapImage::drawPattern(GraphicsContext& ctxt, const FloatRect& tileRect, const AffineTransform& transform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode) { if (tileRect.isEmpty()) return; if (!ctxt.drawLuminanceMask()) { Image::drawPattern(ctxt, tileRect, transform, phase, spacing, op, destRect, blendMode); return; } if (!m_cachedImage) { auto buffer = ImageBuffer::createCompatibleBuffer(expandedIntSize(tileRect.size()), ctxt); if (!buffer) return; ImageObserver* observer = imageObserver(); ASSERT(observer); // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout. setImageObserver(nullptr); draw(buffer->context(), tileRect, tileRect, op, blendMode, ImageOrientationDescription()); setImageObserver(observer); buffer->convertToLuminanceMask(); m_cachedImage = buffer->copyImage(DontCopyBackingStore, Unscaled); if (!m_cachedImage) return; } ctxt.setDrawLuminanceMask(false); m_cachedImage->drawPattern(ctxt, tileRect, transform, phase, spacing, op, destRect, blendMode); }
PassRefPtr<SkImageFilter> FEImage::createImageFilterForRenderer(RenderObject* renderer, SkiaImageFilterBuilder* builder) { FloatRect dstRect = filterPrimitiveSubregion(); AffineTransform transform; SVGElement* contextNode = toSVGElement(renderer->node()); if (contextNode->hasRelativeLengths()) { SVGLengthContext lengthContext(contextNode); FloatSize viewportSize; // 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(viewportSize)) transform = makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), dstRect); } else { transform.translate(dstRect.x(), dstRect.y()); } GraphicsContext* context = builder->context(); if (!context) return adoptRef(SkBitmapSource::Create(SkBitmap())); AffineTransform contentTransformation; context->save(); context->beginRecording(FloatRect(FloatPoint(), dstRect.size())); context->concatCTM(transform); SVGRenderingContext::renderSubtree(context, renderer, contentTransformation); RefPtr<DisplayList> displayList = context->endRecording(); context->restore(); RefPtr<SkImageFilter> result = adoptRef(SkPictureImageFilter::Create(displayList->picture(), dstRect)); return result.release(); }