2017-10-27 20:33:53 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
|
2012-03-26 15:58:59 +04:00
|
|
|
// Main header first:
|
2016-12-18 14:11:47 +03:00
|
|
|
#include "SVGGeometryFrame.h"
|
2012-03-20 16:15:55 +04:00
|
|
|
|
2012-03-26 15:58:59 +04:00
|
|
|
// Keep others in (case-insensitive) order:
|
2014-07-06 00:53:04 +04:00
|
|
|
#include "gfx2DGlue.h"
|
2012-03-26 15:58:59 +04:00
|
|
|
#include "gfxContext.h"
|
|
|
|
#include "gfxPlatform.h"
|
2014-10-17 15:53:16 +04:00
|
|
|
#include "gfxUtils.h"
|
2014-07-06 19:30:55 +04:00
|
|
|
#include "mozilla/gfx/2D.h"
|
2014-09-30 21:08:13 +04:00
|
|
|
#include "mozilla/gfx/Helpers.h"
|
2015-10-18 08:24:48 +03:00
|
|
|
#include "mozilla/RefPtr.h"
|
2016-07-22 14:07:39 +03:00
|
|
|
#include "mozilla/SVGContextPaint.h"
|
2012-07-20 22:12:29 +04:00
|
|
|
#include "nsDisplayList.h"
|
2006-12-26 20:47:52 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2014-08-07 11:09:31 +04:00
|
|
|
#include "nsLayoutUtils.h"
|
2017-08-30 16:14:46 +03:00
|
|
|
#include "SVGObserverUtils.h"
|
2012-06-30 15:20:46 +04:00
|
|
|
#include "nsSVGIntegrationUtils.h"
|
2012-03-26 15:58:59 +04:00
|
|
|
#include "nsSVGMarkerFrame.h"
|
2016-12-18 14:11:47 +03:00
|
|
|
#include "SVGGeometryElement.h"
|
2012-03-26 15:58:59 +04:00
|
|
|
#include "nsSVGUtils.h"
|
2014-01-30 22:26:54 +04:00
|
|
|
#include "mozilla/ArrayUtils.h"
|
2012-05-17 08:05:09 +04:00
|
|
|
#include "SVGAnimatedTransformList.h"
|
2014-07-06 00:53:04 +04:00
|
|
|
#include "SVGContentUtils.h"
|
2013-01-03 10:17:03 +04:00
|
|
|
#include "SVGGraphicsElement.h"
|
2012-05-17 08:05:09 +04:00
|
|
|
|
|
|
|
using namespace mozilla;
|
2017-03-08 07:10:29 +03:00
|
|
|
using namespace mozilla::dom;
|
2013-12-31 01:42:32 +04:00
|
|
|
using namespace mozilla::gfx;
|
2016-07-14 07:47:06 +03:00
|
|
|
using namespace mozilla::image;
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
|
2006-06-21 19:42:28 +04:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Implementation
|
|
|
|
|
|
|
|
nsIFrame*
|
2016-12-18 14:11:47 +03:00
|
|
|
NS_NewSVGGeometryFrame(nsIPresShell* aPresShell,
|
|
|
|
nsStyleContext* aContext)
|
2006-06-21 19:42:28 +04:00
|
|
|
{
|
2016-12-18 14:11:47 +03:00
|
|
|
return new (aPresShell) SVGGeometryFrame(aContext);
|
2006-06-21 19:42:28 +04:00
|
|
|
}
|
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
NS_IMPL_FRAMEARENA_HELPERS(SVGGeometryFrame)
|
2009-09-12 20:49:24 +04:00
|
|
|
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
//----------------------------------------------------------------------
|
2009-01-12 22:20:59 +03:00
|
|
|
// nsQueryFrame methods
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
NS_QUERYFRAME_HEAD(SVGGeometryFrame)
|
2017-02-09 21:24:31 +03:00
|
|
|
NS_QUERYFRAME_ENTRY(nsSVGDisplayableFrame)
|
2016-12-18 14:11:47 +03:00
|
|
|
NS_QUERYFRAME_ENTRY(SVGGeometryFrame)
|
2016-04-18 10:38:47 +03:00
|
|
|
NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
|
2012-07-20 22:12:29 +04:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Display list item:
|
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
class nsDisplaySVGGeometry : public nsDisplayItem {
|
2017-05-18 23:03:41 +03:00
|
|
|
typedef mozilla::image::imgDrawingParams imgDrawingParams;
|
|
|
|
|
2012-07-20 22:12:29 +04:00
|
|
|
public:
|
2016-12-18 14:11:47 +03:00
|
|
|
nsDisplaySVGGeometry(nsDisplayListBuilder* aBuilder,
|
|
|
|
SVGGeometryFrame* aFrame)
|
2012-07-20 22:12:29 +04:00
|
|
|
: nsDisplayItem(aBuilder, aFrame)
|
|
|
|
{
|
2016-12-18 14:11:47 +03:00
|
|
|
MOZ_COUNT_CTOR(nsDisplaySVGGeometry);
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(aFrame, "Must have a frame!");
|
2012-07-20 22:12:29 +04:00
|
|
|
}
|
|
|
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
2016-12-18 14:11:47 +03:00
|
|
|
virtual ~nsDisplaySVGGeometry() {
|
|
|
|
MOZ_COUNT_DTOR(nsDisplaySVGGeometry);
|
2012-07-20 22:12:29 +04:00
|
|
|
}
|
|
|
|
#endif
|
2016-07-14 07:47:06 +03:00
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
NS_DISPLAY_DECL_NAME("nsDisplaySVGGeometry", TYPE_SVG_GEOMETRY)
|
2012-07-20 22:12:29 +04:00
|
|
|
|
|
|
|
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
2015-03-21 19:28:04 +03:00
|
|
|
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
|
2012-07-20 22:12:29 +04:00
|
|
|
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
2017-06-09 22:14:53 +03:00
|
|
|
gfxContext* aCtx) override;
|
2016-07-14 07:47:06 +03:00
|
|
|
|
|
|
|
nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
|
|
|
|
{
|
|
|
|
return new nsDisplayItemGenericImageGeometry(this, aBuilder);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayItemGeometry* aGeometry,
|
2017-08-24 18:09:44 +03:00
|
|
|
nsRegion *aInvalidRegion) const override;
|
2012-07-20 22:12:29 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2016-12-18 14:11:47 +03:00
|
|
|
nsDisplaySVGGeometry::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
|
|
|
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
|
2012-07-20 22:12:29 +04:00
|
|
|
{
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame *frame = static_cast<SVGGeometryFrame*>(mFrame);
|
2012-07-20 22:12:29 +04:00
|
|
|
nsPoint pointRelativeToReferenceFrame = aRect.Center();
|
|
|
|
// ToReferenceFrame() includes frame->GetPosition(), our user space position.
|
2014-08-07 11:09:31 +04:00
|
|
|
nsPoint userSpacePtInAppUnits = pointRelativeToReferenceFrame -
|
|
|
|
(ToReferenceFrame() - frame->GetPosition());
|
|
|
|
gfxPoint userSpacePt =
|
|
|
|
gfxPoint(userSpacePtInAppUnits.x, userSpacePtInAppUnits.y) /
|
|
|
|
frame->PresContext()->AppUnitsPerCSSPixel();
|
2012-07-20 22:12:29 +04:00
|
|
|
if (frame->GetFrameForPoint(userSpacePt)) {
|
|
|
|
aOutFrames->AppendElement(frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-12-18 14:11:47 +03:00
|
|
|
nsDisplaySVGGeometry::Paint(nsDisplayListBuilder* aBuilder,
|
2017-06-09 22:14:53 +03:00
|
|
|
gfxContext* aCtx)
|
2012-07-20 22:12:29 +04:00
|
|
|
{
|
2014-08-29 23:42:07 +04:00
|
|
|
uint32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
|
|
|
|
|
2012-07-20 22:12:29 +04:00
|
|
|
// 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();
|
|
|
|
|
2014-08-29 23:42:07 +04:00
|
|
|
gfxPoint devPixelOffset =
|
|
|
|
nsLayoutUtils::PointToGfxPoint(offset, appUnitsPerDevPixel);
|
|
|
|
|
2017-01-24 18:22:43 +03:00
|
|
|
gfxMatrix tm = nsSVGUtils::GetCSSPxToDevPxMatrix(mFrame) *
|
2014-08-29 23:42:07 +04:00
|
|
|
gfxMatrix::Translation(devPixelOffset);
|
2017-05-18 23:03:41 +03:00
|
|
|
imgDrawingParams imgParams(aBuilder->ShouldSyncDecodeImages()
|
|
|
|
? imgIContainer::FLAG_SYNC_DECODE
|
|
|
|
: imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
|
2017-03-24 11:49:37 +03:00
|
|
|
|
2017-06-09 22:14:53 +03:00
|
|
|
static_cast<SVGGeometryFrame*>(mFrame)->PaintSVG(*aCtx,
|
2017-05-18 23:03:41 +03:00
|
|
|
tm, imgParams);
|
2016-07-14 07:47:06 +03:00
|
|
|
|
2017-05-18 23:03:41 +03:00
|
|
|
nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, imgParams.result);
|
2016-07-14 07:47:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-08-24 18:09:44 +03:00
|
|
|
nsDisplaySVGGeometry::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayItemGeometry* aGeometry,
|
|
|
|
nsRegion* aInvalidRegion) const
|
2016-07-14 07:47:06 +03:00
|
|
|
{
|
|
|
|
auto geometry =
|
|
|
|
static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
|
|
|
|
|
|
|
|
if (aBuilder->ShouldSyncDecodeImages() &&
|
|
|
|
geometry->ShouldInvalidateToSyncDecodeImages()) {
|
|
|
|
bool snap;
|
|
|
|
aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
|
|
|
|
}
|
|
|
|
|
|
|
|
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
|
2012-07-20 22:12:29 +04:00
|
|
|
}
|
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
namespace mozilla {
|
|
|
|
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsIFrame methods
|
2006-06-20 21:01:09 +04:00
|
|
|
|
2014-01-04 12:29:02 +04:00
|
|
|
void
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::Init(nsIContent* aContent,
|
|
|
|
nsContainerFrame* aParent,
|
|
|
|
nsIFrame* aPrevInFlow)
|
2014-01-04 12:29:02 +04:00
|
|
|
{
|
|
|
|
AddStateBits(aParent->GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD);
|
2016-04-18 10:38:47 +03:00
|
|
|
nsFrame::Init(aContent, aParent, aPrevInFlow);
|
2014-01-04 12:29:02 +04:00
|
|
|
}
|
|
|
|
|
2014-02-18 11:47:48 +04:00
|
|
|
nsresult
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::AttributeChanged(int32_t aNameSpaceID,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-12-18 14:11:47 +03:00
|
|
|
int32_t aModType)
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
{
|
2013-05-23 11:04:21 +04:00
|
|
|
// We don't invalidate for transform changes (the layers code does that).
|
|
|
|
// Also note that SVGTransformableElement::GetAttributeChangeHint will
|
|
|
|
// return nsChangeHint_UpdateOverflow for "transform" attribute changes
|
|
|
|
// and cause DoApplyRenderingChangeToTree to make the SchedulePaint call.
|
|
|
|
|
2006-03-02 23:22:19 +03:00
|
|
|
if (aNameSpaceID == kNameSpaceID_None &&
|
2016-12-18 14:11:47 +03:00
|
|
|
(static_cast<SVGGeometryElement*>
|
2017-08-27 01:58:38 +03:00
|
|
|
(GetContent())->AttributeDefinesGeometry(aAttribute))) {
|
2014-11-06 12:30:11 +03:00
|
|
|
nsLayoutUtils::PostRestyleEvent(
|
|
|
|
mContent->AsElement(), nsRestyleHint(0),
|
|
|
|
nsChangeHint_InvalidateRenderingObservers);
|
2013-04-25 13:18:42 +04:00
|
|
|
nsSVGUtils::ScheduleReflowSVG(this);
|
2012-11-28 13:42:13 +04:00
|
|
|
}
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-08-14 13:51:00 +04:00
|
|
|
/* virtual */ void
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
2013-08-14 13:51:00 +04:00
|
|
|
{
|
2016-04-18 10:38:47 +03:00
|
|
|
nsFrame::DidSetStyleContext(aOldStyleContext);
|
2013-08-14 13:51:00 +04:00
|
|
|
|
|
|
|
if (aOldStyleContext) {
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryElement* element =
|
2017-08-27 01:58:38 +03:00
|
|
|
static_cast<SVGGeometryElement*>(GetContent());
|
2014-10-04 15:13:30 +04:00
|
|
|
|
2015-11-12 00:31:32 +03:00
|
|
|
auto oldStyleSVG = aOldStyleContext->PeekStyleSVG();
|
2017-08-27 01:58:38 +03:00
|
|
|
if (oldStyleSVG && !SVGContentUtils::ShapeTypeHasNoCorners(GetContent())) {
|
2015-11-12 00:31:32 +03:00
|
|
|
if (StyleSVG()->mStrokeLinecap != oldStyleSVG->mStrokeLinecap &&
|
2015-03-03 14:09:00 +03:00
|
|
|
element->IsSVGElement(nsGkAtoms::path)) {
|
2014-10-04 15:13:30 +04:00
|
|
|
// If the stroke-linecap changes to or from "butt" then our element
|
|
|
|
// needs to update its cached Moz2D Path, since SVGPathData::BuildPath
|
|
|
|
// decides whether or not to insert little lines into the path for zero
|
|
|
|
// length subpaths base on that property.
|
|
|
|
element->ClearAnyCachedPath();
|
2014-10-06 17:19:14 +04:00
|
|
|
} else if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
|
2015-11-12 00:31:32 +03:00
|
|
|
if (StyleSVG()->mClipRule != oldStyleSVG->mClipRule) {
|
2014-10-06 17:19:14 +04:00
|
|
|
// Moz2D Path objects are fill-rule specific.
|
|
|
|
// For clipPath we use clip-rule as the path's fill-rule.
|
|
|
|
element->ClearAnyCachedPath();
|
|
|
|
}
|
|
|
|
} else {
|
2015-11-12 00:31:32 +03:00
|
|
|
if (StyleSVG()->mFillRule != oldStyleSVG->mFillRule) {
|
2014-10-06 17:19:14 +04:00
|
|
|
// Moz2D Path objects are fill-rule specific.
|
|
|
|
element->ClearAnyCachedPath();
|
|
|
|
}
|
2014-10-04 15:13:30 +04:00
|
|
|
}
|
|
|
|
}
|
2013-08-14 13:51:00 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-17 08:05:09 +04:00
|
|
|
bool
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::IsSVGTransformed(gfx::Matrix *aOwnTransform,
|
|
|
|
gfx::Matrix *aFromParentTransform) const
|
2012-05-17 08:05:09 +04:00
|
|
|
{
|
|
|
|
bool foundTransform = false;
|
|
|
|
|
|
|
|
// Check if our parent has children-only transforms:
|
|
|
|
nsIFrame *parent = GetParent();
|
|
|
|
if (parent &&
|
|
|
|
parent->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer)) {
|
|
|
|
foundTransform = static_cast<nsSVGContainerFrame*>(parent)->
|
|
|
|
HasChildrenOnlyTransform(aFromParentTransform);
|
|
|
|
}
|
|
|
|
|
2017-08-27 01:58:38 +03:00
|
|
|
nsSVGElement *content = static_cast<nsSVGElement*>(GetContent());
|
2013-04-15 02:56:34 +04:00
|
|
|
nsSVGAnimatedTransformList* transformList =
|
2013-04-14 11:17:36 +04:00
|
|
|
content->GetAnimatedTransformList();
|
|
|
|
if ((transformList && transformList->HasTransform()) ||
|
2012-07-09 21:41:12 +04:00
|
|
|
content->GetAnimateMotionTransform()) {
|
2012-05-17 08:05:09 +04:00
|
|
|
if (aOwnTransform) {
|
2015-12-03 01:36:23 +03:00
|
|
|
*aOwnTransform = gfx::ToMatrix(
|
|
|
|
content->PrependLocalTransformsTo(
|
|
|
|
gfxMatrix(),
|
|
|
|
eUserSpaceToParent));
|
2012-05-17 08:05:09 +04:00
|
|
|
}
|
|
|
|
foundTransform = true;
|
|
|
|
}
|
|
|
|
return foundTransform;
|
|
|
|
}
|
|
|
|
|
2013-02-14 15:12:27 +04:00
|
|
|
void
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aLists)
|
2012-07-20 22:12:29 +04:00
|
|
|
{
|
2017-08-27 01:58:38 +03:00
|
|
|
if (!static_cast<const nsSVGElement*>(GetContent())->HasValidDimensions() ||
|
2016-04-01 04:36:46 +03:00
|
|
|
(!IsVisibleForPainting(aBuilder) && aBuilder->IsForPainting())) {
|
2013-02-14 15:12:27 +04:00
|
|
|
return;
|
2012-07-20 22:12:29 +04:00
|
|
|
}
|
2016-05-24 07:23:22 +03:00
|
|
|
DisplayOutline(aBuilder, aLists);
|
2017-12-13 20:23:04 +03:00
|
|
|
aLists.Content()->AppendToTop(
|
2016-12-18 14:11:47 +03:00
|
|
|
new (aBuilder) nsDisplaySVGGeometry(aBuilder, this));
|
2012-07-20 22:12:29 +04:00
|
|
|
}
|
|
|
|
|
2006-04-06 17:02:53 +04:00
|
|
|
//----------------------------------------------------------------------
|
2017-02-09 21:24:31 +03:00
|
|
|
// nsSVGDisplayableFrame methods
|
2006-04-06 17:02:53 +04:00
|
|
|
|
2017-05-18 23:03:41 +03:00
|
|
|
void
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::PaintSVG(gfxContext& aContext,
|
|
|
|
const gfxMatrix& aTransform,
|
2017-05-18 23:03:41 +03:00
|
|
|
imgDrawingParams& aImgParams,
|
|
|
|
const nsIntRect* aDirtyRect)
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
{
|
2013-02-17 01:51:02 +04:00
|
|
|
if (!StyleVisibility()->IsVisible())
|
2017-05-18 23:03:41 +03:00
|
|
|
return;
|
2004-10-04 22:56:53 +04:00
|
|
|
|
2014-09-30 21:08:13 +04:00
|
|
|
// Matrix to the geometry's user space:
|
|
|
|
gfxMatrix newMatrix =
|
2017-11-11 05:14:09 +03:00
|
|
|
aContext.CurrentMatrixDouble().PreMultiply(aTransform).NudgeToIntegers();
|
2014-09-30 21:08:13 +04:00
|
|
|
if (newMatrix.IsSingular()) {
|
2017-05-18 23:03:41 +03:00
|
|
|
return;
|
2014-09-30 21:08:13 +04:00
|
|
|
}
|
|
|
|
|
2013-02-17 01:51:02 +04:00
|
|
|
uint32_t paintOrder = StyleSVG()->mPaintOrder;
|
2017-03-21 05:12:23 +03:00
|
|
|
|
2013-01-13 03:27:53 +04:00
|
|
|
if (paintOrder == NS_STYLE_PAINT_ORDER_NORMAL) {
|
2017-05-18 23:03:41 +03:00
|
|
|
Render(&aContext, eRenderFill | eRenderStroke, newMatrix, aImgParams);
|
|
|
|
PaintMarkers(aContext, aTransform, aImgParams);
|
2013-01-13 03:27:53 +04:00
|
|
|
} else {
|
|
|
|
while (paintOrder) {
|
|
|
|
uint32_t component =
|
|
|
|
paintOrder & ((1 << NS_STYLE_PAINT_ORDER_BITWIDTH) - 1);
|
|
|
|
switch (component) {
|
|
|
|
case NS_STYLE_PAINT_ORDER_FILL:
|
2017-05-18 23:03:41 +03:00
|
|
|
Render(&aContext, eRenderFill, newMatrix, aImgParams);
|
2013-01-13 03:27:53 +04:00
|
|
|
break;
|
|
|
|
case NS_STYLE_PAINT_ORDER_STROKE:
|
2017-05-18 23:03:41 +03:00
|
|
|
Render(&aContext, eRenderStroke, newMatrix, aImgParams);
|
2013-01-13 03:27:53 +04:00
|
|
|
break;
|
|
|
|
case NS_STYLE_PAINT_ORDER_MARKERS:
|
2017-05-18 23:03:41 +03:00
|
|
|
PaintMarkers(aContext, aTransform, aImgParams);
|
2013-01-13 03:27:53 +04:00
|
|
|
break;
|
2007-04-10 14:19:59 +04:00
|
|
|
}
|
2013-01-13 03:27:53 +04:00
|
|
|
paintOrder >>= NS_STYLE_PAINT_ORDER_BITWIDTH;
|
2005-04-06 23:02:13 +04:00
|
|
|
}
|
2004-12-09 06:16:15 +03:00
|
|
|
}
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
}
|
|
|
|
|
2014-02-20 02:34:31 +04:00
|
|
|
nsIFrame*
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::GetFrameForPoint(const gfxPoint& aPoint)
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
{
|
2014-07-06 00:53:04 +04:00
|
|
|
FillRule fillRule;
|
|
|
|
uint16_t hitTestFlags;
|
2010-12-06 23:57:18 +03:00
|
|
|
if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
|
2011-07-08 17:20:14 +04:00
|
|
|
hitTestFlags = SVG_HIT_TEST_FILL;
|
2014-10-11 12:24:44 +04:00
|
|
|
fillRule = nsSVGUtils::ToFillRule(StyleSVG()->mClipRule);
|
2007-12-04 08:11:49 +03:00
|
|
|
} else {
|
2011-07-08 17:20:14 +04:00
|
|
|
hitTestFlags = GetHitTestFlags();
|
2014-08-07 11:09:31 +04:00
|
|
|
if (!hitTestFlags) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2014-07-06 00:53:04 +04:00
|
|
|
}
|
2014-08-07 11:09:31 +04:00
|
|
|
if (hitTestFlags & SVG_HIT_TEST_CHECK_MRECT) {
|
|
|
|
gfxRect rect =
|
|
|
|
nsLayoutUtils::RectToGfxRect(mRect, PresContext()->AppUnitsPerCSSPixel());
|
|
|
|
if (!rect.Contains(aPoint)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
2014-10-11 12:24:44 +04:00
|
|
|
fillRule = nsSVGUtils::ToFillRule(StyleSVG()->mFillRule);
|
2007-12-04 08:11:49 +03:00
|
|
|
}
|
2006-06-09 22:08:33 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isHit = false;
|
2006-06-20 21:01:09 +04:00
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryElement* content =
|
2017-08-27 01:58:38 +03:00
|
|
|
static_cast<SVGGeometryElement*>(GetContent());
|
2014-07-06 00:53:04 +04:00
|
|
|
|
|
|
|
// Using ScreenReferenceDrawTarget() opens us to Moz2D backend specific hit-
|
|
|
|
// testing bugs. Maybe we should use a BackendType::CAIRO DT for hit-testing
|
|
|
|
// so that we get more consistent/backwards compatible results?
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> drawTarget =
|
2014-07-06 00:53:04 +04:00
|
|
|
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Path> path = content->GetOrBuildPath(*drawTarget, fillRule);
|
2014-07-06 00:53:04 +04:00
|
|
|
if (!path) {
|
|
|
|
return nullptr; // no path, so we don't paint anything that can be hit
|
|
|
|
}
|
2006-06-20 21:01:09 +04:00
|
|
|
|
2014-07-06 00:53:04 +04:00
|
|
|
if (hitTestFlags & SVG_HIT_TEST_FILL) {
|
2014-08-07 11:09:31 +04:00
|
|
|
isHit = path->ContainsPoint(ToPoint(aPoint), Matrix());
|
2014-07-06 00:53:04 +04:00
|
|
|
}
|
2011-07-08 17:20:14 +04:00
|
|
|
if (!isHit && (hitTestFlags & SVG_HIT_TEST_STROKE)) {
|
2014-08-07 11:09:31 +04:00
|
|
|
Point point = ToPoint(aPoint);
|
2014-07-06 00:53:04 +04:00
|
|
|
SVGContentUtils::AutoStrokeOptions stroke;
|
|
|
|
SVGContentUtils::GetStrokeOptions(&stroke, content, StyleContext(), nullptr);
|
2014-09-30 21:08:14 +04:00
|
|
|
gfxMatrix userToOuterSVG;
|
|
|
|
if (nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
|
2014-07-06 00:53:04 +04:00
|
|
|
// We need to transform the path back into the appropriate ancestor
|
|
|
|
// coordinate system in order for non-scaled stroke to be correct.
|
|
|
|
// Naturally we also need to transform the point into the same
|
|
|
|
// coordinate system in order to hit-test against the path.
|
2016-09-08 19:26:03 +03:00
|
|
|
point = ToMatrix(userToOuterSVG).TransformPoint(point);
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<PathBuilder> builder =
|
2014-09-30 21:08:14 +04:00
|
|
|
path->TransformedCopyToBuilder(ToMatrix(userToOuterSVG), fillRule);
|
2014-07-06 00:53:04 +04:00
|
|
|
path = builder->Finish();
|
|
|
|
}
|
2014-08-07 11:09:31 +04:00
|
|
|
isHit = path->StrokeContainsPoint(stroke, point, Matrix());
|
2006-08-07 20:41:58 +04:00
|
|
|
}
|
2006-06-20 21:01:09 +04:00
|
|
|
|
2008-08-25 13:23:54 +04:00
|
|
|
if (isHit && nsSVGUtils::HitTestClip(this, aPoint))
|
|
|
|
return this;
|
2006-06-20 21:01:09 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
}
|
|
|
|
|
2012-03-20 16:15:53 +04:00
|
|
|
void
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::ReflowSVG()
|
2006-06-09 22:08:33 +04:00
|
|
|
{
|
2012-07-22 04:01:44 +04:00
|
|
|
NS_ASSERTION(nsSVGUtils::OuterSVGIsCallingReflowSVG(this),
|
|
|
|
"This call is probably a wasteful mistake");
|
2012-03-20 16:15:53 +04:00
|
|
|
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(!(GetStateBits() & NS_FRAME_IS_NONDISPLAY),
|
|
|
|
"ReflowSVG mechanism not designed for this");
|
2012-03-20 16:15:53 +04:00
|
|
|
|
2012-07-22 04:01:44 +04:00
|
|
|
if (!nsSVGUtils::NeedsReflowSVG(this)) {
|
2012-03-20 16:15:53 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t flags = nsSVGUtils::eBBoxIncludeFill |
|
2012-07-09 15:55:16 +04:00
|
|
|
nsSVGUtils::eBBoxIncludeStroke |
|
|
|
|
nsSVGUtils::eBBoxIncludeMarkers;
|
2012-07-11 15:25:27 +04:00
|
|
|
// Our "visual" overflow rect needs to be valid for building display lists
|
|
|
|
// for hit testing, which means that for certain values of 'pointer-events'
|
|
|
|
// it needs to include the geometry of the fill or stroke even when the fill/
|
|
|
|
// stroke don't actually render (e.g. when stroke="none" or
|
|
|
|
// stroke-opacity="0"). GetHitTestFlags() accounts for 'pointer-events'.
|
2012-08-22 19:56:38 +04:00
|
|
|
uint16_t hitTestFlags = GetHitTestFlags();
|
2012-07-11 15:25:27 +04:00
|
|
|
if ((hitTestFlags & SVG_HIT_TEST_FILL)) {
|
|
|
|
flags |= nsSVGUtils::eBBoxIncludeFillGeometry;
|
|
|
|
}
|
|
|
|
if ((hitTestFlags & SVG_HIT_TEST_STROKE)) {
|
|
|
|
flags |= nsSVGUtils::eBBoxIncludeStrokeGeometry;
|
2012-07-09 15:55:16 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2014-10-04 15:13:30 +04:00
|
|
|
gfxRect extent = GetBBoxContribution(Matrix(), flags).ToThebesRect();
|
2012-02-10 16:33:18 +04:00
|
|
|
mRect = nsLayoutUtils::RoundGfxRectToAppRect(extent,
|
2012-02-17 10:07:51 +04:00
|
|
|
PresContext()->AppUnitsPerCSSPixel());
|
2012-02-10 16:33:49 +04:00
|
|
|
|
2012-05-17 08:05:09 +04:00
|
|
|
if (mState & NS_FRAME_FIRST_REFLOW) {
|
|
|
|
// Make sure we have our filter property (if any) before calling
|
|
|
|
// FinishAndStoreOverflow (subsequent filter changes are handled off
|
|
|
|
// nsChangeHint_UpdateEffects):
|
2017-08-30 17:58:31 +03:00
|
|
|
SVGObserverUtils::UpdateEffects(this);
|
2012-05-17 08:05:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsRect overflow = nsRect(nsPoint(0,0), mRect.Size());
|
|
|
|
nsOverflowAreas overflowAreas(overflow, overflow);
|
|
|
|
FinishAndStoreOverflow(overflowAreas, mRect.Size());
|
|
|
|
|
2017-08-24 12:55:28 +03:00
|
|
|
RemoveStateBits(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
2012-03-20 16:15:53 +04:00
|
|
|
|
2012-11-28 14:34:58 +04:00
|
|
|
// Invalidate, but only if this is not our first reflow (since if it is our
|
|
|
|
// first reflow then we haven't had our first paint yet).
|
|
|
|
if (!(GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
|
|
|
InvalidateFrame();
|
2012-03-20 16:15:53 +04:00
|
|
|
}
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
}
|
|
|
|
|
2008-01-25 12:27:03 +03:00
|
|
|
void
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::NotifySVGChanged(uint32_t aFlags)
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED),
|
|
|
|
"Invalidation logic may need adjusting");
|
2012-03-11 19:53:36 +04:00
|
|
|
|
2013-05-08 21:13:11 +04:00
|
|
|
// Changes to our ancestors may affect how we render when we are rendered as
|
|
|
|
// part of our ancestor (specifically, if our coordinate context changes size
|
|
|
|
// and we have percentage lengths defining our geometry, then we need to be
|
|
|
|
// reflowed). However, ancestor changes cannot affect how we render when we
|
|
|
|
// are rendered as part of any rendering observers that we may have.
|
|
|
|
// Therefore no need to notify rendering observers here.
|
|
|
|
|
2013-05-23 18:30:14 +04:00
|
|
|
// Don't try to be too smart trying to avoid the ScheduleReflowSVG calls
|
|
|
|
// for the stroke properties examined below. Checking HasStroke() is not
|
|
|
|
// enough, since what we care about is whether we include the stroke in our
|
|
|
|
// overflow rects or not, and we sometimes deliberately include stroke
|
|
|
|
// when it's not visible. See the complexities of GetBBoxContribution.
|
|
|
|
|
|
|
|
if (aFlags & COORD_CONTEXT_CHANGED) {
|
|
|
|
// Stroke currently contributes to our mRect, which is why we have to take
|
|
|
|
// account of stroke-width here. Note that we do not need to take account
|
|
|
|
// of stroke-dashoffset since, although that can have a percentage value
|
|
|
|
// that is resolved against our coordinate context, it does not affect our
|
|
|
|
// mRect.
|
2017-08-27 01:58:38 +03:00
|
|
|
if (static_cast<SVGGeometryElement*>(GetContent())->GeometryDependsOnCoordCtx() ||
|
2013-05-23 18:30:14 +04:00
|
|
|
StyleSVG()->mStrokeWidth.HasPercent()) {
|
2017-08-27 01:58:38 +03:00
|
|
|
static_cast<SVGGeometryElement*>(GetContent())->ClearAnyCachedPath();
|
2013-05-23 18:30:14 +04:00
|
|
|
nsSVGUtils::ScheduleReflowSVG(this);
|
|
|
|
}
|
2013-05-08 21:13:11 +04:00
|
|
|
}
|
2013-05-23 18:30:14 +04:00
|
|
|
|
2014-12-17 16:58:31 +03:00
|
|
|
if ((aFlags & TRANSFORM_CHANGED) && StyleSVGReset()->HasNonScalingStroke()) {
|
2013-05-23 18:30:14 +04:00
|
|
|
// Stroke currently contributes to our mRect, and our stroke depends on
|
|
|
|
// the transform to our outer-<svg> if |vector-effect:non-scaling-stroke|.
|
|
|
|
nsSVGUtils::ScheduleReflowSVG(this);
|
2017-07-06 15:00:35 +03:00
|
|
|
}
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
}
|
|
|
|
|
2012-04-16 12:23:48 +04:00
|
|
|
SVGBBox
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::GetBBoxContribution(const Matrix &aToBBoxUserspace,
|
|
|
|
uint32_t aFlags)
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
{
|
2012-04-16 12:23:48 +04:00
|
|
|
SVGBBox bbox;
|
|
|
|
|
2009-04-29 08:31:34 +04:00
|
|
|
if (aToBBoxUserspace.IsSingular()) {
|
|
|
|
// XXX ReportToConsole
|
2012-04-16 12:23:48 +04:00
|
|
|
return bbox;
|
2009-04-29 08:31:34 +04:00
|
|
|
}
|
2011-09-30 13:25:37 +04:00
|
|
|
|
2017-02-27 14:43:16 +03:00
|
|
|
if ((aFlags & nsSVGUtils::eForGetClientRects) &&
|
|
|
|
aToBBoxUserspace.PreservesAxisAlignedRectangles()) {
|
|
|
|
Rect rect = NSRectToRect(mRect, PresContext()->AppUnitsPerCSSPixel());
|
|
|
|
bbox = aToBBoxUserspace.TransformBounds(rect);
|
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryElement* element =
|
2017-08-27 01:58:38 +03:00
|
|
|
static_cast<SVGGeometryElement*>(GetContent());
|
2014-10-03 12:50:43 +04:00
|
|
|
|
2014-10-26 21:00:03 +03:00
|
|
|
bool getFill = (aFlags & nsSVGUtils::eBBoxIncludeFillGeometry) ||
|
|
|
|
((aFlags & nsSVGUtils::eBBoxIncludeFill) &&
|
2016-10-11 09:56:11 +03:00
|
|
|
StyleSVG()->mFill.Type() != eStyleSVGPaintType_None);
|
2014-10-26 21:00:03 +03:00
|
|
|
|
|
|
|
bool getStroke = (aFlags & nsSVGUtils::eBBoxIncludeStrokeGeometry) ||
|
|
|
|
((aFlags & nsSVGUtils::eBBoxIncludeStroke) &&
|
|
|
|
nsSVGUtils::HasStroke(this));
|
|
|
|
|
2015-09-01 07:17:00 +03:00
|
|
|
SVGContentUtils::AutoStrokeOptions strokeOptions;
|
|
|
|
if (getStroke) {
|
|
|
|
SVGContentUtils::GetStrokeOptions(&strokeOptions, element,
|
|
|
|
StyleContext(), nullptr,
|
|
|
|
SVGContentUtils::eIgnoreStrokeDashing);
|
|
|
|
} else {
|
|
|
|
// Override the default line width of 1.f so that when we call
|
|
|
|
// GetGeometryBounds below the result doesn't include stroke bounds.
|
2015-01-22 12:36:08 +03:00
|
|
|
strokeOptions.mLineWidth = 0.f;
|
2015-09-01 07:17:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Rect simpleBounds;
|
|
|
|
bool gotSimpleBounds = false;
|
|
|
|
gfxMatrix userToOuterSVG;
|
|
|
|
if (getStroke &&
|
|
|
|
nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
|
|
|
|
Matrix moz2dUserToOuterSVG = ToMatrix(userToOuterSVG);
|
2015-09-30 09:05:00 +03:00
|
|
|
if (moz2dUserToOuterSVG.IsSingular()) {
|
|
|
|
return bbox;
|
|
|
|
}
|
2015-09-01 07:17:00 +03:00
|
|
|
gotSimpleBounds = element->GetGeometryBounds(&simpleBounds,
|
|
|
|
strokeOptions,
|
|
|
|
aToBBoxUserspace,
|
|
|
|
&moz2dUserToOuterSVG);
|
|
|
|
} else {
|
2015-01-22 12:36:08 +03:00
|
|
|
gotSimpleBounds = element->GetGeometryBounds(&simpleBounds,
|
2015-02-03 21:36:32 +03:00
|
|
|
strokeOptions,
|
2014-10-26 21:00:03 +03:00
|
|
|
aToBBoxUserspace);
|
|
|
|
}
|
|
|
|
|
2015-09-01 07:17:00 +03:00
|
|
|
if (gotSimpleBounds) {
|
|
|
|
bbox = simpleBounds;
|
|
|
|
} else {
|
2014-10-26 21:00:03 +03:00
|
|
|
// Get the bounds using a Moz2D Path object (more expensive):
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> tmpDT;
|
2014-07-06 19:30:55 +04:00
|
|
|
#ifdef XP_WIN
|
2014-10-26 21:00:03 +03:00
|
|
|
// Unfortunately D2D backed DrawTarget produces bounds with rounding errors
|
|
|
|
// when whole number results are expected, even in the case of trivial
|
|
|
|
// calculations. To avoid that and meet the expectations of web content we
|
|
|
|
// have to use a CAIRO DrawTarget. The most efficient way to do that is to
|
|
|
|
// wrap the cached cairo_surface_t from ScreenReferenceSurface():
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxASurface> refSurf =
|
2014-10-26 21:00:03 +03:00
|
|
|
gfxPlatform::GetPlatform()->ScreenReferenceSurface();
|
|
|
|
tmpDT = gfxPlatform::GetPlatform()->
|
|
|
|
CreateDrawTargetForSurface(refSurf, IntSize(1, 1));
|
2014-07-06 19:30:55 +04:00
|
|
|
#else
|
2014-10-26 21:00:03 +03:00
|
|
|
tmpDT = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
|
2014-07-06 19:30:55 +04:00
|
|
|
#endif
|
2011-09-30 13:25:37 +04:00
|
|
|
|
2017-09-25 23:57:39 +03:00
|
|
|
FillRule fillRule = nsSVGUtils::ToFillRule(
|
|
|
|
(GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD)
|
|
|
|
? StyleSVG()->mClipRule
|
|
|
|
: StyleSVG()->mFillRule);
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Path> pathInUserSpace = element->GetOrBuildPath(*tmpDT, fillRule);
|
2014-10-26 21:00:03 +03:00
|
|
|
if (!pathInUserSpace) {
|
2014-10-03 12:50:43 +04:00
|
|
|
return bbox;
|
|
|
|
}
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Path> pathInBBoxSpace;
|
2014-10-26 21:00:03 +03:00
|
|
|
if (aToBBoxUserspace.IsIdentity()) {
|
|
|
|
pathInBBoxSpace = pathInUserSpace;
|
|
|
|
} else {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<PathBuilder> builder =
|
2014-10-26 21:00:03 +03:00
|
|
|
pathInUserSpace->TransformedCopyToBuilder(aToBBoxUserspace, fillRule);
|
|
|
|
pathInBBoxSpace = builder->Finish();
|
|
|
|
if (!pathInBBoxSpace) {
|
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
}
|
2011-09-30 13:25:37 +04:00
|
|
|
|
2014-10-26 21:00:03 +03:00
|
|
|
// Be careful when replacing the following logic to get the fill and stroke
|
|
|
|
// extents independently (instead of computing the stroke extents from the
|
|
|
|
// path extents). You may think that you can just use the stroke extents if
|
|
|
|
// there is both a fill and a stroke. In reality it's necessary to
|
|
|
|
// calculate both the fill and stroke extents, and take the union of the
|
|
|
|
// two. There are two reasons for this:
|
|
|
|
//
|
|
|
|
// # Due to stroke dashing, in certain cases the fill extents could
|
|
|
|
// actually extend outside the stroke extents.
|
|
|
|
// # If the stroke is very thin, cairo won't paint any stroke, and so the
|
|
|
|
// stroke bounds that it will return will be empty.
|
|
|
|
|
|
|
|
Rect pathBBoxExtents = pathInBBoxSpace->GetBounds();
|
|
|
|
if (!pathBBoxExtents.IsFinite()) {
|
|
|
|
// This can happen in the case that we only have a move-to command in the
|
|
|
|
// path commands, in which case we know nothing gets rendered.
|
|
|
|
return bbox;
|
|
|
|
}
|
2011-09-30 13:25:37 +04:00
|
|
|
|
2014-10-26 21:00:03 +03:00
|
|
|
// Account for fill:
|
|
|
|
if (getFill) {
|
|
|
|
bbox = pathBBoxExtents;
|
|
|
|
}
|
2011-09-30 13:25:37 +04:00
|
|
|
|
2014-10-26 21:00:03 +03:00
|
|
|
// Account for stroke:
|
|
|
|
if (getStroke) {
|
2014-10-03 12:50:43 +04:00
|
|
|
#if 0
|
2014-10-26 21:00:03 +03:00
|
|
|
// This disabled code is how we would calculate the stroke bounds using
|
|
|
|
// Moz2D Path::GetStrokedBounds(). Unfortunately at the time of writing
|
|
|
|
// it there are two problems that prevent us from using it.
|
|
|
|
//
|
|
|
|
// First, it seems that some of the Moz2D backends are really dumb. Not
|
|
|
|
// only do some GetStrokeOptions() implementations sometimes
|
|
|
|
// significantly overestimate the stroke bounds, but if an argument is
|
|
|
|
// passed for the aTransform parameter then they just return bounds-of-
|
|
|
|
// transformed-bounds. These two things combined can lead the bounds to
|
|
|
|
// be unacceptably oversized, leading to massive over-invalidation.
|
|
|
|
//
|
|
|
|
// Second, the way we account for non-scaling-stroke by transforming the
|
|
|
|
// path using the transform to the outer-<svg> element is not compatible
|
2016-12-18 14:11:47 +03:00
|
|
|
// with the way that SVGGeometryFrame::Reflow() inserts a scale
|
2014-10-26 21:00:03 +03:00
|
|
|
// into aToBBoxUserspace and then scales the bounds that we return.
|
|
|
|
SVGContentUtils::AutoStrokeOptions strokeOptions;
|
|
|
|
SVGContentUtils::GetStrokeOptions(&strokeOptions, element,
|
|
|
|
StyleContext(), nullptr,
|
|
|
|
SVGContentUtils::eIgnoreStrokeDashing);
|
|
|
|
Rect strokeBBoxExtents;
|
|
|
|
gfxMatrix userToOuterSVG;
|
|
|
|
if (nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
|
|
|
|
Matrix outerSVGToUser = ToMatrix(userToOuterSVG);
|
|
|
|
outerSVGToUser.Invert();
|
|
|
|
Matrix outerSVGToBBox = aToBBoxUserspace * outerSVGToUser;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<PathBuilder> builder =
|
2014-10-26 21:00:03 +03:00
|
|
|
pathInUserSpace->TransformedCopyToBuilder(ToMatrix(userToOuterSVG));
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Path> pathInOuterSVGSpace = builder->Finish();
|
2014-10-26 21:00:03 +03:00
|
|
|
strokeBBoxExtents =
|
|
|
|
pathInOuterSVGSpace->GetStrokedBounds(strokeOptions, outerSVGToBBox);
|
|
|
|
} else {
|
|
|
|
strokeBBoxExtents =
|
|
|
|
pathInUserSpace->GetStrokedBounds(strokeOptions, aToBBoxUserspace);
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(strokeBBoxExtents.IsFinite(), "bbox is about to go bad");
|
|
|
|
bbox.UnionEdges(strokeBBoxExtents);
|
2014-10-03 12:50:43 +04:00
|
|
|
#else
|
|
|
|
// For now we just use nsSVGUtils::PathExtentsToMaxStrokeExtents:
|
2014-10-26 21:00:03 +03:00
|
|
|
gfxRect strokeBBoxExtents =
|
|
|
|
nsSVGUtils::PathExtentsToMaxStrokeExtents(ThebesRect(pathBBoxExtents),
|
|
|
|
this,
|
|
|
|
ThebesMatrix(aToBBoxUserspace));
|
|
|
|
MOZ_ASSERT(ToRect(strokeBBoxExtents).IsFinite(), "bbox is about to go bad");
|
|
|
|
bbox.UnionEdges(strokeBBoxExtents);
|
2014-10-03 12:50:43 +04:00
|
|
|
#endif
|
2014-10-26 21:00:03 +03:00
|
|
|
}
|
2011-09-30 13:25:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Account for markers:
|
|
|
|
if ((aFlags & nsSVGUtils::eBBoxIncludeMarkers) != 0 &&
|
2017-08-27 01:58:38 +03:00
|
|
|
static_cast<SVGGeometryElement*>(GetContent())->IsMarkable()) {
|
2011-09-30 13:25:37 +04:00
|
|
|
|
2012-08-10 15:13:43 +04:00
|
|
|
float strokeWidth = nsSVGUtils::GetStrokeWidth(this);
|
2011-09-30 13:25:37 +04:00
|
|
|
MarkerProperties properties = GetMarkerProperties(this);
|
|
|
|
|
|
|
|
if (properties.MarkersExist()) {
|
|
|
|
nsTArray<nsSVGMark> marks;
|
2017-08-27 01:58:38 +03:00
|
|
|
static_cast<SVGGeometryElement*>(GetContent())->GetMarkPoints(&marks);
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t num = marks.Length();
|
2011-09-30 13:25:37 +04:00
|
|
|
|
2013-07-12 10:39:38 +04:00
|
|
|
// These are in the same order as the nsSVGMark::Type constants.
|
|
|
|
nsSVGMarkerFrame* markerFrames[] = {
|
|
|
|
properties.GetMarkerStartFrame(),
|
|
|
|
properties.GetMarkerMidFrame(),
|
|
|
|
properties.GetMarkerEndFrame(),
|
|
|
|
};
|
2016-08-23 18:24:54 +03:00
|
|
|
static_assert(MOZ_ARRAY_LENGTH(markerFrames) == nsSVGMark::eTypeCount,
|
|
|
|
"Number of Marker frames should be equal to eTypeCount");
|
2013-07-12 10:39:38 +04:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < num; i++) {
|
2017-06-08 08:17:07 +03:00
|
|
|
const nsSVGMark& mark = marks[i];
|
2013-07-12 10:39:38 +04:00
|
|
|
nsSVGMarkerFrame* frame = markerFrames[mark.type];
|
2011-09-30 13:25:37 +04:00
|
|
|
if (frame) {
|
2012-04-16 12:23:48 +04:00
|
|
|
SVGBBox mbbox =
|
2011-09-30 13:25:37 +04:00
|
|
|
frame->GetMarkBBoxContribution(aToBBoxUserspace, aFlags, this,
|
2017-06-08 08:17:07 +03:00
|
|
|
mark, strokeWidth);
|
2014-10-03 12:50:43 +04:00
|
|
|
MOZ_ASSERT(mbbox.IsFinite(), "bbox is about to go bad");
|
2012-04-16 12:23:48 +04:00
|
|
|
bbox.UnionEdges(mbbox);
|
2011-09-30 13:25:37 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bbox;
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-12-18 14:11:47 +03:00
|
|
|
// SVGGeometryFrame methods:
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
|
2009-04-29 08:31:34 +04:00
|
|
|
gfxMatrix
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::GetCanvasTM()
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
{
|
2014-05-25 02:20:41 +04:00
|
|
|
NS_ASSERTION(GetParent(), "null parent");
|
2004-08-05 13:01:13 +04:00
|
|
|
|
2014-05-25 02:20:41 +04:00
|
|
|
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(GetParent());
|
2017-08-27 01:58:38 +03:00
|
|
|
SVGGraphicsElement *content = static_cast<SVGGraphicsElement*>(GetContent());
|
2006-04-20 19:24:51 +04:00
|
|
|
|
2014-09-08 15:28:50 +04:00
|
|
|
return content->PrependLocalTransformsTo(parent->GetCanvasTM());
|
Landing of SVG_20020806_BRANCH, Bug 182533. Refactoring of SVG backend, new GDI+ and Libart rendering
backends, text support on Windows (GDI+), rudimentary text support on Linux (libart/freetype2), presentation
attributes, lots of bug fixes (see bug 182533 for dependency list).
Not part of default build; code is #ifdef'ed out.
r=sicking, sr=jst for dom and htmlparser changes
r=bsmedberg, sr=tor for config changes
r=dbaron, sr=bzbarsky for content and layout changes
r=tor, sr=bzbarsky for gfx changes
2004-02-07 15:39:26 +03:00
|
|
|
}
|
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::MarkerProperties
|
|
|
|
SVGGeometryFrame::GetMarkerProperties(SVGGeometryFrame *aFrame)
|
2007-07-24 13:05:37 +04:00
|
|
|
{
|
2008-10-10 17:14:05 +04:00
|
|
|
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
|
2007-07-24 13:05:37 +04:00
|
|
|
|
2008-10-10 17:14:05 +04:00
|
|
|
MarkerProperties result;
|
2016-06-23 21:11:51 +03:00
|
|
|
nsCOMPtr<nsIURI> markerURL =
|
2017-08-30 17:58:31 +03:00
|
|
|
SVGObserverUtils::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerStart);
|
2010-03-29 05:46:55 +04:00
|
|
|
result.mMarkerStart =
|
2017-08-30 17:58:31 +03:00
|
|
|
SVGObserverUtils::GetMarkerProperty(markerURL, aFrame,
|
|
|
|
SVGObserverUtils::MarkerBeginProperty());
|
2016-06-23 21:11:51 +03:00
|
|
|
|
2017-08-30 17:58:31 +03:00
|
|
|
markerURL = SVGObserverUtils::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerMid);
|
2010-03-29 05:46:55 +04:00
|
|
|
result.mMarkerMid =
|
2017-08-30 17:58:31 +03:00
|
|
|
SVGObserverUtils::GetMarkerProperty(markerURL, aFrame,
|
|
|
|
SVGObserverUtils::MarkerMiddleProperty());
|
2016-06-23 21:11:51 +03:00
|
|
|
|
2017-08-30 17:58:31 +03:00
|
|
|
markerURL = SVGObserverUtils::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerEnd);
|
2010-03-29 05:46:55 +04:00
|
|
|
result.mMarkerEnd =
|
2017-08-30 17:58:31 +03:00
|
|
|
SVGObserverUtils::GetMarkerProperty(markerURL, aFrame,
|
|
|
|
SVGObserverUtils::MarkerEndProperty());
|
2008-10-10 17:14:05 +04:00
|
|
|
return result;
|
2007-07-24 13:05:37 +04:00
|
|
|
}
|
|
|
|
|
2008-10-10 17:14:05 +04:00
|
|
|
nsSVGMarkerFrame *
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::MarkerProperties::GetMarkerStartFrame()
|
2007-07-24 13:05:37 +04:00
|
|
|
{
|
2008-10-10 17:14:05 +04:00
|
|
|
if (!mMarkerStart)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2017-04-30 18:30:08 +03:00
|
|
|
return static_cast<nsSVGMarkerFrame*>(
|
2017-05-01 20:32:52 +03:00
|
|
|
mMarkerStart->GetReferencedFrame(LayoutFrameType::SVGMarker, nullptr));
|
2007-07-24 13:05:37 +04:00
|
|
|
}
|
|
|
|
|
2008-10-10 17:14:05 +04:00
|
|
|
nsSVGMarkerFrame *
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::MarkerProperties::GetMarkerMidFrame()
|
2007-07-24 13:05:37 +04:00
|
|
|
{
|
2008-10-10 17:14:05 +04:00
|
|
|
if (!mMarkerMid)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2017-04-30 18:30:08 +03:00
|
|
|
return static_cast<nsSVGMarkerFrame*>(
|
2017-05-01 20:32:52 +03:00
|
|
|
mMarkerMid->GetReferencedFrame(LayoutFrameType::SVGMarker, nullptr));
|
2008-10-10 17:14:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsSVGMarkerFrame *
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::MarkerProperties::GetMarkerEndFrame()
|
2008-10-10 17:14:05 +04:00
|
|
|
{
|
|
|
|
if (!mMarkerEnd)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2017-04-30 18:30:08 +03:00
|
|
|
return static_cast<nsSVGMarkerFrame*>(
|
2017-05-01 20:32:52 +03:00
|
|
|
mMarkerEnd->GetReferencedFrame(LayoutFrameType::SVGMarker, nullptr));
|
2007-07-24 13:05:37 +04:00
|
|
|
}
|
|
|
|
|
2017-05-18 23:03:41 +03:00
|
|
|
void
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::Render(gfxContext* aContext,
|
|
|
|
uint32_t aRenderComponents,
|
2017-03-24 22:19:18 +03:00
|
|
|
const gfxMatrix& aNewTransform,
|
2017-05-18 23:03:41 +03:00
|
|
|
imgDrawingParams& aImgParams)
|
2006-06-20 21:01:09 +04:00
|
|
|
{
|
2014-09-30 21:08:13 +04:00
|
|
|
MOZ_ASSERT(!aNewTransform.IsSingular());
|
2006-06-20 21:01:09 +04:00
|
|
|
|
2014-09-30 21:08:13 +04:00
|
|
|
DrawTarget* drawTarget = aContext->GetDrawTarget();
|
|
|
|
|
2014-09-29 17:26:15 +04:00
|
|
|
FillRule fillRule =
|
2014-10-11 12:24:44 +04:00
|
|
|
nsSVGUtils::ToFillRule((GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) ?
|
|
|
|
StyleSVG()->mClipRule : StyleSVG()->mFillRule);
|
2014-09-29 17:26:15 +04:00
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryElement* element =
|
2017-08-27 01:58:38 +03:00
|
|
|
static_cast<SVGGeometryElement*>(GetContent());
|
2014-09-29 17:26:15 +04:00
|
|
|
|
2014-09-30 21:08:13 +04:00
|
|
|
AntialiasMode aaMode =
|
|
|
|
(StyleSVG()->mShapeRendering == NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED ||
|
|
|
|
StyleSVG()->mShapeRendering == NS_STYLE_SHAPE_RENDERING_CRISPEDGES) ?
|
|
|
|
AntialiasMode::NONE : AntialiasMode::SUBPIXEL;
|
2006-06-20 21:01:09 +04:00
|
|
|
|
2014-09-30 21:08:13 +04:00
|
|
|
// We wait as late as possible before setting the transform so that we don't
|
|
|
|
// set it unnecessarily if we return early (it's an expensive operation for
|
|
|
|
// some backends).
|
|
|
|
gfxContextMatrixAutoSaveRestore autoRestoreTransform(aContext);
|
2017-11-11 05:14:09 +03:00
|
|
|
aContext->SetMatrixDouble(aNewTransform);
|
2014-09-29 17:26:15 +04:00
|
|
|
|
2014-10-11 12:24:44 +04:00
|
|
|
if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
|
2014-10-22 15:29:05 +04:00
|
|
|
// We don't complicate this code with GetAsSimplePath since the cost of
|
|
|
|
// masking will dwarf Path creation overhead anyway.
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Path> path = element->GetOrBuildPath(*drawTarget, fillRule);
|
2014-10-22 15:29:05 +04:00
|
|
|
if (path) {
|
|
|
|
ColorPattern white(ToDeviceColor(Color(1.0f, 1.0f, 1.0f, 1.0f)));
|
|
|
|
drawTarget->Fill(path, white,
|
|
|
|
DrawOptions(1.0f, CompositionOp::OP_OVER, aaMode));
|
|
|
|
}
|
2017-05-18 23:03:41 +03:00
|
|
|
return;
|
2006-06-20 21:01:09 +04:00
|
|
|
}
|
|
|
|
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryElement::SimplePath simplePath;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Path> path;
|
2014-10-22 15:29:05 +04:00
|
|
|
|
|
|
|
element->GetAsSimplePath(&simplePath);
|
|
|
|
if (!simplePath.IsPath()) {
|
|
|
|
path = element->GetOrBuildPath(*drawTarget, fillRule);
|
|
|
|
if (!path) {
|
2017-05-18 23:03:41 +03:00
|
|
|
return;
|
2014-10-22 15:29:05 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-27 01:58:38 +03:00
|
|
|
SVGContextPaint* contextPaint = SVGContextPaint::GetContextPaint(GetContent());
|
2012-09-06 08:58:46 +04:00
|
|
|
|
2014-09-30 21:08:13 +04:00
|
|
|
if (aRenderComponents & eRenderFill) {
|
2014-09-29 17:26:15 +04:00
|
|
|
GeneralPattern fillPattern;
|
2017-05-18 23:03:41 +03:00
|
|
|
nsSVGUtils::MakeFillPatternFor(this, aContext, &fillPattern, aImgParams,
|
|
|
|
contextPaint);
|
2017-03-21 05:12:23 +03:00
|
|
|
|
2014-09-29 17:26:15 +04:00
|
|
|
if (fillPattern.GetPattern()) {
|
2014-10-22 15:29:05 +04:00
|
|
|
DrawOptions drawOptions(1.0f, CompositionOp::OP_OVER, aaMode);
|
|
|
|
if (simplePath.IsRect()) {
|
|
|
|
drawTarget->FillRect(simplePath.AsRect(), fillPattern, drawOptions);
|
|
|
|
} else if (path) {
|
|
|
|
drawTarget->Fill(path, fillPattern, drawOptions);
|
|
|
|
}
|
2014-09-29 17:12:06 +04:00
|
|
|
}
|
2006-06-20 21:01:09 +04:00
|
|
|
}
|
|
|
|
|
2013-01-13 03:27:53 +04:00
|
|
|
if ((aRenderComponents & eRenderStroke) &&
|
2014-09-29 17:12:07 +04:00
|
|
|
nsSVGUtils::HasStroke(this, contextPaint)) {
|
2014-09-30 21:08:13 +04:00
|
|
|
// Account for vector-effect:non-scaling-stroke:
|
2014-09-30 21:08:14 +04:00
|
|
|
gfxMatrix userToOuterSVG;
|
|
|
|
if (nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
|
2014-10-22 15:29:05 +04:00
|
|
|
// A simple Rect can't be transformed with rotate/skew, so let's switch
|
|
|
|
// to using a real path:
|
|
|
|
if (!path) {
|
|
|
|
path = element->GetOrBuildPath(*drawTarget, fillRule);
|
|
|
|
if (!path) {
|
2017-05-18 23:03:41 +03:00
|
|
|
return;
|
2014-10-22 15:29:05 +04:00
|
|
|
}
|
|
|
|
simplePath.Reset();
|
|
|
|
}
|
2014-09-30 21:08:13 +04:00
|
|
|
// We need to transform the path back into the appropriate ancestor
|
|
|
|
// coordinate system, and paint it it that coordinate system, in order
|
|
|
|
// for non-scaled stroke to paint correctly.
|
2014-09-30 21:08:14 +04:00
|
|
|
gfxMatrix outerSVGToUser = userToOuterSVG;
|
|
|
|
outerSVGToUser.Invert();
|
|
|
|
aContext->Multiply(outerSVGToUser);
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<PathBuilder> builder =
|
2014-10-04 15:13:30 +04:00
|
|
|
path->TransformedCopyToBuilder(ToMatrix(userToOuterSVG), fillRule);
|
2014-09-30 21:08:13 +04:00
|
|
|
path = builder->Finish();
|
|
|
|
}
|
2014-09-29 17:26:15 +04:00
|
|
|
GeneralPattern strokePattern;
|
2017-05-18 23:03:41 +03:00
|
|
|
nsSVGUtils::MakeStrokePatternFor(this, aContext, &strokePattern,
|
|
|
|
aImgParams, contextPaint);
|
2017-03-21 05:12:23 +03:00
|
|
|
|
2014-09-29 17:26:15 +04:00
|
|
|
if (strokePattern.GetPattern()) {
|
2014-09-30 21:08:13 +04:00
|
|
|
SVGContentUtils::AutoStrokeOptions strokeOptions;
|
|
|
|
SVGContentUtils::GetStrokeOptions(&strokeOptions,
|
2017-08-27 01:58:38 +03:00
|
|
|
static_cast<nsSVGElement*>(GetContent()),
|
2014-09-30 21:08:13 +04:00
|
|
|
StyleContext(), contextPaint);
|
|
|
|
// GetStrokeOptions may set the line width to zero as an optimization
|
|
|
|
if (strokeOptions.mLineWidth <= 0) {
|
2017-05-18 23:03:41 +03:00
|
|
|
return;
|
2014-09-30 21:08:13 +04:00
|
|
|
}
|
2014-10-22 15:29:05 +04:00
|
|
|
DrawOptions drawOptions(1.0f, CompositionOp::OP_OVER, aaMode);
|
|
|
|
if (simplePath.IsRect()) {
|
|
|
|
drawTarget->StrokeRect(simplePath.AsRect(), strokePattern,
|
|
|
|
strokeOptions, drawOptions);
|
|
|
|
} else if (simplePath.IsLine()) {
|
|
|
|
drawTarget->StrokeLine(simplePath.Point1(), simplePath.Point2(),
|
|
|
|
strokePattern, strokeOptions, drawOptions);
|
|
|
|
} else {
|
|
|
|
drawTarget->Stroke(path, strokePattern, strokeOptions, drawOptions);
|
|
|
|
}
|
2014-09-29 17:12:07 +04:00
|
|
|
}
|
2006-06-20 21:01:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-18 23:03:41 +03:00
|
|
|
void
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::PaintMarkers(gfxContext& aContext,
|
2017-03-27 07:33:53 +03:00
|
|
|
const gfxMatrix& aTransform,
|
2017-05-18 23:03:41 +03:00
|
|
|
imgDrawingParams& aImgParams)
|
2013-01-13 03:27:53 +04:00
|
|
|
{
|
2017-08-27 01:58:38 +03:00
|
|
|
SVGContextPaint* contextPaint = SVGContextPaint::GetContextPaint(GetContent());
|
|
|
|
if (static_cast<SVGGeometryElement*>(GetContent())->IsMarkable()) {
|
2013-01-13 03:27:53 +04:00
|
|
|
MarkerProperties properties = GetMarkerProperties(this);
|
|
|
|
|
|
|
|
if (properties.MarkersExist()) {
|
2013-05-16 06:35:12 +04:00
|
|
|
float strokeWidth = nsSVGUtils::GetStrokeWidth(this, contextPaint);
|
2013-01-13 03:27:53 +04:00
|
|
|
|
|
|
|
nsTArray<nsSVGMark> marks;
|
2016-12-18 14:11:47 +03:00
|
|
|
static_cast<SVGGeometryElement*>
|
2017-08-27 01:58:38 +03:00
|
|
|
(GetContent())->GetMarkPoints(&marks);
|
2013-01-13 03:27:53 +04:00
|
|
|
|
|
|
|
uint32_t num = marks.Length();
|
|
|
|
if (num) {
|
2013-07-12 10:39:38 +04:00
|
|
|
// These are in the same order as the nsSVGMark::Type constants.
|
|
|
|
nsSVGMarkerFrame* markerFrames[] = {
|
|
|
|
properties.GetMarkerStartFrame(),
|
|
|
|
properties.GetMarkerMidFrame(),
|
|
|
|
properties.GetMarkerEndFrame(),
|
|
|
|
};
|
2016-08-23 18:24:54 +03:00
|
|
|
static_assert(MOZ_ARRAY_LENGTH(markerFrames) == nsSVGMark::eTypeCount,
|
|
|
|
"Number of Marker frames should be equal to eTypeCount");
|
2013-07-12 10:39:38 +04:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < num; i++) {
|
2017-06-08 08:17:07 +03:00
|
|
|
const nsSVGMark& mark = marks[i];
|
2013-07-12 10:39:38 +04:00
|
|
|
nsSVGMarkerFrame* frame = markerFrames[mark.type];
|
|
|
|
if (frame) {
|
2017-06-08 08:17:07 +03:00
|
|
|
frame->PaintMark(aContext, aTransform, this, mark, strokeWidth,
|
2017-05-18 23:03:41 +03:00
|
|
|
aImgParams);
|
2013-07-12 10:39:38 +04:00
|
|
|
}
|
2013-01-13 03:27:53 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-01-04 12:29:02 +04:00
|
|
|
|
|
|
|
uint16_t
|
2016-12-18 14:11:47 +03:00
|
|
|
SVGGeometryFrame::GetHitTestFlags()
|
2014-01-04 12:29:02 +04:00
|
|
|
{
|
|
|
|
return nsSVGUtils::GetGeometryHitTestFlags(this);
|
|
|
|
}
|
2016-12-18 14:11:47 +03:00
|
|
|
} // namespace mozilla
|