Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/layout/svg/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 8 kB image not shown  

Quelle  SVGMarkerFrame.cpp   Sprache: C

 
/* -*- 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 "SVGMarkerFrame.h"

// Keep others in (case-insensitive) order:
#include "gfxContext.h"
#include "mozilla/PresShell.h"
#include "mozilla/SVGContextPaint.h"
#include "mozilla/SVGGeometryFrame.h"
#include "mozilla/SVGObserverUtils.h"
#include "mozilla/SVGUtils.h"
#include "mozilla/dom/SVGGeometryElement.h"
#include "mozilla/dom/SVGMarkerElement.h"

using namespace mozilla::dom;
using namespace mozilla::gfx;
using namespace mozilla::image;

nsContainerFrame* NS_NewSVGMarkerFrame(mozilla::PresShell* aPresShell,
                                       mozilla::ComputedStyle* aStyle) {
  return new (aPresShell)
      mozilla::SVGMarkerFrame(aStyle, aPresShell->GetPresContext());
}

namespace mozilla {

NS_IMPL_FRAMEARENA_HELPERS(SVGMarkerFrame)

//----------------------------------------------------------------------
// nsIFrame methods:

nsresult SVGMarkerFrame::AttributeChanged(int32_t aNameSpaceID,
                                          nsAtom* aAttribute,
                                          int32_t aModType) {
  if (aNameSpaceID == kNameSpaceID_None &&
      (aAttribute == nsGkAtoms::markerUnits || aAttribute == nsGkAtoms::refX ||
       aAttribute == nsGkAtoms::refY || aAttribute == nsGkAtoms::markerWidth ||
       aAttribute == nsGkAtoms::markerHeight ||
       aAttribute == nsGkAtoms::orient ||
       aAttribute == nsGkAtoms::preserveAspectRatio ||
       aAttribute == nsGkAtoms::viewBox)) {
    SVGObserverUtils::InvalidateRenderingObservers(this);
  }

  return SVGContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
                                             aModType);
}

#ifdef DEBUG
void SVGMarkerFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
                          nsIFrame* aPrevInFlow) {
  NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::marker),
               "Content is not an SVG marker");

  SVGContainerFrame::Init(aContent, aParent, aPrevInFlow);
}
#endif /* DEBUG */

//----------------------------------------------------------------------
// SVGContainerFrame methods:

gfxMatrix SVGMarkerFrame::GetCanvasTM() {
  NS_ASSERTION(mMarkedFrame, "null SVGGeometry frame");

  if (mInUse2) {
    // We're going to be bailing drawing the marker, so return an identity.
    return gfxMatrix();
  }

  SVGMarkerElement* content = static_cast<SVGMarkerElement*>(GetContent());

  mInUse2 = true;
  gfxMatrix markedTM = mMarkedFrame->GetCanvasTM();
  mInUse2 = false;

  Matrix viewBoxTM = content->GetViewBoxTransform();

  return ThebesMatrix(viewBoxTM * mMarkerTM) * markedTM;
}

static nsIFrame* GetAnonymousChildFrame(nsIFrame* aFrame) {
  nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
  MOZ_ASSERT(kid && kid->IsSVGMarkerAnonChildFrame(),
             "expected to find anonymous child of marker frame");
  return kid;
}

void SVGMarkerFrame::PaintMark(gfxContext& aContext,
                               const gfxMatrix& aToMarkedFrameUserSpace,
                               SVGGeometryFrame* aMarkedFrame,
                               const SVGMark& aMark, float aStrokeWidth,
                               imgDrawingParams& aImgParams) {
  // If the flag is set when we get here, it means this marker frame
  // has already been used painting the current mark, and the document
  // has a marker reference loop.
  if (mInUse) {
    return;
  }

  AutoMarkerReferencer markerRef(this, aMarkedFrame);

  SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(GetContent());
  if (!marker->HasValidDimensions()) {
    return;
  }

  const SVGViewBox viewBox = marker->GetViewBox();

  if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) {
    // We must disable rendering if the viewBox width or height are zero.
    return;
  }

  Matrix viewBoxTM = marker->GetViewBoxTransform();

  mMarkerTM = marker->GetMarkerTransform(aStrokeWidth, aMark);

  gfxMatrix markTM = ThebesMatrix(viewBoxTM) * ThebesMatrix(mMarkerTM) *
                     aToMarkedFrameUserSpace;

  gfxClipAutoSaveRestore autoSaveClip(&aContext);
  if (StyleDisplay()->IsScrollableOverflow()) {
    gfxRect clipRect = SVGUtils::GetClipRectForFrame(
        this, viewBox.x, viewBox.y, viewBox.width, viewBox.height);
    autoSaveClip.TransformedClip(markTM, clipRect);
  }

  nsIFrame* kid = GetAnonymousChildFrame(this);
  ISVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
  // The CTM of each frame referencing us may be different.
  SVGFrame->NotifySVGChanged(ISVGDisplayableFrame::TRANSFORM_CHANGED);
  auto contextPaint = MakeRefPtr<SVGContextPaintImpl>();
  contextPaint->Init(aContext.GetDrawTarget(), aContext.CurrentMatrixDouble(),
                     aMarkedFrame, SVGContextPaint::GetContextPaint(marker),
                     aImgParams);
  AutoSetRestoreSVGContextPaint autoSetRestore(contextPaint,
                                               marker->OwnerDoc());
  SVGUtils::PaintFrameWithEffects(kid, aContext, markTM, aImgParams);
}

