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 "nsSVGAnimatedPreserveAspectRatio.h"
|
|
|
|
#include "nsStyleContext.h"
|
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsISVGChildFrame.h"
|
|
|
|
#include "nsIDOMSVGRect.h"
|
|
|
|
#include "nsSVGMatrix.h"
|
|
|
|
#include "nsSVGRect.h"
|
|
|
|
#include "nsSVGUtils.h"
|
2008-09-30 08:47:20 +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"
|
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"
|
2005-09-13 22:38:36 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_scooter
|
2007-04-30 15:53:55 +00:00
|
|
|
static void printCTM(char *msg, gfxMatrix aCTM);
|
2005-09-13 22:38:36 +00:00
|
|
|
static void printCTM(char *msg, nsIDOMSVGMatrix *aCTM);
|
|
|
|
static void printRect(char *msg, nsIDOMSVGRect *aRect);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Implementation
|
|
|
|
|
2006-09-08 13:54:05 +00:00
|
|
|
nsSVGPatternFrame::nsSVGPatternFrame(nsStyleContext* aContext,
|
|
|
|
nsIDOMSVGURIReference *aRef) :
|
|
|
|
nsSVGPatternFrameBase(aContext),
|
2008-09-30 08:47:20 +00:00
|
|
|
mLoopFlag(PR_FALSE), mPaintLoopFlag(PR_FALSE),
|
|
|
|
mNoHRefURI(PR_FALSE)
|
2006-09-08 13:54:05 +00:00
|
|
|
{
|
|
|
|
if (aRef) {
|
|
|
|
// Get the hRef
|
|
|
|
aRef->GetHref(getter_AddRefs(mHref));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsIFrame methods:
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2006-03-09 18:55:21 +00:00
|
|
|
nsSVGPatternFrame::DidSetStyleContext()
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGEffects::InvalidateRenderingObservers(this);
|
|
|
|
return nsSVGPatternFrameBase::DidSetStyleContext();
|
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-09-30 08:47:20 +00:00
|
|
|
nsSVGEffects::InvalidateRenderingObservers(this);
|
|
|
|
}
|
2006-03-22 01:40:00 +00:00
|
|
|
|
|
|
|
if (aNameSpaceID == kNameSpaceID_XLink &&
|
|
|
|
aAttribute == nsGkAtoms::href) {
|
2008-09-30 08:47:20 +00:00
|
|
|
// Blow away our reference, if any
|
|
|
|
DeleteProperty(nsGkAtoms::href);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
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
|
2008-09-30 08:47:20 +00:00
|
|
|
already_AddRefed<nsIDOMSVGMatrix>
|
2007-07-17 09:24:27 +00:00
|
|
|
nsSVGPatternFrame::GetCanvasTM()
|
|
|
|
{
|
2006-02-09 18:15:03 +00:00
|
|
|
nsIDOMSVGMatrix *rCTM;
|
2008-09-30 08:47:20 +00:00
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
if (mCTM) {
|
2006-02-09 18:15:03 +00:00
|
|
|
rCTM = mCTM;
|
|
|
|
NS_IF_ADDREF(rCTM);
|
2005-09-13 22:38:36 +00:00
|
|
|
} else {
|
|
|
|
// Do we know our rendering parent?
|
|
|
|
if (mSource) {
|
|
|
|
// Yes, use it!
|
2006-02-09 18:15:03 +00:00
|
|
|
mSource->GetCanvasTM(&rCTM);
|
2005-09-13 22:38:36 +00:00
|
|
|
} else {
|
2006-05-02 15:05:25 +00:00
|
|
|
// No, return an identity
|
|
|
|
// We get here when geometry in the <pattern> container is updated
|
|
|
|
NS_NewSVGMatrix(&rCTM);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
}
|
2008-09-30 08:47:20 +00:00
|
|
|
return rCTM;
|
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,
|
2007-04-24 08:11:22 +00:00
|
|
|
nsSVGGeometryFrame *aSource,
|
|
|
|
float aGraphicOpacity)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* General approach:
|
|
|
|
* Set the content geometry stuff
|
2008-09-30 08:47:20 +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;
|
|
|
|
|
|
|
|
// Get our child
|
|
|
|
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
|
2006-04-14 15:09:39 +00:00
|
|
|
nsSVGElement *callerContent;
|
2006-04-04 20:40:27 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGRect> callerBBox;
|
|
|
|
nsCOMPtr<nsIDOMSVGMatrix> callerCTM;
|
|
|
|
if (NS_FAILED(GetCallerGeometry(getter_AddRefs(callerCTM),
|
|
|
|
getter_AddRefs(callerBBox),
|
|
|
|
&callerContent, aSource)))
|
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.
|
2007-10-02 14:57:47 +00:00
|
|
|
if (NS_FAILED(ConstructCTM(getter_AddRefs(mCTM), callerBBox, callerCTM)))
|
2005-09-13 22:38:36 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
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.
|
2006-06-28 12:32:26 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGRect> bbox;
|
2007-10-02 14:57:47 +00:00
|
|
|
if (NS_FAILED(GetPatternRect(getter_AddRefs(bbox),
|
|
|
|
callerBBox, callerCTM,
|
2006-04-04 20:40:27 +00:00
|
|
|
callerContent)))
|
2006-02-09 18:15:03 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
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
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
#ifdef DEBUG_scooter
|
2007-10-02 14:57:47 +00:00
|
|
|
printRect("Geometry Rect: ", callerBBox);
|
|
|
|
printRect("Pattern Rect: ", bbox);
|
|
|
|
printCTM("Pattern TM ", *patternMatrix);
|
|
|
|
printCTM("Child TM ", mCTM);
|
2005-09-13 22:38:36 +00:00
|
|
|
#endif
|
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.
|
2007-06-13 09:02:48 +00:00
|
|
|
float patternWidth, patternHeight;
|
|
|
|
bbox->GetWidth(&patternWidth);
|
|
|
|
bbox->GetHeight(&patternHeight);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (resultOverflows) {
|
|
|
|
// scale down drawing to new pattern surface size
|
|
|
|
nsCOMPtr<nsIDOMSVGMatrix> tempTM, aCTM;
|
|
|
|
NS_NewSVGMatrix(getter_AddRefs(tempTM),
|
|
|
|
surfaceSize.width / patternWidth, 0.0f,
|
|
|
|
0.0f, surfaceSize.height / patternHeight,
|
|
|
|
0.0f, 0.0f);
|
|
|
|
mCTM->Multiply(tempTM, getter_AddRefs(aCTM));
|
|
|
|
aCTM.swap(mCTM);
|
|
|
|
|
|
|
|
// and magnify pattern to compensate
|
|
|
|
patternMatrix->Scale(patternWidth / surfaceSize.width,
|
|
|
|
patternHeight / surfaceSize.height);
|
|
|
|
}
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2007-01-22 23:19:54 +00:00
|
|
|
#ifdef DEBUG_scooter
|
2007-06-13 09:02:48 +00:00
|
|
|
printf("Creating %dX%d surface\n", int(surfaceSize.width), int(surfaceSize.height));
|
2007-01-22 23:19:54 +00:00
|
|
|
#endif
|
2006-11-27 17:30:57 +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,
|
2007-04-30 15:53:55 +00:00
|
|
|
gfxASurface::ImageFormatARGB32);
|
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
|
|
|
|
|
|
|
// Set our geometrical parent
|
|
|
|
mSource = aSource;
|
|
|
|
|
2008-09-30 08:47:20 +00:00
|
|
|
// Delay checking mPaintLoopFlag until here so we can give back a clear
|
|
|
|
// surface if there's a loop
|
|
|
|
if (!mPaintLoopFlag) {
|
|
|
|
mPaintLoopFlag = PR_TRUE;
|
|
|
|
for (nsIFrame* kid = firstKid; kid;
|
|
|
|
kid = kid->GetNextSibling()) {
|
|
|
|
nsSVGUtils::PaintChildWithEffects(&tmpState, nsnull, kid);
|
|
|
|
}
|
|
|
|
mPaintLoopFlag = PR_FALSE;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2008-09-30 08:47:20 +00:00
|
|
|
|
2006-02-09 18:15:03 +00:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
// Do we have any children ourselves?
|
2008-09-30 08:47:20 +00:00
|
|
|
*kid = mFrames.FirstChild();
|
|
|
|
if (*kid)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// No, see if we chain to someone who does
|
|
|
|
nsSVGPatternFrame *next = GetReferencedPattern();
|
|
|
|
|
|
|
|
mLoopFlag = PR_TRUE;
|
|
|
|
if (!next || next->mLoopFlag) {
|
|
|
|
mLoopFlag = PR_FALSE;
|
|
|
|
return NS_ERROR_FAILURE;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2008-09-30 08:47:20 +00:00
|
|
|
|
|
|
|
nsresult rv = next->GetPatternFirstChild(kid);
|
2005-09-13 22:38:36 +00:00
|
|
|
mLoopFlag = PR_FALSE;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2006-05-05 16:06:43 +00:00
|
|
|
PRUint16
|
|
|
|
nsSVGPatternFrame::GetPatternUnits()
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2006-03-22 01:40:00 +00:00
|
|
|
// See if we need to get the value from another pattern
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternElement *patternElement =
|
|
|
|
GetPatternWithAttr(nsGkAtoms::patternUnits, mContent);
|
|
|
|
return patternElement->mEnumAttributes[nsSVGPatternElement::PATTERNUNITS].GetAnimValue();
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-05 16:06:43 +00:00
|
|
|
PRUint16
|
|
|
|
nsSVGPatternFrame::GetPatternContentUnits()
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternElement *patternElement =
|
|
|
|
GetPatternWithAttr(nsGkAtoms::patternContentUnits, mContent);
|
|
|
|
return patternElement->mEnumAttributes[nsSVGPatternElement::PATTERNCONTENTUNITS].GetAnimValue();
|
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
|
|
|
{
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternElement *patternElement =
|
|
|
|
GetPatternWithAttr(nsGkAtoms::patternTransform, mContent);
|
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
gfxMatrix matrix;
|
2008-09-30 08:47:20 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGTransformList> lTrans;
|
|
|
|
patternElement->mPatternTransform->GetAnimVal(getter_AddRefs(lTrans));
|
|
|
|
nsCOMPtr<nsIDOMSVGMatrix> patternTransform =
|
|
|
|
nsSVGTransformList::GetConsolidationMatrix(lTrans);
|
|
|
|
if (patternTransform) {
|
|
|
|
matrix = nsSVGUtils::ConvertSVGMatrixToThebes(patternTransform);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2007-04-30 15:53:55 +00:00
|
|
|
return matrix;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSVGPatternFrame::GetViewBox(nsIDOMSVGRect **aViewBox)
|
|
|
|
{
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternElement *patternElement =
|
|
|
|
GetPatternWithAttr(nsGkAtoms::viewBox, mContent);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMSVGAnimatedRect> viewBox;
|
|
|
|
patternElement->GetViewBox(getter_AddRefs(viewBox));
|
|
|
|
return viewBox->GetAnimVal(aViewBox);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternFrame::GetPreserveAspectRatio(nsIDOMSVGAnimatedPreserveAspectRatio
|
2006-02-26 17:58:58 +00:00
|
|
|
**aPreserveAspectRatio)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternElement *patternElement =
|
|
|
|
GetPatternWithAttr(nsGkAtoms::preserveAspectRatio, mContent);
|
|
|
|
|
|
|
|
return patternElement->GetPreserveAspectRatio(aPreserveAspectRatio);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2006-04-14 15:09:39 +00:00
|
|
|
nsSVGLength2 *
|
|
|
|
nsSVGPatternFrame::GetX()
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternElement *pattern = GetPatternWithAttr(nsGkAtoms::x, mContent);
|
|
|
|
return &pattern->mLengthAttributes[nsSVGPatternElement::X];
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2006-04-14 15:09:39 +00:00
|
|
|
nsSVGLength2 *
|
|
|
|
nsSVGPatternFrame::GetY()
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternElement *pattern = GetPatternWithAttr(nsGkAtoms::y, mContent);
|
|
|
|
return &pattern->mLengthAttributes[nsSVGPatternElement::Y];
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2006-04-14 15:09:39 +00:00
|
|
|
nsSVGLength2 *
|
|
|
|
nsSVGPatternFrame::GetWidth()
|
2006-03-22 01:40:00 +00:00
|
|
|
{
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternElement *pattern = GetPatternWithAttr(nsGkAtoms::width, mContent);
|
|
|
|
return &pattern->mLengthAttributes[nsSVGPatternElement::WIDTH];
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
2006-04-14 15:09:39 +00:00
|
|
|
nsSVGLength2 *
|
|
|
|
nsSVGPatternFrame::GetHeight()
|
2006-03-22 01:40:00 +00:00
|
|
|
{
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternElement *pattern = GetPatternWithAttr(nsGkAtoms::height, mContent);
|
|
|
|
return &pattern->mLengthAttributes[nsSVGPatternElement::HEIGHT];
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Private (helper) methods
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternFrame *
|
|
|
|
nsSVGPatternFrame::GetReferencedPattern()
|
|
|
|
{
|
|
|
|
if (mNoHRefURI)
|
|
|
|
return nsnull;
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPaintingProperty *property =
|
|
|
|
static_cast<nsSVGPaintingProperty*>(GetProperty(nsGkAtoms::href));
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2008-09-30 08:47:20 +00:00
|
|
|
if (!property) {
|
|
|
|
// Fetch our pattern element's xlink:href attribute
|
|
|
|
nsAutoString href;
|
|
|
|
mHref->GetAnimVal(href);
|
|
|
|
if (href.IsEmpty()) {
|
|
|
|
mNoHRefURI = PR_TRUE;
|
|
|
|
return nsnull; // no URL
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2008-09-30 08:47:20 +00:00
|
|
|
|
|
|
|
// Convert href to an nsIURI
|
|
|
|
nsCOMPtr<nsIURI> targetURI;
|
|
|
|
nsCOMPtr<nsIURI> base = mContent->GetBaseURI();
|
|
|
|
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
|
|
|
|
mContent->GetCurrentDoc(), base);
|
|
|
|
|
|
|
|
property = nsSVGEffects::GetPaintingProperty(targetURI, this, nsGkAtoms::href);
|
|
|
|
if (!property)
|
|
|
|
return nsnull;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2008-09-30 08:47:20 +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);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsSVGPatternElement *
|
|
|
|
nsSVGPatternFrame::GetPatternWithAttr(nsIAtom *aAttrName, nsIContent *aDefault)
|
|
|
|
{
|
|
|
|
if (mContent->HasAttr(kNameSpaceID_None, aAttrName))
|
|
|
|
return static_cast<nsSVGPatternElement *>(mContent);
|
|
|
|
|
|
|
|
nsSVGPatternElement *pattern = static_cast<nsSVGPatternElement *>(aDefault);
|
|
|
|
|
|
|
|
nsSVGPatternFrame *next = GetReferencedPattern();
|
|
|
|
if (!next)
|
|
|
|
return pattern;
|
|
|
|
|
|
|
|
// Set mLoopFlag before checking mNextGrad->mLoopFlag in case we are mNextGrad
|
|
|
|
mLoopFlag = PR_TRUE;
|
|
|
|
// XXXjwatt: we should really send an error to the JavaScript Console here:
|
|
|
|
NS_WARN_IF_FALSE(!next->mLoopFlag, "gradient reference loop detected "
|
|
|
|
"while inheriting attribute!");
|
|
|
|
if (!next->mLoopFlag)
|
|
|
|
pattern = next->GetPatternWithAttr(aAttrName, aDefault);
|
|
|
|
mLoopFlag = PR_FALSE;
|
|
|
|
|
|
|
|
return pattern;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
// Helper functions
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
2008-09-30 08:47:20 +00:00
|
|
|
nsresult
|
|
|
|
nsSVGPatternFrame::GetPatternRect(nsIDOMSVGRect **patternRect,
|
2007-10-02 14:57:47 +00:00
|
|
|
nsIDOMSVGRect *bbox,
|
|
|
|
nsIDOMSVGMatrix *callerCTM,
|
2006-04-14 15:09:39 +00:00
|
|
|
nsSVGElement *content)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
|
|
|
// Get our type
|
2006-05-05 16:06:43 +00:00
|
|
|
PRUint16 type = GetPatternUnits();
|
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
|
2006-04-14 15:09:39 +00:00
|
|
|
nsSVGLength2 *tmpX, *tmpY, *tmpHeight, *tmpWidth;
|
|
|
|
tmpX = GetX();
|
|
|
|
tmpY = GetY();
|
|
|
|
tmpHeight = GetHeight();
|
|
|
|
tmpWidth = GetWidth();
|
2006-03-22 01:40:00 +00:00
|
|
|
|
2007-08-27 23:11:14 +00:00
|
|
|
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
|
2006-04-14 15:09:39 +00:00
|
|
|
x = nsSVGUtils::ObjectSpace(bbox, tmpX);
|
|
|
|
y = nsSVGUtils::ObjectSpace(bbox, tmpY);
|
|
|
|
width = nsSVGUtils::ObjectSpace(bbox, tmpWidth);
|
|
|
|
height = nsSVGUtils::ObjectSpace(bbox, tmpHeight);
|
2005-09-13 22:38:36 +00:00
|
|
|
} else {
|
2007-10-02 14:57:47 +00:00
|
|
|
float scale = nsSVGUtils::MaxExpansion(callerCTM);
|
|
|
|
x = nsSVGUtils::UserSpace(content, tmpX) * scale;
|
|
|
|
y = nsSVGUtils::UserSpace(content, tmpY) * scale;
|
|
|
|
width = nsSVGUtils::UserSpace(content, tmpWidth) * scale;
|
|
|
|
height = nsSVGUtils::UserSpace(content, tmpHeight) * scale;
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_NewSVGRect(patternRect, x, y, width, height);
|
|
|
|
}
|
|
|
|
|
2006-05-05 16:06:43 +00:00
|
|
|
static float
|
|
|
|
GetLengthValue(nsSVGLength2 *aLength)
|
|
|
|
{
|
2007-07-08 07:08:04 +00:00
|
|
|
return aLength->GetAnimValue(static_cast<nsSVGSVGElement*>(nsnull));
|
2006-05-05 16:06:43 +00:00
|
|
|
}
|
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
nsresult
|
2006-04-04 20:40:27 +00:00
|
|
|
nsSVGPatternFrame::ConstructCTM(nsIDOMSVGMatrix **aCTM,
|
2007-10-02 14:57:47 +00:00
|
|
|
nsIDOMSVGRect *callerBBox,
|
|
|
|
nsIDOMSVGMatrix *callerCTM)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2006-04-04 20:40:27 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGMatrix> tCTM, tempTM;
|
|
|
|
|
|
|
|
// Begin by handling the objectBoundingBox conversion since
|
|
|
|
// this must be handled in the CTM
|
2006-05-05 16:06:43 +00:00
|
|
|
PRUint16 type = GetPatternContentUnits();
|
2006-04-04 20:40:27 +00:00
|
|
|
|
2007-08-27 23:11:14 +00:00
|
|
|
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
|
2006-04-04 20:40:27 +00:00
|
|
|
// Use the bounding box
|
2007-04-19 08:29:27 +00:00
|
|
|
float width, height;
|
2006-04-04 20:40:27 +00:00
|
|
|
callerBBox->GetWidth(&width);
|
|
|
|
callerBBox->GetHeight(&height);
|
2008-09-30 08:47:20 +00:00
|
|
|
NS_NewSVGMatrix(getter_AddRefs(tCTM), width, 0.0f, 0.0f,
|
2007-04-19 08:29:27 +00:00
|
|
|
height, 0.0f, 0.0f);
|
2006-04-04 20:40:27 +00:00
|
|
|
} else {
|
2007-10-02 14:57:47 +00:00
|
|
|
float scale = nsSVGUtils::MaxExpansion(callerCTM);
|
|
|
|
NS_NewSVGMatrix(getter_AddRefs(tCTM), scale, 0, 0, scale, 0, 0);
|
2006-04-04 20:40:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Do we have a viewbox?
|
|
|
|
nsCOMPtr<nsIDOMSVGRect> viewRect;
|
|
|
|
GetViewBox(getter_AddRefs(viewRect));
|
2005-09-13 22:38:36 +00:00
|
|
|
|
|
|
|
// See if we really have something
|
|
|
|
float viewBoxX, viewBoxY, viewBoxHeight, viewBoxWidth;
|
2006-04-04 20:40:27 +00:00
|
|
|
viewRect->GetX(&viewBoxX);
|
|
|
|
viewRect->GetY(&viewBoxY);
|
|
|
|
viewRect->GetHeight(&viewBoxHeight);
|
|
|
|
viewRect->GetWidth(&viewBoxWidth);
|
2008-02-21 17:43:25 +00:00
|
|
|
if (viewBoxHeight > 0.0f && viewBoxWidth > 0.0f) {
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2006-05-05 16:06:43 +00:00
|
|
|
float viewportWidth = GetLengthValue(GetWidth());
|
|
|
|
float viewportHeight = GetLengthValue(GetHeight());
|
|
|
|
float refX = GetLengthValue(GetX());
|
|
|
|
float refY = GetLengthValue(GetY());
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2006-02-26 17:58:58 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> par;
|
|
|
|
GetPreserveAspectRatio(getter_AddRefs(par));
|
2005-09-13 22:38:36 +00:00
|
|
|
|
2006-02-26 17:58:58 +00:00
|
|
|
tempTM = nsSVGUtils::GetViewBoxTransform(viewportWidth, viewportHeight,
|
|
|
|
viewBoxX + refX, viewBoxY + refY,
|
|
|
|
viewBoxWidth, viewBoxHeight,
|
|
|
|
par,
|
|
|
|
PR_TRUE);
|
2005-09-13 22:38:36 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
// No viewBox, construct from the (modified) parent matrix
|
2006-06-06 07:50:11 +00:00
|
|
|
NS_NewSVGMatrix(getter_AddRefs(tempTM));
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
2006-06-06 07:50:11 +00:00
|
|
|
tCTM->Multiply(tempTM, aCTM);
|
2005-09-13 22:38:36 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
gfxMatrix
|
|
|
|
nsSVGPatternFrame::GetPatternMatrix(nsIDOMSVGRect *bbox,
|
2007-04-19 08:29:27 +00:00
|
|
|
nsIDOMSVGRect *callerBBox,
|
2006-04-04 20:40:27 +00:00
|
|
|
nsIDOMSVGMatrix *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
|
2007-04-19 08:29:27 +00:00
|
|
|
float minx, miny;
|
2006-04-04 20:40:27 +00:00
|
|
|
bbox->GetX(&minx);
|
|
|
|
bbox->GetY(&miny);
|
2007-04-19 08:29:27 +00:00
|
|
|
|
|
|
|
PRUint16 type = GetPatternContentUnits();
|
2007-08-27 23:11:14 +00:00
|
|
|
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
|
2007-04-19 08:29:27 +00:00
|
|
|
float x, y;
|
|
|
|
callerBBox->GetX(&x);
|
|
|
|
callerBBox->GetY(&y);
|
|
|
|
minx += x;
|
|
|
|
miny += y;
|
|
|
|
}
|
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
|
2008-09-30 08:47:20 +00:00
|
|
|
nsSVGPatternFrame::GetCallerGeometry(nsIDOMSVGMatrix **aCTM,
|
2006-04-04 20:40:27 +00:00
|
|
|
nsIDOMSVGRect **aBBox,
|
2006-04-14 15:09:39 +00:00
|
|
|
nsSVGElement **aContent,
|
2006-05-02 15:05:25 +00:00
|
|
|
nsSVGGeometryFrame *aSource)
|
2006-04-04 20:40:27 +00:00
|
|
|
{
|
|
|
|
*aCTM = nsnull;
|
|
|
|
*aBBox = nsnull;
|
|
|
|
*aContent = nsnull;
|
|
|
|
|
|
|
|
// Make sure the callerContent is an SVG element. If we are attempting
|
|
|
|
// to paint a pattern for text, then the content will be the #text, so we
|
|
|
|
// actually want the parent, which should be the <svg:text> or <svg:tspan>
|
|
|
|
// element.
|
2006-05-02 15:05:25 +00:00
|
|
|
nsIAtom *callerType = aSource->GetType();
|
2006-12-26 17:47:52 +00:00
|
|
|
if (callerType == nsGkAtoms::svgGlyphFrame) {
|
2007-07-08 07:08:04 +00:00
|
|
|
*aContent = static_cast<nsSVGElement*>
|
|
|
|
(aSource->GetContent()->GetParent());
|
2005-09-13 22:38:36 +00:00
|
|
|
} else {
|
2007-07-08 07:08:04 +00:00
|
|
|
*aContent = static_cast<nsSVGElement*>(aSource->GetContent());
|
2006-04-04 20:40:27 +00:00
|
|
|
}
|
|
|
|
NS_ASSERTION(aContent,"Caller does not have any content!");
|
|
|
|
if (!aContent)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Get the calling geometry's bounding box. This
|
|
|
|
// will be in *device coordinates*
|
2006-05-02 15:05:25 +00:00
|
|
|
nsISVGChildFrame *callerSVGFrame;
|
2006-11-13 20:42:42 +00:00
|
|
|
if (callerType == nsGkAtoms::svgGlyphFrame)
|
|
|
|
CallQueryInterface(aSource->GetParent(), &callerSVGFrame);
|
|
|
|
else
|
|
|
|
CallQueryInterface(aSource, &callerSVGFrame);
|
2007-10-02 14:57:47 +00:00
|
|
|
|
|
|
|
callerSVGFrame->SetMatrixPropagation(PR_FALSE);
|
2008-09-30 08:47:20 +00:00
|
|
|
callerSVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
|
2008-01-25 09:27:03 +00:00
|
|
|
nsISVGChildFrame::TRANSFORM_CHANGED );
|
2006-04-04 20:40:27 +00:00
|
|
|
callerSVGFrame->GetBBox(aBBox);
|
2007-10-02 14:57:47 +00:00
|
|
|
callerSVGFrame->SetMatrixPropagation(PR_TRUE);
|
2008-01-25 09:27:03 +00:00
|
|
|
callerSVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
|
|
|
|
nsISVGChildFrame::TRANSFORM_CHANGED);
|
2007-10-02 14:57:47 +00:00
|
|
|
|
2006-04-04 20:40:27 +00:00
|
|
|
// Sanity check
|
2007-04-10 09:57:12 +00:00
|
|
|
PRUint16 type = GetPatternUnits();
|
2007-08-27 23:11:14 +00:00
|
|
|
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
|
2006-04-04 20:40:27 +00:00
|
|
|
float width, height;
|
|
|
|
(*aBBox)->GetWidth(&width);
|
|
|
|
(*aBBox)->GetHeight(&height);
|
|
|
|
if (width <= 0 || height <= 0) {
|
|
|
|
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
|
|
|
|
aSource->GetCanvasTM(aCTM);
|
|
|
|
|
|
|
|
// OK, now fix up the bounding box to reflect user coordinates
|
|
|
|
// We handle device unit scaling in pattern matrix
|
|
|
|
{
|
2007-04-19 08:29:27 +00:00
|
|
|
float x, y, width, height;
|
2006-04-04 20:40:27 +00:00
|
|
|
(*aBBox)->GetX(&x);
|
|
|
|
(*aBBox)->GetY(&y);
|
|
|
|
(*aBBox)->GetWidth(&width);
|
|
|
|
(*aBBox)->GetHeight(&height);
|
2007-10-02 14:57:47 +00:00
|
|
|
float scale = nsSVGUtils::MaxExpansion(*aCTM);
|
|
|
|
#ifdef DEBUG_scooter
|
|
|
|
fprintf(stderr, "pattern scale %f\n", scale);
|
|
|
|
fprintf(stderr, "x,y,width,height: %f %f %f %f\n", x, y, width, height);
|
|
|
|
#endif
|
|
|
|
x *= scale;
|
|
|
|
y *= scale;
|
|
|
|
width *= scale;
|
|
|
|
height *= scale;
|
2006-04-04 20:40:27 +00:00
|
|
|
(*aBBox)->SetX(x);
|
|
|
|
(*aBBox)->SetY(y);
|
|
|
|
(*aBBox)->SetWidth(width);
|
|
|
|
(*aBBox)->SetHeight(height);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2006-05-16 15:55:01 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsSVGPaintServerFrame methods:
|
|
|
|
|
2007-04-23 09:11:19 +00:00
|
|
|
PRBool
|
2007-01-10 17:01:20 +00:00
|
|
|
nsSVGPatternFrame::SetupPaintServer(gfxContext *aContext,
|
2006-05-16 15:55:01 +00:00
|
|
|
nsSVGGeometryFrame *aSource,
|
2007-10-21 09:05:41 +00:00
|
|
|
float aGraphicOpacity)
|
2006-05-16 15:55:01 +00:00
|
|
|
{
|
2008-02-08 21:52:04 +00:00
|
|
|
if (aGraphicOpacity == 0.0f) {
|
|
|
|
aContext->SetColor(gfxRGBA(0, 0, 0, 0));
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-04-24 08:11:22 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
gfxMatrix matrix = aContext->CurrentMatrix();
|
2006-05-16 15:55:01 +00:00
|
|
|
|
|
|
|
// Paint it!
|
2007-04-30 15:53:55 +00:00
|
|
|
nsRefPtr<gfxASurface> surface;
|
|
|
|
gfxMatrix pMatrix;
|
|
|
|
aContext->IdentityMatrix();
|
|
|
|
nsresult rv = PaintPattern(getter_AddRefs(surface), &pMatrix,
|
2007-04-24 08:11:22 +00:00
|
|
|
aSource, aGraphicOpacity);
|
2007-10-02 14:57:47 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
aContext->SetMatrix(matrix);
|
2006-09-26 16:36:03 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
2007-04-23 09:11:19 +00:00
|
|
|
return PR_FALSE;
|
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()) {
|
2007-10-10 00:00:05 +00:00
|
|
|
return PR_FALSE;
|
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())
|
2007-10-10 00:00:05 +00:00
|
|
|
return PR_FALSE;
|
2006-05-16 15:55:01 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
pattern->SetMatrix(pMatrix);
|
|
|
|
pattern->SetExtend(gfxPattern::EXTEND_REPEAT);
|
2006-05-16 15:55:01 +00:00
|
|
|
|
2007-04-30 15:53:55 +00:00
|
|
|
aContext->SetPattern(pattern);
|
2006-05-16 15:55:01 +00:00
|
|
|
|
2007-04-23 09:11:19 +00:00
|
|
|
return PR_TRUE;
|
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,
|
|
|
|
nsIContent* aContent,
|
|
|
|
nsStyleContext* aContext)
|
2005-09-13 22:38:36 +00:00
|
|
|
{
|
2006-03-22 01:40:00 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGPatternElement> patternElement = do_QueryInterface(aContent);
|
2007-07-25 09:16:02 +00:00
|
|
|
if (!patternElement) {
|
|
|
|
NS_ERROR("Can't create frame! Content is not an SVG pattern");
|
2005-11-11 02:36:29 +00:00
|
|
|
return nsnull;
|
2007-07-25 09:16:02 +00:00
|
|
|
}
|
2006-03-26 21:30:36 +00:00
|
|
|
|
2006-02-09 18:15:03 +00:00
|
|
|
nsCOMPtr<nsIDOMSVGURIReference> ref = do_QueryInterface(aContent);
|
2008-09-30 08:47:20 +00:00
|
|
|
NS_ASSERTION(ref,
|
2005-09-13 22:38:36 +00:00
|
|
|
"NS_NewSVGPatternFrame -- Content doesn't support nsIDOMSVGURIReference");
|
|
|
|
|
|
|
|
#ifdef DEBUG_scooter
|
2006-03-22 01:40:00 +00:00
|
|
|
printf("NS_NewSVGPatternFrame\n");
|
2005-09-13 22:38:36 +00:00
|
|
|
#endif
|
2006-09-08 13:54:05 +00:00
|
|
|
return new (aPresShell) nsSVGPatternFrame(aContext, ref);
|
2005-09-13 22:38:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG_scooter
|
2007-04-30 15:53:55 +00:00
|
|
|
static void printCTM(char *msg, gfxMatrix aCTM)
|
|
|
|
{
|
|
|
|
printf("%s {%f,%f,%f,%f,%f,%f}\n", msg,
|
|
|
|
aCTM.xx, aCTM.yx, aCTM.xy, aCTM.yy, aCTM.x0, aCTM.y0);
|
|
|
|
}
|
|
|
|
|
2005-09-13 22:38:36 +00:00
|
|
|
static void printCTM(char *msg, nsIDOMSVGMatrix *aCTM)
|
|
|
|
{
|
|
|
|
float a,b,c,d,e,f;
|
2008-09-30 08:47:20 +00:00
|
|
|
aCTM->GetA(&a);
|
|
|
|
aCTM->GetB(&b);
|
2005-09-13 22:38:36 +00:00
|
|
|
aCTM->GetC(&c);
|
2008-09-30 08:47:20 +00:00
|
|
|
aCTM->GetD(&d);
|
|
|
|
aCTM->GetE(&e);
|
2005-09-13 22:38:36 +00:00
|
|
|
aCTM->GetF(&f);
|
|
|
|
printf("%s {%f,%f,%f,%f,%f,%f}\n",msg,a,b,c,d,e,f);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printRect(char *msg, nsIDOMSVGRect *aRect)
|
|
|
|
{
|
|
|
|
float x,y,width,height;
|
2008-09-30 08:47:20 +00:00
|
|
|
aRect->GetX(&x);
|
|
|
|
aRect->GetY(&y);
|
|
|
|
aRect->GetWidth(&width);
|
|
|
|
aRect->GetHeight(&height);
|
2005-09-13 22:38:36 +00:00
|
|
|
printf("%s {%f,%f,%f,%f}\n",msg,x,y,width,height);
|
|
|
|
}
|
|
|
|
#endif
|