Bug 1823477 - Create a DisplaySVGItem as a base class for SVG Painted Display Items r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D173056
This commit is contained in:
Robert Longson 2023-03-21 15:05:34 +00:00
Родитель b1dfac72d9
Коммит 5d0eab08a3
8 изменённых файлов: 109 добавлений и 91 удалений

Просмотреть файл

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Main header first:
#include "DisplaySVGItem.h"
#include "mozilla/ISVGDisplayableFrame.h"
#include "mozilla/SVGUtils.h"
#include "nsLayoutUtils.h"
#include "nsPoint.h"
using namespace mozilla::gfx;
using namespace mozilla::image;
namespace mozilla {
void DisplaySVGItem::HitTest(nsDisplayListBuilder* aBuilder,
const nsRect& aRect, HitTestState* aState,
nsTArray<nsIFrame*>* aOutFrames) {
ISVGDisplayableFrame* svgFrame = do_QueryFrame(mFrame);
MOZ_ASSERT(svgFrame, "Unexpected frame type");
nsPoint pointRelativeToReferenceFrame = aRect.Center();
// ToReferenceFrame() includes mFrame->GetPosition(), our user
// space position.
nsPoint userSpacePtInAppUnits = pointRelativeToReferenceFrame -
(ToReferenceFrame() - mFrame->GetPosition());
gfxPoint userSpacePt =
gfxPoint(userSpacePtInAppUnits.x, userSpacePtInAppUnits.y) /
AppUnitsPerCSSPixel();
if (auto* target = svgFrame->GetFrameForPoint(userSpacePt)) {
aOutFrames->AppendElement(target);
}
}
void DisplaySVGItem::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {
ISVGDisplayableFrame* svgFrame = do_QueryFrame(mFrame);
MOZ_ASSERT(svgFrame, "Unexpected frame type");
int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
// ToReferenceFrame() includes our mRect offset, but painting takes
// account of that too. To avoid double counting, we subtract that
// here.
nsPoint offset = ToReferenceFrame() - mFrame->GetPosition();
gfxPoint devPixelOffset =
nsLayoutUtils::PointToGfxPoint(offset, appUnitsPerDevPixel);
gfxMatrix tm = SVGUtils::GetCSSPxToDevPxMatrix(mFrame) *
gfxMatrix::Translation(devPixelOffset);
imgDrawingParams imgParams(aBuilder->GetImageDecodeFlags());
svgFrame->PaintSVG(*aCtx, tm, imgParams);
}
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef LAYOUT_SVG_DISPLAYSVGITEM_H_
#define LAYOUT_SVG_DISPLAYSVGITEM_H_
#include "nsDisplayList.h"
namespace mozilla {
//----------------------------------------------------------------------
// Display list item:
class DisplaySVGItem : public nsPaintedDisplayItem {
public:
DisplaySVGItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsPaintedDisplayItem(aBuilder, aFrame) {
MOZ_ASSERT(aFrame, "Must have a frame!");
}
/**
* Hit testing for display lists.
* @param aRect the point or rect being tested, relative to aFrame.
* If the width and height are both 1 app unit, it indicates we're
* hit testing a point, not a rect.
* @param aOutFrames each item appends the frame(s) in this display item that
* the rect is considered over (if any) to aOutFrames.
*/
void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
/**
* Paint the frame to some rendering context.
*/
void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
};
} // namespace mozilla
#endif // LAYOUT_SVG_DISPLAYSVGITEM_H_

Просмотреть файл

@ -22,7 +22,7 @@
#include "mozilla/SVGContextPaint.h"
#include "mozilla/SVGContentUtils.h"
#include "mozilla/SVGObserverUtils.h"
#include "nsDisplayList.h"
#include "mozilla/SVGUtils.h"
#include "nsGkAtoms.h"
#include "nsLayoutUtils.h"
#include "SVGAnimatedTransformList.h"

Просмотреть файл

@ -8,14 +8,11 @@
#define LAYOUT_SVG_SVGGEOMETRYFRAME_H_
#include "mozilla/Attributes.h"
#include "mozilla/DisplaySVGItem.h"
#include "mozilla/ISVGDisplayableFrame.h"
#include "mozilla/SVGUtils.h"
#include "gfxMatrix.h"
#include "gfxRect.h"
#include "nsDisplayList.h"
#include "nsIFrame.h"
#include "nsLiteralString.h"
#include "nsQueryFrame.h"
namespace mozilla {
@ -147,28 +144,19 @@ class SVGGeometryFrame : public nsIFrame, public ISVGDisplayableFrame {
//----------------------------------------------------------------------
// Display list item:
class DisplaySVGGeometry final : public nsPaintedDisplayItem {
class DisplaySVGGeometry final : public DisplaySVGItem {
using imgDrawingParams = image::imgDrawingParams;
public:
DisplaySVGGeometry(nsDisplayListBuilder* aBuilder, SVGGeometryFrame* aFrame)
: nsPaintedDisplayItem(aBuilder, aFrame) {
: DisplaySVGItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(DisplaySVGGeometry);
MOZ_ASSERT(aFrame, "Must have a frame!");
}
MOZ_COUNTED_DTOR_OVERRIDE(DisplaySVGGeometry)
NS_DISPLAY_DECL_NAME("DisplaySVGGeometry", TYPE_SVG_GEOMETRY)
void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override {
SVGUtils::HitTest(aBuilder, this, aRect, aOutFrames);
}
void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
SVGUtils::Paint(aBuilder, this, aCtx);
}
// Whether this part of the SVG should be natively handled by webrender,
// potentially becoming an "active layer" inside a blob image.
bool ShouldBeActive(mozilla::wr::DisplayListBuilder& aBuilder,

Просмотреть файл

@ -34,6 +34,7 @@
#include "nsLayoutUtils.h"
#include "nsFrameSelection.h"
#include "nsStyleStructInlines.h"
#include "mozilla/DisplaySVGItem.h"
#include "mozilla/Likely.h"
#include "mozilla/PresShell.h"
#include "mozilla/SVGObserverUtils.h"
@ -48,7 +49,6 @@
#include "mozilla/dom/Text.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/PatternHelpers.h"
#include "nsDisplayList.h"
#include <algorithm>
#include <cmath>
#include <limits>
@ -2666,25 +2666,17 @@ void SVGTextDrawPathCallbacks::StrokeGeometry() {
// ----------------------------------------------------------------------------
// Display list item
class DisplaySVGText final : public nsPaintedDisplayItem {
class DisplaySVGText final : public DisplaySVGItem {
public:
DisplaySVGText(nsDisplayListBuilder* aBuilder, SVGTextFrame* aFrame)
: nsPaintedDisplayItem(aBuilder, aFrame) {
: DisplaySVGItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(DisplaySVGText);
MOZ_ASSERT(aFrame, "Must have a frame!");
}
MOZ_COUNTED_DTOR_OVERRIDE(DisplaySVGText)
NS_DISPLAY_DECL_NAME("DisplaySVGText", TYPE_SVG_TEXT)
void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override {
SVGUtils::HitTest(aBuilder, this, aRect, aOutFrames);
}
void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
SVGUtils::Paint(aBuilder, this, aCtx);
}
nsDisplayItemGeometry* AllocateGeometry(
nsDisplayListBuilder* aBuilder) override {
return new nsDisplayItemGenericGeometry(this, aBuilder);

Просмотреть файл

@ -892,51 +892,6 @@ nsIFrame* SVGUtils::HitTestChildren(SVGDisplayContainerFrame* aFrame,
return result;
}
void SVGUtils::HitTest(nsDisplayListBuilder* aBuilder,
const nsPaintedDisplayItem* aDisplayItem,
const nsRect& aRect, nsTArray<nsIFrame*>* aOutFrames) {
ISVGDisplayableFrame* svgFrame = do_QueryFrame(aDisplayItem->mFrame);
MOZ_ASSERT(svgFrame && FrameDoesNotIncludePositionInTM(aDisplayItem->mFrame),
"Unexpected frame type");
nsPoint pointRelativeToReferenceFrame = aRect.Center();
// ToReferenceFrame() includes mFrame->GetPosition(), our user
// space position.
nsPoint userSpacePtInAppUnits =
pointRelativeToReferenceFrame -
(aDisplayItem->ToReferenceFrame() - aDisplayItem->mFrame->GetPosition());
gfxPoint userSpacePt =
gfxPoint(userSpacePtInAppUnits.x, userSpacePtInAppUnits.y) /
AppUnitsPerCSSPixel();
if (auto* target = svgFrame->GetFrameForPoint(userSpacePt)) {
aOutFrames->AppendElement(target);
}
}
void SVGUtils::Paint(nsDisplayListBuilder* aBuilder,
const nsPaintedDisplayItem* aDisplayItem,
gfxContext* aCtx) {
ISVGDisplayableFrame* svgFrame = do_QueryFrame(aDisplayItem->mFrame);
MOZ_ASSERT(svgFrame && FrameDoesNotIncludePositionInTM(aDisplayItem->mFrame),
"Unexpected frame type");
uint32_t appUnitsPerDevPixel =
aDisplayItem->mFrame->PresContext()->AppUnitsPerDevPixel();
// ToReferenceFrame() includes our mRect offset, but painting takes
// account of that too. To avoid double counting, we subtract that
// here.
nsPoint offset =
aDisplayItem->ToReferenceFrame() - aDisplayItem->mFrame->GetPosition();
gfxPoint devPixelOffset =
nsLayoutUtils::PointToGfxPoint(offset, appUnitsPerDevPixel);
gfxMatrix tm = SVGUtils::GetCSSPxToDevPxMatrix(aDisplayItem->mFrame) *
gfxMatrix::Translation(devPixelOffset);
imgDrawingParams imgParams(aBuilder->GetImageDecodeFlags());
svgFrame->PaintSVG(*aCtx, tm, imgParams);
}
nsRect SVGUtils::TransformFrameRectToOuterSVG(const nsRect& aRect,
const gfxMatrix& aMatrix,
nsPresContext* aPresContext) {

Просмотреть файл

@ -39,7 +39,6 @@ struct nsStyleSVG;
struct nsRect;
namespace mozilla {
class nsPaintedDisplayItem;
class SVGAnimatedEnumeration;
class SVGAnimatedLength;
class SVGContextPaint;
@ -262,24 +261,6 @@ class SVGUtils final {
static nsIFrame* HitTestChildren(SVGDisplayContainerFrame* aFrame,
const gfxPoint& aPoint);
/**
* Hit testing for display lists.
* @param aRect the point or rect being tested, relative to aFrame.
* If the width and height are both 1 app unit, it indicates we're
* hit testing a point, not a rect.
* @param aOutFrames each item appends the frame(s) in this display item that
* the rect is considered over (if any) to aOutFrames.
*/
static void HitTest(nsDisplayListBuilder* aBuilder,
const nsPaintedDisplayItem* aDisplayItem,
const nsRect& aRect, nsTArray<nsIFrame*>* aOutFrames);
/**
* Paint the frame to some rendering context.
*/
static void Paint(nsDisplayListBuilder* aBuilder,
const nsPaintedDisplayItem* aDisplayItem, gfxContext* aCtx);
/*
* Returns the CanvasTM of the indicated frame, whether it's a
* child SVG frame, container SVG frame, or a regular frame.

Просмотреть файл

@ -17,6 +17,7 @@ if CONFIG["ENABLE_TESTS"]:
EXPORTS.mozilla += [
"CSSClipPathInstance.h",
"DisplaySVGItem.h",
"FilterInstance.h",
"ISVGDisplayableFrame.h",
"ISVGSVGFrame.h",
@ -42,6 +43,7 @@ EXPORTS.mozilla += [
UNIFIED_SOURCES += [
"CSSClipPathInstance.cpp",
"CSSFilterInstance.cpp",
"DisplaySVGItem.cpp",
"FilterInstance.cpp",
"SVGAFrame.cpp",
"SVGClipPathFrame.cpp",