SVGBBox SVGMarkerFrame::GetMarkBBoxContribution(const Matrix& aToBBoxUserspace,
                                                uint32_t aFlags,
                                                SVGGeometryFrame* aMarkedFrame,
                                                const SVGMark& aMark,
                                                float aStrokeWidth) {
  SVGBBox bbox;

  // If the flag is set when we get here, it means this marker frame
  // has already been used in calculating the current mark bbox, and
  // the document has a marker reference loop.
  if (mInUse) {
    return bbox;
  }

  AutoMarkerReferencer markerRef(this, aMarkedFrame);

  SVGMarkerElement* content = static_cast<SVGMarkerElement*>(GetContent());
  if (!content->HasValidDimensions()) {
    return bbox;
  }

  const SVGViewBox viewBox = content->GetViewBox();

  if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) {
    return bbox;
  }

  mMarkerTM = content->GetMarkerTransform(aStrokeWidth, aMark);
  Matrix viewBoxTM = content->GetViewBoxTransform();

  Matrix tm = viewBoxTM * mMarkerTM * aToBBoxUserspace;

  ISVGDisplayableFrame* child = do_QueryFrame(GetAnonymousChildFrame(this));
  // When we're being called to obtain the invalidation area, we need to
  // pass down all the flags so that stroke is included. However, once DOM
  // getBBox() accepts flags, maybe we should strip some of those here?

  // We need to include zero width/height vertical/horizontal lines, so we have
  // to use UnionEdges.
  bbox.UnionEdges(child->GetBBoxContribution(tm, aFlags));

  return bbox;
}

void SVGMarkerFrame::SetParentCoordCtxProvider(SVGViewportElement* aContext) {
  SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(GetContent());
  marker->SetParentCoordCtxProvider(aContext);
}

void SVGMarkerFrame::AppendDirectlyOwnedAnonBoxes(
    nsTArray<OwnedAnonBox>& aResult) {
  aResult.AppendElement(OwnedAnonBox(GetAnonymousChildFrame(this)));
}

//----------------------------------------------------------------------
// helper class

SVGMarkerFrame::AutoMarkerReferencer::AutoMarkerReferencer(
    SVGMarkerFrame* aFrame, SVGGeometryFrame* aMarkedFrame)
    : mFrame(aFrame) {
  mFrame->mInUse = true;
  mFrame->mMarkedFrame = aMarkedFrame;

  SVGViewportElement* ctx =
      static_cast<SVGElement*>(aMarkedFrame->GetContent())->GetCtx();
  mFrame->SetParentCoordCtxProvider(ctx);
}

SVGMarkerFrame::AutoMarkerReferencer::~AutoMarkerReferencer() {
  mFrame->SetParentCoordCtxProvider(nullptr);

  mFrame->mMarkedFrame = nullptr;
  mFrame->mInUse = false;
}

}  // namespace mozilla

//----------------------------------------------------------------------
// Implementation of SVGMarkerAnonChildFrame

nsContainerFrame* NS_NewSVGMarkerAnonChildFrame(
    mozilla::PresShell* aPresShell, mozilla::ComputedStyle* aStyle) {
  return new (aPresShell)
      mozilla::SVGMarkerAnonChildFrame(aStyle, aPresShell->GetPresContext());
}

namespace mozilla {

NS_IMPL_FRAMEARENA_HELPERS(SVGMarkerAnonChildFrame)

#ifdef DEBUG
void SVGMarkerAnonChildFrame::Init(nsIContent* aContent,
                                   nsContainerFrame* aParent,
                                   nsIFrame* aPrevInFlow) {
  MOZ_ASSERT(aParent->IsSVGMarkerFrame(), "Unexpected parent");
  SVGDisplayContainerFrame::Init(aContent, aParent, aPrevInFlow);
}
#endif

}  // namespace mozilla

100%


¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.