void HTMLCanvasPainter::paintReplaced(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { GraphicsContext* context = paintInfo.context; LayoutRect contentRect = m_renderHTMLCanvas.contentBoxRect(); contentRect.moveBy(paintOffset); LayoutRect paintRect = m_renderHTMLCanvas.replacedContentRect(); paintRect.moveBy(paintOffset); bool clip = !contentRect.contains(paintRect); if (clip) { context->save(); context->clip(contentRect); } // FIXME: InterpolationNone should be used if ImageRenderingOptimizeContrast is set. // See bug for more details: crbug.com/353716. InterpolationQuality interpolationQuality = m_renderHTMLCanvas.style()->imageRendering() == ImageRenderingOptimizeContrast ? InterpolationLow : CanvasDefaultInterpolationQuality; if (m_renderHTMLCanvas.style()->imageRendering() == ImageRenderingPixelated) interpolationQuality = InterpolationNone; InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality(); context->setImageInterpolationQuality(interpolationQuality); toHTMLCanvasElement(m_renderHTMLCanvas.node())->paint(context, paintRect); context->setImageInterpolationQuality(previousInterpolationQuality); if (clip) context->restore(); }
void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { GraphicsContext* context = paintInfo.context; LayoutRect contentRect = contentBoxRect(); contentRect.moveBy(paintOffset); LayoutRect paintRect = replacedContentRect(); paintRect.moveBy(paintOffset); bool clip = !contentRect.contains(paintRect); if (clip) { // Not allowed to overflow the content box. paintInfo.context->save(); paintInfo.context->clip(pixelSnappedIntRect(contentRect)); } // FIXME: InterpolationNone should be used if ImageRenderingOptimizeContrast is set. // See bug for more details: crbug.com/353716. InterpolationQuality interpolationQuality = style()->imageRendering() == ImageRenderingOptimizeContrast ? InterpolationLow : CanvasDefaultInterpolationQuality; HTMLCanvasElement* canvas = toHTMLCanvasElement(node()); LayoutSize layoutSize = contentRect.size(); if (style()->imageRendering() == ImageRenderingPixelated && (layoutSize.width() > canvas->width() || layoutSize.height() > canvas->height() || layoutSize == canvas->size())) { interpolationQuality = InterpolationNone; } InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality(); context->setImageInterpolationQuality(interpolationQuality); canvas->paint(context, paintRect); context->setImageInterpolationQuality(previousInterpolationQuality); if (clip) context->restore(); }
void RenderHTMLCanvas::canvasSizeChanged() { IntSize canvasSize = toHTMLCanvasElement(node())->size(); LayoutSize zoomedSize(canvasSize.width() * style()->effectiveZoom(), canvasSize.height() * style()->effectiveZoom()); if (zoomedSize == intrinsicSize()) return; setIntrinsicSize(zoomedSize); if (!parent()) return; if (!preferredLogicalWidthsDirty()) setPreferredLogicalWidthsDirty(); LayoutSize oldSize = size(); updateLogicalWidth(); updateLogicalHeight(); if (oldSize == size()) return; if (!selfNeedsLayout()) setNeedsLayoutAndFullPaintInvalidation(); }
CompositingReasons RenderHTMLCanvas::additionalCompositingReasons() const { HTMLCanvasElement* canvas = toHTMLCanvasElement(node()); if (canvas->renderingContext() && canvas->renderingContext()->isAccelerated()) return CompositingReasonCanvas; return CompositingReasonNone; }
SkImageFilter* CanvasRenderingContext2DState::getFilter( Element* styleResolutionHost, IntSize canvasSize, CanvasRenderingContext2D* context) const { if (!m_filterValue) return nullptr; // StyleResolverState cannot be used in frame-less documents. if (!styleResolutionHost->document().frame()) return nullptr; if (!m_resolvedFilter) { RefPtr<ComputedStyle> filterStyle = ComputedStyle::create(); // Must set font in case the filter uses any font-relative units (em, ex) filterStyle->setFont(m_fontForFilter); StyleResolverState resolverState(styleResolutionHost->document(), styleResolutionHost, filterStyle.get()); resolverState.setStyle(filterStyle); StyleBuilder::applyProperty(CSSPropertyFilter, resolverState, *m_filterValue); resolverState.loadPendingResources(); // We can't reuse m_fillPaint and m_strokePaint for the filter, since these // incorporate the global alpha, which isn't applicable here. SkPaint fillPaintForFilter; m_fillStyle->applyToPaint(fillPaintForFilter); fillPaintForFilter.setColor(m_fillStyle->paintColor()); SkPaint strokePaintForFilter; m_strokeStyle->applyToPaint(strokePaintForFilter); strokePaintForFilter.setColor(m_strokeStyle->paintColor()); FilterEffectBuilder filterEffectBuilder( styleResolutionHost, FloatRect((FloatPoint()), FloatSize(canvasSize)), 1.0f, // Deliberately ignore zoom on the canvas element. &fillPaintForFilter, &strokePaintForFilter); if (FilterEffect* lastEffect = filterEffectBuilder.buildFilterEffect(filterStyle->filter())) { m_resolvedFilter = SkiaImageFilterBuilder::build(lastEffect, ColorSpaceDeviceRGB); if (m_resolvedFilter) { updateFilterReferences(toHTMLCanvasElement(styleResolutionHost), context, filterStyle->filter()); if (lastEffect->originTainted()) context->setOriginTainted(); } } } return m_resolvedFilter.get(); }
void CanvasFontCacheTest::SetUp() { Page::PageClients pageClients; fillWithEmptyClients(pageClients); m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600), &pageClients); m_document = toHTMLDocument(&m_dummyPageHolder->document()); m_document->documentElement()->setInnerHTML("<body><canvas id='c'></canvas></body>", ASSERT_NO_EXCEPTION); m_document->view()->updateAllLifecyclePhases(); m_canvasElement = toHTMLCanvasElement(m_document->getElementById("c")); String canvasType("2d"); CanvasContextCreationAttributes attributes; attributes.setAlpha(true); m_canvasElement->getCanvasRenderingContext(canvasType, attributes); context2d(); // Calling this for the checks }
void TouchEventManager::updateTargetAndRegionMapsForTouchStarts( HeapVector<TouchInfo>& touchInfos) { for (auto& touchInfo : touchInfos) { // Touch events implicitly capture to the touched node, and don't change // active/hover states themselves (Gesture events do). So we only need // to hit-test on touchstart and when the target could be different than // the corresponding pointer event target. if (touchInfo.point.state() == PlatformTouchPoint::TouchPressed) { HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent | HitTestRequest::ReadOnly | HitTestRequest::Active; LayoutPoint pagePoint = roundedLayoutPoint(m_frame->view()->rootFrameToContents(touchInfo.point.pos())); HitTestResult result; if (!m_touchSequenceDocument) { result = m_frame->eventHandler().hitTestResultAtPoint(pagePoint, hitType); } else if (m_touchSequenceDocument->frame()) { LayoutPoint framePoint = roundedLayoutPoint(m_touchSequenceDocument->frame()->view()->rootFrameToContents(touchInfo.point.pos())); result = EventHandler::hitTestResultInFrame(m_touchSequenceDocument->frame(), framePoint, hitType); } else { continue; } Node* node = result.innerNode(); if (!node) continue; if (isHTMLCanvasElement(node)) { std::pair<Element*, String> regionInfo = toHTMLCanvasElement(node)->getControlAndIdIfHitRegionExists(result.pointInInnerNodeFrame()); if (regionInfo.first) node = regionInfo.first; touchInfo.region = regionInfo.second; } // Touch events should not go to text nodes. if (node->isTextNode()) node = FlatTreeTraversal::parent(*node); touchInfo.touchNode = node; if (!m_touchSequenceDocument) { // Keep track of which document should receive all touch events // in the active sequence. This must be a single document to // ensure we don't leak Nodes between documents. m_touchSequenceDocument = &(touchInfo.touchNode->document()); ASSERT(m_touchSequenceDocument->frame()->view()); } // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id()) // since we shouldn't get a touchstart for a touch that's already // down. However EventSender allows this to be violated and there's // some tests that take advantage of it. There may also be edge // cases in the browser where this happens. // See http://crbug.com/345372. m_targetForTouchID.set(touchInfo.point.id(), touchInfo.touchNode); m_regionForTouchID.set(touchInfo.point.id(), touchInfo.region); TouchAction effectiveTouchAction = TouchActionUtil::computeEffectiveTouchAction( *touchInfo.touchNode); if (effectiveTouchAction != TouchActionAuto) m_frame->page()->chromeClient().setTouchAction(effectiveTouchAction); } } }