2005-09-13 22:38:36 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is the Mozilla SVG project.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Scooter Morris.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2005
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Scooter Morris <scootermorris@comcast.net>
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
2007-01-30 00:06:41 +00:00
|
|
|
#include "nsGkAtoms.h"
|
2005-09-13 22:38:36 +00:00
|
|
|
#include "nsIDOMSVGAnimatedRect.h"
|
|
|
|
#include "nsIDOMSVGAnimTransformList.h"
|
2007-01-03 09:54:08 +00:00
|
|
|
#include "nsSVGTransformList.h"
|
2005-09-13 22:38:36 +00:00
|
|
|
#include "nsStyleContext.h"
|
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsISVGChildFrame.h"
|
|
|
|
#include "nsSVGMatrix.h"
|
|
|
|
#include "nsSVGRect.h"
|
|
|
|
#include "nsSVGUtils.h"
|
2008-10-01 00:51:05 +00:00
|
|
|
#include "nsSVGEffects.h"
|
2006-06-15 19:10:28 +00:00
|
|
|
#include "nsSVGOuterSVGFrame.h"
|
2006-04-14 15:09:39 +00:00
|
|
|
#include "nsSVGPatternElement.h"
|
2006-05-02 15:05:25 +00:00
|
|
|
#include "nsSVGGeometryFrame.h"
|
2006-05-05 16:06:43 +00:00
|
|
|
#include "nsSVGPatternFrame.h"
|
2011-01-16 07:36:34 +00:00
|
|
|
#include "nsSVGAnimatedTransformList.h"
|
2006-11-27 17:30:57 +00:00
|
|
|
#include "gfxContext.h"
|
2007-04-30 15:53:55 +00:00
|
|
|
#include "gfxPlatform.h"
|
|
|
|
#include "gfxPattern.h"
|
2009-07-23 08:35:59 +00:00
|
|
|
#include "gfxMatrix.h"
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2010-12-20 00:45:29 +00:00
|
|
|
using namespace mozilla;
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Helper classes
|
|
|
|
|
|
|
|
class nsSVGPatternFrame::AutoPatternReferencer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AutoPatternReferencer(nsSVGPatternFrame *aFrame)
|
|
|
|
: mFrame(aFrame)
|
|
|
|
{
|
|
|
|
// Reference loops should normally be detected in advance and handled, so
|
|
|
|
// we're not expecting to encounter them here
|
|
|
|
NS_ABORT_IF_FALSE(!mFrame->mLoopFlag, "Undetected reference loop!");
|
|
|
|
mFrame->mLoopFlag = PR_TRUE;
|
|
|
|
}
|
|
|
|
~AutoPatternReferencer() {
|
|
|
|
mFrame->mLoopFlag = PR_FALSE;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
nsSVGPatternFrame *mFrame;
|
|
|
|
};
|
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Implementation
|
|
|
|
|
2008-10-11 11:29:35 +00:00
|
|
|
nsSVGPatternFrame::nsSVGPatternFrame(nsStyleContext* aContext) :
|
2006-09-08 13:54:05 +00:00
|
|
|
nsSVGPatternFrameBase(aContext),
|
2010-08-13 13:32:15 +00:00
|
|
|
mLoopFlag(PR_FALSE),
|
2008-10-01 00:51:05 +00:00
|
|
|
mNoHRefURI(PR_FALSE)
|
2006-09-08 13:54:05 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-09-12 16:49:24 +00:00
|
|
|
NS_IMPL_FRAMEARENA_HELPERS(nsSVGPatternFrame)
|
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsIFrame methods:
|
|
|
|
|
2008-10-13 22:03:28 +00:00
|
|
|
/* virtual */ void
|
2008-10-26 10:11:34 +00:00
|
|
|
nsSVGPatternFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2008-10-01 00:51:05 +00:00
|
|
|
nsSVGEffects::InvalidateRenderingObservers(this);
|
2008-10-26 10:11:34 +00:00
|
|
|
nsSVGPatternFrameBase::DidSetStyleContext(aOldStyleContext);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2006-03-22 01:40:00 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSVGPatternFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
|
|
|
nsIAtom* aAttribute,
|
|
|
|
PRInt32 aModType)
|
|
|
|
{
|
|
|
|
if (aNameSpaceID == kNameSpaceID_None &&
|
|
|
|
(aAttribute == nsGkAtoms::patternUnits ||
|
|
|
|
aAttribute == nsGkAtoms::patternContentUnits ||
|
|
|
|
aAttribute == nsGkAtoms::patternTransform ||
|
|
|
|
aAttribute == nsGkAtoms::x ||
|
|
|
|
aAttribute == nsGkAtoms::y ||
|
|
|
|
aAttribute == nsGkAtoms::width ||
|
|
|
|
aAttribute == nsGkAtoms::height ||
|
|
|
|
aAttribute == nsGkAtoms::preserveAspectRatio ||
|
|
|
|
aAttribute == nsGkAtoms::viewBox)) {
|
2008-10-01 00:51:05 +00:00
|
|
|
nsSVGEffects::InvalidateRenderingObservers(this);
|
|
|
|
}
|
2006-03-22 01:40:00 +00:00
|
|
|
|
|
|
|
if (aNameSpaceID == kNameSpaceID_XLink &&
|
|
|
|
aAttribute == nsGkAtoms::href) {
|
2008-10-01 00:51:05 +00:00
|
|
|
// Blow away our reference, if any
|
2010-03-29 01:46:55 +00:00
|
|
|
Properties().Delete(nsSVGEffects::HrefProperty());
|
2008-10-01 00:51:05 +00:00
|
|
|
mNoHRefURI = PR_FALSE;
|
|
|
|
// And update whoever references us
|
|
|
|
nsSVGEffects::InvalidateRenderingObservers(this);
|
2006-03-22 01:40:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nsSVGPatternFrameBase::AttributeChanged(aNameSpaceID,
|
|
|
|
aAttribute, aModType);
|
|
|
|
}
|
|
|
|
|
2009-01-19 18:31:34 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSVGPatternFrame::Init(nsIContent* aContent,
|
|
|
|
nsIFrame* aParent,
|
|
|
|
nsIFrame* aPrevInFlow)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMSVGPatternElement> patternElement = do_QueryInterface(aContent);
|
|
|
|
NS_ASSERTION(patternElement, "Content is not an SVG pattern");
|
|
|
|
|
|
|
|
return nsSVGPatternFrameBase::Init(aContent, aParent, aPrevInFlow);
|
|
|
|
}
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
nsIAtom*
|
|
|
|
nsSVGPatternFrame::GetType() const
|
|
|
|
{
|
2006-12-26 17:47:52 +00:00
|
|
|
return nsGkAtoms::svgPatternFrame;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2006-06-01 15:31:15 +00:00
|
|
|
// nsSVGContainerFrame methods:
|
2005-09-13 22:38:36 +00:00
|
|
|
|
|
|
|
// If our GetCanvasTM is getting called, we
|
|
|
|
// need to return *our current* transformation
|
|
|
|
// matrix, which depends on our units parameters
|
|
|
|
// and X, Y, Width, and Height
|
2009-04-29 04:31:34 +00:00
|
|
|
gfxMatrix
|
2007-07-17 09:24:27 +00:00
|
|
|
nsSVGPatternFrame::GetCanvasTM()
|
|
|
|
{
|
2005-09-13 22:38:36 +00:00
|
|
|
if (mCTM) {
|
2009-04-29 04:31:34 +00:00
|
|
|
return nsSVGUtils::ConvertSVGMatrixToThebes(mCTM);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2009-04-29 04:31:34 +00:00
|
|
|
|
|
|
|
// Do we know our rendering parent?
|
|
|
|
if (mSource) {
|
|
|
|
// Yes, use it!
|
|
|
|
return mSource->GetCanvasTM();
|
|
|
|
}
|
|
|
|
|
|
|
|
// We get here when geometry in the <pattern> container is updated
|
|
|
|
return gfxMatrix();
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-05 16:06:43 +00:00
|
|
|
nsresult
|
2007-04-30 15:53:55 +00:00
|
|
|
nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
|
|
|
|
gfxMatrix* patternMatrix,
|
2010-07-01 16:40:30 +00:00
|
|
|
nsIFrame *aSource,
|
|
|
|
float aGraphicOpacity,
|
|
|
|
const gfxRect *aOverrideBounds)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* General approach:
|
|
|
|
* Set the content geometry stuff
|
2008-10-01 00:51:05 +00:00
|
|
|
* Calculate our bbox (using x,y,width,height & patternUnits &
|
2005-09-13 22:38:36 +00:00
|
|
|
* patternTransform)
|
|
|
|
* Create the surface
|
|
|
|
* Calculate the content transformation matrix
|
|
|
|
* Get our children (we may need to get them from another Pattern)
|
|
|
|
* Call SVGPaint on all of our children
|
|
|
|
* Return
|
|
|
|
*/
|
|
|
|
*surface = nsnull;
|
|
|
|
|
2009-10-26 19:37:31 +00:00
|
|
|
// Get the first child of the pattern data we will render
|
2005-09-13 22:38:36 +00:00
|
|
|
nsIFrame *firstKid;
|
|
|
|
if (NS_FAILED(GetPatternFirstChild(&firstKid)))
|
|
|
|
return NS_ERROR_FAILURE; // Either no kids or a bad reference
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the content geometry information. This is a little tricky --
|
|
|
|
* our parent is probably a <defs>, but we are rendering in the context
|
|
|
|
* of some geometry source. Our content geometry information needs to
|
|
|
|
* come from our rendering parent as opposed to our content parent. We
|
|
|
|
* get that information from aSource, which is passed to us from the
|
|
|
|
* backend renderer.
|
2006-04-04 20:40:27 +00:00
|
|
|
*
|
|
|
|
* There are three "geometries" that we need:
|
|
|
|
* 1) The bounding box for the pattern. We use this to get the
|
|
|
|
* width and height for the surface, and as the return to
|
|
|
|
* GetBBox.
|
|
|
|
* 2) The transformation matrix for the pattern. This is not *quite*
|
|
|
|
* the same as the canvas transformation matrix that we will
|
|
|
|
* provide to our rendering children since we "fudge" it a little
|
|
|
|
* to get the renderer to handle the translations correctly for us.
|
|
|
|
* 3) The CTM that we return to our children who make up the pattern.
|
2005-09-13 22:38:36 +00:00
|
|
|
*/
|
|
|
|
|
2006-04-04 20:40:27 +00:00
|
|
|
// Get all of the information we need from our "caller" -- i.e.
|
|
|
|
// the geometry that is being rendered with a pattern
|
2009-06-11 15:21:03 +00:00
|
|
|
gfxRect callerBBox;
|
2009-07-23 08:35:59 +00:00
|
|
|
gfxMatrix callerCTM;
|
|
|
|
if (NS_FAILED(GetTargetGeometry(&callerCTM,
|
2009-06-11 15:21:03 +00:00
|
|
|
&callerBBox,
|
2010-07-01 16:40:30 +00:00
|
|
|
aSource,
|
|
|
|
aOverrideBounds)))
|
2005-09-13 22:38:36 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2006-04-04 20:40:27 +00:00
|
|
|
// Construct the CTM that we will provide to our children when we
|
|
|
|
// render them into the tile.
|
2010-07-01 16:40:30 +00:00
|
|
|
gfxMatrix ctm = ConstructCTM(callerBBox, callerCTM, aSource);
|
2009-07-23 08:35:59 +00:00
|
|
|
if (ctm.IsSingular()) {
|
2005-09-13 22:38:36 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2009-07-23 08:35:59 +00:00
|
|
|
}
|
2009-10-26 19:37:31 +00:00
|
|
|
|
|
|
|
// Get the pattern we are going to render
|
|
|
|
nsSVGPatternFrame *patternFrame =
|
|
|
|
static_cast<nsSVGPatternFrame*>(firstKid->GetParent());
|
|
|
|
patternFrame->mCTM = NS_NewSVGMatrix(ctm);
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2006-04-04 20:40:27 +00:00
|
|
|
// Get the bounding box of the pattern. This will be used to determine
|
|
|
|
// the size of the surface, and will also be used to define the bounding
|
|
|
|
// box for the pattern tile.
|
2010-07-01 16:40:30 +00:00
|
|
|
gfxRect bbox = GetPatternRect(callerBBox, callerCTM, aSource);
|
2006-04-04 20:40:27 +00:00
|
|
|
|
|
|
|
// Get the transformation matrix that we will hand to the renderer's pattern
|
|
|
|
// routine.
|
2007-04-30 15:53:55 +00:00
|
|
|
*patternMatrix = GetPatternMatrix(bbox, callerBBox, callerCTM);
|
2006-04-04 20:40:27 +00:00
|
|
|
|
|
|
|
// Now that we have all of the necessary geometries, we can
|
2006-06-28 12:32:26 +00:00
|
|
|
// create our surface.
|
2009-06-11 15:21:03 +00:00
|
|
|
float patternWidth = bbox.Width();
|
|
|
|
float patternHeight = bbox.Height();
|
2007-06-13 09:02:48 +00:00
|
|
|
|
|
|
|
PRBool resultOverflows;
|
|
|
|
gfxIntSize surfaceSize =
|
|
|
|
nsSVGUtils::ConvertToSurfaceSize(gfxSize(patternWidth, patternHeight),
|
|
|
|
&resultOverflows);
|
|
|
|
|
|
|
|
// 0 disables rendering, < 0 is an error
|
|
|
|
if (surfaceSize.width <= 0 || surfaceSize.height <= 0)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2009-12-23 11:30:44 +00:00
|
|
|
if (resultOverflows ||
|
|
|
|
patternWidth != surfaceSize.width ||
|
|
|
|
patternHeight != surfaceSize.height) {
|
|
|
|
// scale drawing to pattern surface size
|
2007-06-13 09:02:48 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGMatrix> tempTM, aCTM;
|
|
|
|
NS_NewSVGMatrix(getter_AddRefs(tempTM),
|
|
|
|
surfaceSize.width / patternWidth, 0.0f,
|
|
|
|
0.0f, surfaceSize.height / patternHeight,
|
|
|
|
0.0f, 0.0f);
|
2009-10-26 19:37:31 +00:00
|
|
|
patternFrame->mCTM->Multiply(tempTM, getter_AddRefs(aCTM));
|
|
|
|
aCTM.swap(patternFrame->mCTM);
|
2007-06-13 09:02:48 +00:00
|
|
|
|
2009-12-23 11:30:44 +00:00
|
|
|
// and rescale pattern to compensate
|
2007-06-13 09:02:48 +00:00
|
|
|
patternMatrix->Scale(patternWidth / surfaceSize.width,
|
|
|
|
patternHeight / surfaceSize.height);
|
|
|
|
}
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
nsRefPtr<gfxASurface> tmpSurface =
|
2007-06-13 09:02:48 +00:00
|
|
|
gfxPlatform::GetPlatform()->CreateOffscreenSurface(surfaceSize,
|
2010-09-16 21:34:53 +00:00
|
|
|
gfxASurface::CONTENT_COLOR_ALPHA);
|
2007-07-17 09:24:27 +00:00
|
|
|
if (!tmpSurface || tmpSurface->CairoStatus())
|
2007-01-22 23:19:54 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2006-11-27 17:30:57 +00:00
|
|
|
|
2008-08-12 08:36:51 +00:00
|
|
|
nsSVGRenderState tmpState(tmpSurface);
|
|
|
|
gfxContext* tmpContext = tmpState.GetGfxContext();
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
// Fill with transparent black
|
2008-08-12 08:36:51 +00:00
|
|
|
tmpContext->SetOperator(gfxContext::OPERATOR_CLEAR);
|
|
|
|
tmpContext->Paint();
|
|
|
|
tmpContext->SetOperator(gfxContext::OPERATOR_OVER);
|
2007-04-30 15:53:55 +00:00
|
|
|
|
2007-04-24 08:11:22 +00:00
|
|
|
if (aGraphicOpacity != 1.0f) {
|
2008-08-12 08:36:51 +00:00
|
|
|
tmpContext->Save();
|
|
|
|
tmpContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
|
2007-04-24 08:11:22 +00:00
|
|
|
}
|
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
// OK, now render -- note that we use "firstKid", which
|
|
|
|
// we got at the beginning because it takes care of the
|
|
|
|
// referenced pattern situation for us
|
2006-02-09 18:15:03 +00:00
|
|
|
|
2010-07-01 16:40:30 +00:00
|
|
|
if (aSource->IsFrameOfType(nsIFrame::eSVGGeometry)) {
|
|
|
|
// Set the geometrical parent of the pattern we are rendering
|
|
|
|
patternFrame->mSource = static_cast<nsSVGGeometryFrame*>(aSource);
|
|
|
|
}
|
2006-02-09 18:15:03 +00:00
|
|
|
|
2010-08-13 13:32:15 +00:00
|
|
|
// Delay checking NS_FRAME_DRAWING_AS_PAINTSERVER bit until here so we can
|
|
|
|
// give back a clear surface if there's a loop
|
|
|
|
if (!(patternFrame->GetStateBits() & NS_FRAME_DRAWING_AS_PAINTSERVER)) {
|
|
|
|
patternFrame->AddStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER);
|
2008-10-01 00:51:05 +00:00
|
|
|
for (nsIFrame* kid = firstKid; kid;
|
|
|
|
kid = kid->GetNextSibling()) {
|
2010-12-23 05:48:31 +00:00
|
|
|
// The CTM of each frame referencing us can be different
|
|
|
|
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
|
|
|
|
if (SVGFrame) {
|
|
|
|
SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
|
|
|
|
nsISVGChildFrame::TRANSFORM_CHANGED);
|
|
|
|
}
|
2008-10-20 08:42:03 +00:00
|
|
|
nsSVGUtils::PaintFrameWithEffects(&tmpState, nsnull, kid);
|
2008-10-01 00:51:05 +00:00
|
|
|
}
|
2010-08-13 13:32:15 +00:00
|
|
|
patternFrame->RemoveStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2008-10-01 00:51:05 +00:00
|
|
|
|
2009-10-26 19:37:31 +00:00
|
|
|
patternFrame->mSource = nsnull;
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2007-04-24 08:11:22 +00:00
|
|
|
if (aGraphicOpacity != 1.0f) {
|
2008-08-12 08:36:51 +00:00
|
|
|
tmpContext->PopGroupToSource();
|
|
|
|
tmpContext->Paint(aGraphicOpacity);
|
|
|
|
tmpContext->Restore();
|
2007-04-24 08:11:22 +00:00
|
|
|
}
|
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
// caller now owns the surface
|
|
|
|
tmpSurface.swap(*surface);
|
2005-09-13 22:38:36 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Will probably need something like this... */
|
|
|
|
// How do we handle the insertion of a new frame?
|
|
|
|
// We really don't want to rerender this every time,
|
|
|
|
// do we?
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSVGPatternFrame::GetPatternFirstChild(nsIFrame **kid)
|
|
|
|
{
|
2008-09-30 11:28:20 +00:00
|
|
|
// Do we have any children ourselves?
|
2008-10-01 00:51:05 +00:00
|
|
|
*kid = mFrames.FirstChild();
|
|
|
|
if (*kid)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// No, see if we chain to someone who does
|
2011-01-16 07:36:34 +00:00
|
|
|
AutoPatternReferencer patternRef(this);
|
2008-10-01 00:51:05 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
|
|
|
if (!next)
|
2008-10-01 00:51:05 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
return next->GetPatternFirstChild(kid);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-05 16:06:43 +00:00
|
|
|
PRUint16
|
2011-01-16 07:36:34 +00:00
|
|
|
nsSVGPatternFrame::GetEnumValue(PRUint32 aIndex, nsIContent *aDefault)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2011-01-16 07:36:34 +00:00
|
|
|
nsSVGEnum& thisEnum =
|
|
|
|
static_cast<nsSVGPatternElement *>(mContent)->mEnumAttributes[aIndex];
|
|
|
|
|
|
|
|
if (thisEnum.IsExplicitlySet())
|
|
|
|
return thisEnum.GetAnimValue();
|
|
|
|
|
|
|
|
AutoPatternReferencer patternRef(this);
|
|
|
|
|
|
|
|
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
|
|
|
return next ? next->GetEnumValue(aIndex, aDefault) :
|
|
|
|
static_cast<nsSVGPatternElement *>(aDefault)->
|
|
|
|
mEnumAttributes[aIndex].GetAnimValue();
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
nsIDOMSVGAnimatedTransformList*
|
|
|
|
nsSVGPatternFrame::GetPatternTransformList(nsIContent* aDefault)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2011-01-16 07:36:34 +00:00
|
|
|
nsIDOMSVGAnimatedTransformList *thisTransformList =
|
|
|
|
static_cast<nsSVGPatternElement *>(mContent)->mPatternTransform.get();
|
|
|
|
|
|
|
|
// XXX We should be able to do something cleaner than this casting once
|
|
|
|
// bug 602759 is fixed and we have a proper animated transform list class
|
|
|
|
const nsSVGAnimatedTransformList *thisListAsConcreteType =
|
|
|
|
static_cast<const nsSVGAnimatedTransformList *>(thisTransformList);
|
|
|
|
if (thisListAsConcreteType && thisListAsConcreteType->IsExplicitlySet())
|
|
|
|
return thisTransformList;
|
|
|
|
|
|
|
|
AutoPatternReferencer patternRef(this);
|
|
|
|
|
|
|
|
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
|
|
|
return next ? next->GetPatternTransformList(aDefault) :
|
|
|
|
static_cast<nsSVGPatternElement *>(aDefault)->mPatternTransform.get();
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
gfxMatrix
|
|
|
|
nsSVGPatternFrame::GetPatternTransform()
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2011-01-16 07:36:34 +00:00
|
|
|
nsIDOMSVGAnimatedTransformList* transformList =
|
|
|
|
GetPatternTransformList(mContent);
|
2008-10-01 00:51:05 +00:00
|
|
|
|
2010-05-28 12:15:56 +00:00
|
|
|
static const gfxMatrix identityMatrix;
|
2011-01-16 07:36:34 +00:00
|
|
|
if (!transformList) {
|
2010-05-28 12:15:56 +00:00
|
|
|
return identityMatrix;
|
|
|
|
}
|
2008-10-01 00:51:05 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGTransformList> lTrans;
|
2011-01-16 07:36:34 +00:00
|
|
|
transformList->GetAnimVal(getter_AddRefs(lTrans));
|
2008-10-01 00:51:05 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGMatrix> patternTransform =
|
|
|
|
nsSVGTransformList::GetConsolidationMatrix(lTrans);
|
2010-05-28 12:15:56 +00:00
|
|
|
if (!patternTransform) {
|
|
|
|
return identityMatrix;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2010-05-28 12:15:56 +00:00
|
|
|
return nsSVGUtils::ConvertSVGMatrixToThebes(patternTransform);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2009-02-03 14:42:24 +00:00
|
|
|
const nsSVGViewBox &
|
2011-01-16 07:36:34 +00:00
|
|
|
nsSVGPatternFrame::GetViewBox(nsIContent* aDefault)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2011-01-16 07:36:34 +00:00
|
|
|
const nsSVGViewBox &thisViewBox =
|
|
|
|
static_cast<nsSVGPatternElement *>(mContent)->mViewBox;
|
2008-10-01 00:51:05 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
if (thisViewBox.IsValid())
|
|
|
|
return thisViewBox;
|
|
|
|
|
|
|
|
AutoPatternReferencer patternRef(this);
|
|
|
|
|
|
|
|
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
|
|
|
return next ? next->GetViewBox(aDefault) :
|
|
|
|
static_cast<nsSVGPatternElement *>(aDefault)->mViewBox;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2010-12-20 00:45:29 +00:00
|
|
|
const SVGAnimatedPreserveAspectRatio &
|
2011-01-16 07:36:34 +00:00
|
|
|
nsSVGPatternFrame::GetPreserveAspectRatio(nsIContent *aDefault)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2011-01-16 07:36:34 +00:00
|
|
|
const SVGAnimatedPreserveAspectRatio &thisPar =
|
|
|
|
static_cast<nsSVGPatternElement *>(mContent)->mPreserveAspectRatio;
|
2008-10-01 00:51:05 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
if (thisPar.IsExplicitlySet())
|
|
|
|
return thisPar;
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
AutoPatternReferencer patternRef(this);
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
|
|
|
return next ? next->GetPreserveAspectRatio(aDefault) :
|
|
|
|
static_cast<nsSVGPatternElement *>(aDefault)->mPreserveAspectRatio;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2009-02-03 14:42:24 +00:00
|
|
|
const nsSVGLength2 *
|
2011-01-16 07:36:34 +00:00
|
|
|
nsSVGPatternFrame::GetLengthValue(PRUint32 aIndex, nsIContent *aDefault)
|
2006-03-22 01:40:00 +00:00
|
|
|
{
|
2011-01-16 07:36:34 +00:00
|
|
|
const nsSVGLength2 *thisLength =
|
|
|
|
&static_cast<nsSVGPatternElement *>(mContent)->mLengthAttributes[aIndex];
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
if (thisLength->IsExplicitlySet())
|
|
|
|
return thisLength;
|
|
|
|
|
|
|
|
AutoPatternReferencer patternRef(this);
|
|
|
|
|
|
|
|
nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse();
|
|
|
|
return next ? next->GetLengthValue(aIndex, aDefault) :
|
|
|
|
&static_cast<nsSVGPatternElement *>(aDefault)->mLengthAttributes[aIndex];
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Private (helper) methods
|
2008-10-01 00:51:05 +00:00
|
|
|
nsSVGPatternFrame *
|
|
|
|
nsSVGPatternFrame::GetReferencedPattern()
|
|
|
|
{
|
|
|
|
if (mNoHRefURI)
|
|
|
|
return nsnull;
|
2008-09-30 11:28:20 +00:00
|
|
|
|
2010-03-29 01:46:55 +00:00
|
|
|
nsSVGPaintingProperty *property = static_cast<nsSVGPaintingProperty*>
|
|
|
|
(Properties().Get(nsSVGEffects::HrefProperty()));
|
2008-09-30 08:47:20 +00:00
|
|
|
|
2008-10-01 00:51:05 +00:00
|
|
|
if (!property) {
|
|
|
|
// Fetch our pattern element's xlink:href attribute
|
2008-10-11 11:29:35 +00:00
|
|
|
nsSVGPatternElement *pattern = static_cast<nsSVGPatternElement *>(mContent);
|
2009-01-22 00:56:51 +00:00
|
|
|
nsAutoString href;
|
|
|
|
pattern->mStringAttributes[nsSVGPatternElement::HREF].GetAnimValue(href, pattern);
|
2008-10-01 00:51:05 +00:00
|
|
|
if (href.IsEmpty()) {
|
|
|
|
mNoHRefURI = PR_TRUE;
|
|
|
|
return nsnull; // no URL
|
2008-09-30 11:28:20 +00:00
|
|
|
}
|
2008-10-01 00:51:05 +00:00
|
|
|
|
|
|
|
// Convert href to an nsIURI
|
|
|
|
nsCOMPtr<nsIURI> targetURI;
|
|
|
|
nsCOMPtr<nsIURI> base = mContent->GetBaseURI();
|
|
|
|
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
|
|
|
|
mContent->GetCurrentDoc(), base);
|
|
|
|
|
2010-03-29 01:46:55 +00:00
|
|
|
property =
|
|
|
|
nsSVGEffects::GetPaintingProperty(targetURI, this, nsSVGEffects::HrefProperty());
|
2008-10-01 00:51:05 +00:00
|
|
|
if (!property)
|
|
|
|
return nsnull;
|
2008-09-30 11:28:20 +00:00
|
|
|
}
|
2008-10-01 00:51:05 +00:00
|
|
|
|
|
|
|
nsIFrame *result = property->GetReferencedFrame();
|
|
|
|
if (!result)
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
nsIAtom* frameType = result->GetType();
|
|
|
|
if (frameType != nsGkAtoms::svgPatternFrame)
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
return static_cast<nsSVGPatternFrame*>(result);
|
|
|
|
}
|
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
nsSVGPatternFrame *
|
|
|
|
nsSVGPatternFrame::GetReferencedPatternIfNotInUse()
|
2008-10-01 00:51:05 +00:00
|
|
|
{
|
2011-01-16 07:36:34 +00:00
|
|
|
nsSVGPatternFrame *referenced = GetReferencedPattern();
|
|
|
|
if (!referenced)
|
|
|
|
return nsnull;
|
2008-10-01 00:51:05 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
if (referenced->mLoopFlag) {
|
|
|
|
// XXXjwatt: we should really send an error to the JavaScript Console here:
|
|
|
|
NS_WARNING("pattern reference loop detected while inheriting attribute!");
|
|
|
|
return nsnull;
|
|
|
|
}
|
2008-10-01 00:51:05 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
return referenced;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
// Helper functions
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
2009-06-11 15:21:03 +00:00
|
|
|
gfxRect
|
|
|
|
nsSVGPatternFrame::GetPatternRect(const gfxRect &aTargetBBox,
|
2009-07-23 08:35:59 +00:00
|
|
|
const gfxMatrix &aTargetCTM,
|
2010-07-01 16:40:30 +00:00
|
|
|
nsIFrame *aTarget)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
|
|
|
// Get our type
|
2011-01-16 07:36:34 +00:00
|
|
|
PRUint16 type = GetEnumValue(nsSVGPatternElement::PATTERNUNITS);
|
2005-09-13 22:38:36 +00:00
|
|
|
|
|
|
|
// We need to initialize our box
|
2006-03-22 01:40:00 +00:00
|
|
|
float x,y,width,height;
|
|
|
|
|
|
|
|
// Get the pattern x,y,width, and height
|
2009-02-03 14:42:24 +00:00
|
|
|
const nsSVGLength2 *tmpX, *tmpY, *tmpHeight, *tmpWidth;
|
2011-01-16 07:36:34 +00:00
|
|
|
tmpX = GetLengthValue(nsSVGPatternElement::X);
|
|
|
|
tmpY = GetLengthValue(nsSVGPatternElement::Y);
|
|
|
|
tmpHeight = GetLengthValue(nsSVGPatternElement::HEIGHT);
|
|
|
|
tmpWidth = GetLengthValue(nsSVGPatternElement::WIDTH);
|
2006-03-22 01:40:00 +00:00
|
|
|
|
2007-08-27 23:11:14 +00:00
|
|
|
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
|
2009-06-11 15:21:03 +00:00
|
|
|
x = nsSVGUtils::ObjectSpace(aTargetBBox, tmpX);
|
|
|
|
y = nsSVGUtils::ObjectSpace(aTargetBBox, tmpY);
|
|
|
|
width = nsSVGUtils::ObjectSpace(aTargetBBox, tmpWidth);
|
|
|
|
height = nsSVGUtils::ObjectSpace(aTargetBBox, tmpHeight);
|
2005-09-13 22:38:36 +00:00
|
|
|
} else {
|
2009-06-11 15:21:03 +00:00
|
|
|
float scale = nsSVGUtils::MaxExpansion(aTargetCTM);
|
|
|
|
x = nsSVGUtils::UserSpace(aTarget, tmpX) * scale;
|
|
|
|
y = nsSVGUtils::UserSpace(aTarget, tmpY) * scale;
|
|
|
|
width = nsSVGUtils::UserSpace(aTarget, tmpWidth) * scale;
|
|
|
|
height = nsSVGUtils::UserSpace(aTarget, tmpHeight) * scale;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2009-06-11 15:21:03 +00:00
|
|
|
return gfxRect(x, y, width, height);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2009-07-23 08:35:59 +00:00
|
|
|
gfxMatrix
|
|
|
|
nsSVGPatternFrame::ConstructCTM(const gfxRect &callerBBox,
|
2009-10-25 13:05:33 +00:00
|
|
|
const gfxMatrix &callerCTM,
|
2010-07-01 16:40:30 +00:00
|
|
|
nsIFrame *aTarget)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2009-07-23 08:35:59 +00:00
|
|
|
gfxMatrix tCTM;
|
2010-10-18 22:08:52 +00:00
|
|
|
nsSVGSVGElement *ctx = nsnull;
|
|
|
|
nsIContent* targetContent = aTarget->GetContent();
|
2006-04-04 20:40:27 +00:00
|
|
|
|
2009-07-23 08:35:59 +00:00
|
|
|
// The objectBoundingBox conversion must be handled in the CTM:
|
2011-01-16 07:36:34 +00:00
|
|
|
if (GetEnumValue(nsSVGPatternElement::PATTERNCONTENTUNITS) ==
|
2009-07-23 08:35:59 +00:00
|
|
|
nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
|
|
|
|
tCTM.Scale(callerBBox.Width(), callerBBox.Height());
|
2006-04-04 20:40:27 +00:00
|
|
|
} else {
|
2010-10-18 22:08:52 +00:00
|
|
|
if (targetContent->IsSVG()) {
|
|
|
|
ctx = static_cast<nsSVGElement*>(targetContent)->GetCtx();
|
|
|
|
}
|
2007-10-02 14:57:47 +00:00
|
|
|
float scale = nsSVGUtils::MaxExpansion(callerCTM);
|
2009-07-23 08:35:59 +00:00
|
|
|
tCTM.Scale(scale, scale);
|
2006-04-04 20:40:27 +00:00
|
|
|
}
|
|
|
|
|
2010-02-18 21:51:00 +00:00
|
|
|
nsSVGPatternElement *patternElement =
|
|
|
|
static_cast<nsSVGPatternElement*>(mContent);
|
2009-12-29 09:56:25 +00:00
|
|
|
gfxMatrix tm;
|
2010-02-25 18:20:43 +00:00
|
|
|
const nsSVGViewBoxRect viewBox = GetViewBox().GetAnimValue();
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2009-02-03 14:42:24 +00:00
|
|
|
if (viewBox.height > 0.0f && viewBox.width > 0.0f) {
|
2010-07-01 16:40:30 +00:00
|
|
|
float viewportWidth, viewportHeight, refX, refY;
|
|
|
|
if (targetContent->IsSVG()) {
|
|
|
|
// If we're dealing with an SVG target only retrieve the context once.
|
|
|
|
// Calling the nsIFrame* variant of GetAnimValue would look it up on
|
|
|
|
// every call.
|
2011-01-16 07:36:34 +00:00
|
|
|
viewportWidth =
|
|
|
|
GetLengthValue(nsSVGPatternElement::WIDTH)->GetAnimValue(ctx);
|
|
|
|
viewportHeight =
|
|
|
|
GetLengthValue(nsSVGPatternElement::HEIGHT)->GetAnimValue(ctx);
|
|
|
|
refX = GetLengthValue(nsSVGPatternElement::X)->GetAnimValue(ctx);
|
|
|
|
refY = GetLengthValue(nsSVGPatternElement::Y)->GetAnimValue(ctx);
|
2010-07-01 16:40:30 +00:00
|
|
|
} else {
|
|
|
|
// No SVG target, call the nsIFrame* variant of GetAnimValue.
|
2011-01-16 07:36:34 +00:00
|
|
|
viewportWidth =
|
|
|
|
GetLengthValue(nsSVGPatternElement::WIDTH)->GetAnimValue(aTarget);
|
|
|
|
viewportHeight =
|
|
|
|
GetLengthValue(nsSVGPatternElement::HEIGHT)->GetAnimValue(aTarget);
|
|
|
|
refX = GetLengthValue(nsSVGPatternElement::X)->GetAnimValue(aTarget);
|
|
|
|
refY = GetLengthValue(nsSVGPatternElement::Y)->GetAnimValue(aTarget);
|
2010-07-01 16:40:30 +00:00
|
|
|
}
|
2010-02-08 02:28:01 +00:00
|
|
|
gfxMatrix viewBoxTM = nsSVGUtils::GetViewBoxTransform(patternElement,
|
|
|
|
viewportWidth, viewportHeight,
|
2009-12-29 09:56:25 +00:00
|
|
|
viewBox.x, viewBox.y,
|
|
|
|
viewBox.width, viewBox.height,
|
2010-07-18 10:06:03 +00:00
|
|
|
GetPreserveAspectRatio());
|
2009-12-29 09:56:25 +00:00
|
|
|
|
|
|
|
gfxPoint ref = viewBoxTM.Transform(gfxPoint(refX, refY));
|
|
|
|
|
|
|
|
tm = viewBoxTM * gfxMatrix().Translate(gfxPoint(-ref.x, -ref.y));
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2009-12-29 09:56:25 +00:00
|
|
|
return tm * tCTM;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
gfxMatrix
|
2009-06-11 15:21:03 +00:00
|
|
|
nsSVGPatternFrame::GetPatternMatrix(const gfxRect &bbox,
|
|
|
|
const gfxRect &callerBBox,
|
2009-07-23 08:35:59 +00:00
|
|
|
const gfxMatrix &callerCTM)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
|
|
|
// Get the pattern transform
|
2007-04-30 15:53:55 +00:00
|
|
|
gfxMatrix patternTransform = GetPatternTransform();
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2006-04-04 20:40:27 +00:00
|
|
|
// We really want the pattern matrix to handle translations
|
2009-06-11 15:21:03 +00:00
|
|
|
float minx = bbox.X();
|
|
|
|
float miny = bbox.Y();
|
2007-04-19 08:29:27 +00:00
|
|
|
|
2011-01-16 07:36:34 +00:00
|
|
|
PRUint16 type = GetEnumValue(nsSVGPatternElement::PATTERNCONTENTUNITS);
|
2007-08-27 23:11:14 +00:00
|
|
|
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
|
2009-06-11 15:21:03 +00:00
|
|
|
minx += callerBBox.X();
|
|
|
|
miny += callerBBox.Y();
|
2007-04-19 08:29:27 +00:00
|
|
|
}
|
2007-04-30 15:53:55 +00:00
|
|
|
|
2007-10-02 14:57:47 +00:00
|
|
|
float scale = 1.0f / nsSVGUtils::MaxExpansion(callerCTM);
|
|
|
|
patternTransform.Scale(scale, scale);
|
2007-04-30 15:53:55 +00:00
|
|
|
patternTransform.Translate(gfxPoint(minx, miny));
|
2006-04-04 20:40:27 +00:00
|
|
|
|
2007-10-02 14:57:47 +00:00
|
|
|
return patternTransform;
|
2006-04-04 20:40:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2009-07-23 08:35:59 +00:00
|
|
|
nsSVGPatternFrame::GetTargetGeometry(gfxMatrix *aCTM,
|
2009-06-11 15:21:03 +00:00
|
|
|
gfxRect *aBBox,
|
2010-07-01 16:40:30 +00:00
|
|
|
nsIFrame *aTarget,
|
|
|
|
const gfxRect *aOverrideBounds)
|
2006-04-04 20:40:27 +00:00
|
|
|
{
|
2010-08-07 09:38:11 +00:00
|
|
|
*aBBox = aOverrideBounds ? *aOverrideBounds : nsSVGUtils::GetBBox(aTarget);
|
2010-07-01 16:40:30 +00:00
|
|
|
|
2006-04-04 20:40:27 +00:00
|
|
|
// Sanity check
|
2011-01-16 07:36:34 +00:00
|
|
|
PRUint16 type = GetEnumValue(nsSVGPatternElement::PATTERNUNITS);
|
2007-08-27 23:11:14 +00:00
|
|
|
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
|
2009-06-11 15:21:03 +00:00
|
|
|
if (aBBox->Width() <= 0 || aBBox->Height() <= 0) {
|
2006-04-04 20:40:27 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
}
|
2006-04-04 20:40:27 +00:00
|
|
|
|
|
|
|
// Get the transformation matrix from our calling geometry
|
2010-07-01 16:40:30 +00:00
|
|
|
*aCTM = nsSVGUtils::GetCanvasTM(aTarget);
|
2006-04-04 20:40:27 +00:00
|
|
|
|
|
|
|
// OK, now fix up the bounding box to reflect user coordinates
|
|
|
|
// We handle device unit scaling in pattern matrix
|
|
|
|
{
|
2007-10-02 14:57:47 +00:00
|
|
|
float scale = nsSVGUtils::MaxExpansion(*aCTM);
|
2009-06-11 15:21:03 +00:00
|
|
|
if (scale <= 0) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
aBBox->Scale(scale);
|
2006-04-04 20:40:27 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2006-05-16 15:55:01 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsSVGPaintServerFrame methods:
|
|
|
|
|
2010-07-01 16:40:30 +00:00
|
|
|
already_AddRefed<gfxPattern>
|
|
|
|
nsSVGPatternFrame::GetPaintServerPattern(nsIFrame *aSource,
|
|
|
|
float aGraphicOpacity,
|
|
|
|
const gfxRect *aOverrideBounds)
|
2006-05-16 15:55:01 +00:00
|
|
|
{
|
2008-02-08 21:52:04 +00:00
|
|
|
if (aGraphicOpacity == 0.0f) {
|
2010-07-01 16:40:30 +00:00
|
|
|
nsRefPtr<gfxPattern> pattern = new gfxPattern(gfxRGBA(0, 0, 0, 0));
|
|
|
|
return pattern.forget();
|
2008-02-08 21:52:04 +00:00
|
|
|
}
|
2007-04-24 08:11:22 +00:00
|
|
|
|
2006-05-16 15:55:01 +00:00
|
|
|
// Paint it!
|
2007-04-30 15:53:55 +00:00
|
|
|
nsRefPtr<gfxASurface> surface;
|
|
|
|
gfxMatrix pMatrix;
|
|
|
|
nsresult rv = PaintPattern(getter_AddRefs(surface), &pMatrix,
|
2010-07-01 16:40:30 +00:00
|
|
|
aSource, aGraphicOpacity, aOverrideBounds);
|
2007-10-02 14:57:47 +00:00
|
|
|
|
2006-09-26 16:36:03 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
2010-07-01 16:40:30 +00:00
|
|
|
return nsnull;
|
2006-09-26 16:36:03 +00:00
|
|
|
}
|
2006-05-16 15:55:01 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
if (pMatrix.IsSingular()) {
|
2010-07-01 16:40:30 +00:00
|
|
|
return nsnull;
|
2006-09-26 16:36:03 +00:00
|
|
|
}
|
2007-10-02 14:57:47 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
pMatrix.Invert();
|
2006-05-16 15:55:01 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
nsRefPtr<gfxPattern> pattern = new gfxPattern(surface);
|
2006-09-26 16:36:03 +00:00
|
|
|
|
2008-03-17 17:15:43 +00:00
|
|
|
if (!pattern || pattern->CairoStatus())
|
2010-11-03 22:35:00 +00:00
|
|
|
return nsnull;
|
2006-05-16 15:55:01 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
pattern->SetMatrix(pMatrix);
|
|
|
|
pattern->SetExtend(gfxPattern::EXTEND_REPEAT);
|
2010-07-01 16:40:30 +00:00
|
|
|
return pattern.forget();
|
2006-05-16 15:55:01 +00:00
|
|
|
}
|
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
// Public functions
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
2006-03-26 21:30:36 +00:00
|
|
|
nsIFrame* NS_NewSVGPatternFrame(nsIPresShell* aPresShell,
|
|
|
|
nsStyleContext* aContext)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2008-10-11 11:29:35 +00:00
|
|
|
return new (aPresShell) nsSVGPatternFrame(aContext);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|