Пример #1
0
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();
}
Пример #2
0
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();
}
Пример #3
0
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();
}
Пример #4
0
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();
}
Пример #6
0
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
}
Пример #7
0
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);
        }
    }
}