Bug 326966. Reenable SVG <foreignobject> for cairo-gfx builds. r+sr=tor

git-svn-id: svn://10.0.0.236/trunk@190630 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
roc+%cs.cmu.edu
2006-02-21 00:33:27 +00:00
parent 6745dc09c9
commit da75593fc0
9 changed files with 476 additions and 335 deletions

View File

@@ -4244,6 +4244,7 @@ MOZ_REFLOW_PERF=
MOZ_REORDER=
MOZ_SINGLE_PROFILE=
MOZ_STATIC_MAIL_BUILD=
MOZ_SVG_FOREIGNOBJECT=$MOZ_ENABLE_CAIRO_GFX
MOZ_TIMELINE=
MOZ_UI_LOCALE=en-US
MOZ_UNIVERSALCHARDET=1
@@ -5396,19 +5397,21 @@ if test -n "$MOZ_SVG"; then
esac
fi
dnl COMMENTED OUT because foreignobject support should
dnl not be tweakable by distributors!
dnl ========================================================
dnl SVG <foreignObject>
dnl ========================================================
dnl MOZ_ARG_ENABLE_BOOL(svg-foreignobject,
dnl [ --enable-svg-foreignobject
dnl Enable SVG <foreignObject> support],
dnl MOZ_SVG_FOREIGNOBJECT=1,
dnl MOZ_SVG_FOREIGNOBJECT= )
dnl if test -n "$MOZ_SVG_FOREIGNOBJECT"; then
dnl AC_DEFINE(MOZ_SVG_FOREIGNOBJECT)
dnl fi
MOZ_ARG_DISABLE_BOOL(svg-foreignobject,
[ --disable-svg-foreignobject
Disable SVG <foreignObject> support],
MOZ_SVG_FOREIGNOBJECT=,
MOZ_SVG_FOREIGNOBJECT=1 )
if test "$MOZ_SVG_FOREIGNOBJECT"; then
if test -z "$MOZ_ENABLE_CAIRO_GFX"; then
AC_MSG_ERROR([<foreignobject> requires cairo gfx])
else
AC_DEFINE(MOZ_SVG_FOREIGNOBJECT)
fi
fi
dnl ========================================================
dnl Installer

View File

@@ -54,6 +54,9 @@
#include "nsGUIEvent.h"
#include "nsDisplayList.h"
#include "nsRegion.h"
#include "nsSVGForeignObjectFrame.h"
#include "nsSVGUtils.h"
#include "nsISVGOuterSVGFrame.h"
/**
* A namespace class for static layout utilities.
@@ -492,17 +495,33 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(nsEvent* aEvent, nsIFrame* aFrame)
if (!GUIEvent->widget)
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
nsPoint frameToView;
nsIView* frameView = aFrame->GetClosestView(&frameToView);
// If it is, or is a descendant of, an SVG foreignobject frame,
// then we need to do extra work
nsIFrame* rootFrame;
for (nsIFrame* f = aFrame; f; f = GetCrossDocParentFrame(f)) {
if (f->IsFrameOfType(nsIFrame::eSVGForeignObject)) {
nsSVGForeignObjectFrame* fo = NS_STATIC_CAST(nsSVGForeignObjectFrame*, f);
nsIFrame* outer;
CallQueryInterface(nsSVGUtils::GetOuterSVGFrame(fo), &outer);
return fo->TransformPointFromOuter(
GetEventCoordinatesRelativeTo(aEvent, outer)) -
aFrame->GetOffsetTo(fo);
}
rootFrame = f;
}
nsPoint widgetToView = TranslateWidgetToView(aFrame->GetPresContext(),
nsIView* rootView = rootFrame->GetView();
if (!rootView)
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
nsPoint widgetToView = TranslateWidgetToView(rootFrame->GetPresContext(),
GUIEvent->widget, GUIEvent->refPoint,
frameView);
rootView);
if (widgetToView == nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE))
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
return widgetToView - frameToView;
return widgetToView - aFrame->GetOffsetTo(rootFrame);
}
nsPoint

View File

@@ -108,6 +108,7 @@ FORCE_STATIC_LIB = 1
EXPORTS = \
nsSVGUtils.h \
nsSVGFilterInstance.h \
nsSVGForeignObjectFrame.h \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -36,15 +36,11 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsBlockFrame.h"
#include "nsIDOMSVGGElement.h"
#include "nsPresContext.h"
#include "nsISVGChildFrame.h"
#include "nsISVGContainerFrame.h"
#include "nsSVGForeignObjectFrame.h"
#include "nsISVGRendererCanvas.h"
#include "nsWeakReference.h"
#include "nsISVGValue.h"
#include "nsISVGValueObserver.h"
#include "nsIDOMSVGGElement.h"
#include "nsIDOMSVGTransformable.h"
#include "nsIDOMSVGAnimTransformList.h"
#include "nsIDOMSVGTransformList.h"
@@ -58,118 +54,16 @@
#include "nsISVGRendererRegion.h"
#include "nsISVGRenderer.h"
#include "nsISVGOuterSVGFrame.h"
#include "nsTransform2D.h"
#include "nsISVGValueUtils.h"
#include "nsRegion.h"
#include "nsLayoutAtoms.h"
#include "nsLayoutUtils.h"
#include "nsSVGUtils.h"
#include "nsIURI.h"
#include "nsSVGFilterFrame.h"
#include "nsSVGPoint.h"
#include "nsSVGRect.h"
#include "nsSVGMatrix.h"
#include "nsLayoutAtoms.h"
typedef nsBlockFrame nsSVGForeignObjectFrameBase;
class nsSVGForeignObjectFrame : public nsSVGForeignObjectFrameBase,
public nsISVGContainerFrame,
public nsISVGChildFrame,
public nsISVGValueObserver,
public nsSupportsWeakReference
{
friend nsIFrame*
NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent);
protected:
nsSVGForeignObjectFrame();
virtual ~nsSVGForeignObjectFrame();
nsresult Init();
// nsISupports interface:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
private:
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
public:
// nsIFrame:
NS_IMETHOD Init(nsPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame);
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::svgForeignObjectFrame
*/
// XXX Need to make sure that any of the code examining
// frametypes, particularly code looking at block and area
// also handles foreignObject before we return our own frametype
// virtual nsIAtom* GetType() const;
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("SVGForeignObject"), aResult);
}
#endif
// nsISVGValueObserver
NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
nsISVGValue::modificationType aModType);
NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
nsISVGValue::modificationType aModType);
// nsISupportsWeakReference
// implementation inherited from nsSupportsWeakReference
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation);
NS_IMETHOD NotifyRedrawSuspended();
NS_IMETHOD NotifyRedrawUnsuspended();
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
// nsISVGContainerFrame interface:
already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
already_AddRefed<nsSVGCoordCtxProvider> GetCoordContextProvider();
protected:
// implementation helpers:
void Update();
already_AddRefed<nsISVGRendererRegion> DoReflow();
float GetPxPerTwips();
float GetTwipsPerPx();
void TransformPoint(float& x, float& y);
void TransformVector(float& x, float& y);
PRBool mIsDirty;
nsCOMPtr<nsIDOMSVGLength> mX;
nsCOMPtr<nsIDOMSVGLength> mY;
nsCOMPtr<nsIDOMSVGLength> mWidth;
nsCOMPtr<nsIDOMSVGLength> mHeight;
nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;
PRBool mPropagateTransform;
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
};
//----------------------------------------------------------------------
// Implementation
@@ -189,7 +83,7 @@ NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent)
}
nsSVGForeignObjectFrame::nsSVGForeignObjectFrame()
: mIsDirty(PR_TRUE), mPropagateTransform(PR_TRUE)
: mIsDirty(PR_TRUE), mPropagateTransform(PR_TRUE), mFilter(nsnull)
{
}
@@ -212,6 +106,10 @@ nsSVGForeignObjectFrame::~nsSVGForeignObjectFrame()
value->RemoveObserver(this);
if (mHeight && (value = do_QueryInterface(mHeight)))
value->RemoveObserver(this);
if (mFilter) {
NS_REMOVE_SVGVALUE_OBSERVER(mFilter);
}
}
nsresult nsSVGForeignObjectFrame::Init()
@@ -323,37 +221,15 @@ nsSVGForeignObjectFrame::Reflow(nsPresContext* aPresContext,
NS_ENSURE_TRUE(mX && mY && mWidth && mHeight, NS_ERROR_FAILURE);
float x, y, width, height;
mX->GetValue(&x);
mY->GetValue(&y);
float width, height;
mWidth->GetValue(&width);
mHeight->GetValue(&height);
// transform x,y,width,height according to the current canvastm:
// XXX we're ignoring rotation at the moment
// (x, y): (left, top) -> (center_x, center_y)
x+=width/2.0f;
y+=height/2.0f;
// (x, y): (cx, cy) -> (cx', cy')
TransformPoint(x, y);
// find new ex & ey unit vectors
float e1x = 1.0f, e1y = 0.0f, e2x = 0.0f, e2y = 1.0f;
TransformVector(e1x, e1y);
TransformVector(e2x, e2y);
// adopt the scale of them for (w,h)
width *= (float)sqrt(e1x*e1x + e1y*e1y);
height *= (float)sqrt(e2x*e2x + e2y*e2y);
// (x, y): (cx', cy') -> (left', top')
x -= width/2.0f;
y -= height/2.0f;
// move ourselves to (x,y):
SetPosition(nsPoint((nscoord) (x*twipsPerPx), (nscoord) (y*twipsPerPx)));
// Xxx: if zewe have a view, move that
// move our frame to (0, 0), set our size to the untransformed
// width and height. Our frame size and position are meaningless
// given the possibility of non-rectilinear transforms; our size
// is only useful for reflowing our content
SetPosition(nsPoint(0, 0));
// create a new reflow state, setting our max size to (width,height):
nsSize availableSpace((nscoord)(width*twipsPerPx), (nscoord)(height*twipsPerPx));
@@ -432,6 +308,20 @@ NS_IMETHODIMP
nsSVGForeignObjectFrame::WillModifySVGObservable(nsISVGValue* observable,
nsISVGValue::modificationType aModType)
{
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
// need to handle filters because we might be the topmost filtered frame and
// the filter region could be changing.
if (filter && mFilterRegion) {
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
return NS_OK;
}
@@ -442,6 +332,29 @@ nsSVGForeignObjectFrame::DidModifySVGObservable (nsISVGValue* observable,
{
Update();
nsISVGFilterFrame *filter;
CallQueryInterface(observable, &filter);
if (filter) {
if (aModType == nsISVGValue::mod_die) {
mFilter = nsnull;
mFilterRegion = nsnull;
}
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame)
return NS_ERROR_FAILURE;
if (mFilter)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
nsCOMPtr<nsISVGRendererRegion> region;
nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region));
if (region)
outerSVGFrame->InvalidateRegion(region, PR_TRUE);
}
return NS_OK;
}
@@ -449,6 +362,50 @@ nsSVGForeignObjectFrame::DidModifySVGObservable (nsISVGValue* observable,
//----------------------------------------------------------------------
// nsISVGChildFrame methods
/**
* Transform a rectangle with a given matrix. Since the image of the
* rectangle may not be a rectangle, the output rectangle is the
* bounding box of the true image.
*/
static void
TransformRect(float* aX, float *aY, float* aWidth, float *aHeight,
nsIDOMSVGMatrix* aMatrix)
{
float x[4], y[4];
x[0] = *aX;
y[0] = *aY;
x[1] = x[0] + *aWidth;
y[1] = y[0];
x[2] = x[0] + *aWidth;
y[2] = y[0] + *aHeight;
x[3] = x[0];
y[3] = y[0] + *aHeight;
int i;
for (i = 0; i < 4; i++) {
nsSVGUtils::TransformPoint(aMatrix, &x[i], &y[i]);
}
float xmin, xmax, ymin, ymax;
xmin = xmax = x[0];
ymin = ymax = y[0];
for (int i=1; i<4; i++) {
if (x[i] < xmin)
xmin = x[i];
if (y[i] < ymin)
ymin = y[i];
if (x[i] > xmax)
xmax = x[i];
if (y[i] > ymax)
ymax = y[i];
}
*aX = xmin;
*aY = ymin;
*aWidth = xmax - xmin;
*aHeight = ymax - ymin;
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
@@ -458,59 +415,106 @@ nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas,
nsCOMPtr<nsISVGRendererRegion> region = DoReflow();
}
nsPresContext *presContext = GetPresContext();
nsRect r(mRect);
if (!r.IntersectRect(dirtyRectTwips, r))
return PR_TRUE;
/* check for filter */
if (!ignoreFilter) {
if (!mFilter) {
nsCOMPtr<nsIURI> aURI = GetStyleSVGReset()->mFilter;
if (aURI)
NS_GetSVGFilterFrame(&mFilter, aURI, mContent);
if (mFilter)
NS_ADD_SVGVALUE_OBSERVER(mFilter);
}
if (mFilter) {
if (!mFilterRegion)
mFilter->GetInvalidationRegion(this, getter_AddRefs(mFilterRegion));
mFilter->FilterPaint(canvas, this);
return NS_OK;
}
}
nsRect dirtyRect = nsRect(nsPoint(0, 0), GetSize());
nsCOMPtr<nsIDOMSVGMatrix> tm = GetTMIncludingOffset();
nsCOMPtr<nsIDOMSVGMatrix> inverse;
nsresult rv = tm->Inverse(getter_AddRefs(inverse));
float pxPerTwips = GetPxPerTwips();
r.x*=pxPerTwips;
r.y*=pxPerTwips;
r.width*=pxPerTwips;
r.height*=pxPerTwips;
float twipsPerPx = GetTwipsPerPx();
if (NS_SUCCEEDED(rv)) {
float x = dirtyRectTwips.x*pxPerTwips;
float y = dirtyRectTwips.y*pxPerTwips;
float w = dirtyRectTwips.width*pxPerTwips;
float h = dirtyRectTwips.height*pxPerTwips;
TransformRect(&x, &y, &w, &h, inverse);
nsRect r;
r.x = NSToCoordFloor(x*twipsPerPx);
r.y = NSToCoordFloor(y*twipsPerPx);
r.width = NSToCoordCeil((x + w)*twipsPerPx) - r.x;
r.height = NSToCoordCeil((y + h)*twipsPerPx) - r.y;
dirtyRect.IntersectRect(dirtyRect, r);
}
if (dirtyRect.IsEmpty())
return NS_OK;
nsCOMPtr<nsIRenderingContext> ctx;
canvas->LockRenderingContext(r, getter_AddRefs(ctx));
canvas->LockRenderingContext(tm, getter_AddRefs(ctx));
if (!ctx) {
NS_WARNING("Can't render foreignObject element!");
return NS_ERROR_FAILURE;
}
rv = nsLayoutUtils::PaintFrame(ctx, this, nsRegion(dirtyRect),
NS_RGBA(0,0,0,0));
nsRect dirtyRect = dirtyRectTwips;
dirtyRect.x -= mRect.x;
dirtyRect.y -= mRect.y;
{
nsIRenderingContext::AutoPushTranslation
translate(ctx, mRect.x, mRect.y);
rv = nsLayoutUtils::PaintFrame(ctx, this, nsRegion(dirtyRect));
}
ctx = nsnull;
canvas->UnlockRenderingContext();
return rv;
}
nsresult
nsSVGForeignObjectFrame::TransformPointFromOuterPx(float aX, float aY, nsPoint* aOut)
{
nsCOMPtr<nsIDOMSVGMatrix> tm = GetTMIncludingOffset();
nsCOMPtr<nsIDOMSVGMatrix> inverse;
nsresult rv = tm->Inverse(getter_AddRefs(inverse));
if (NS_FAILED(rv))
return rv;
nsSVGUtils::TransformPoint(inverse, &aX, &aY);
float twipsPerPx = GetTwipsPerPx();
*aOut = nsPoint(NSToCoordRound(aX*twipsPerPx),
NSToCoordRound(aY*twipsPerPx));
return NS_OK;
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
{
nsPoint p( (nscoord)(x*GetTwipsPerPx()),
(nscoord)(y*GetTwipsPerPx()));
*hit = nsLayoutUtils::GetFrameForPoint(this, p);
nsPoint pt;
nsresult rv = TransformPointFromOuterPx(x, y, &pt);
if (NS_FAILED(rv))
return rv;
*hit = nsLayoutUtils::GetFrameForPoint(this, pt);
return NS_OK;
}
nsPoint
nsSVGForeignObjectFrame::TransformPointFromOuter(nsPoint aPt)
{
float pxPerTwips = GetPxPerTwips();
nsPoint pt(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
TransformPointFromOuterPx(aPt.x*pxPerTwips, aPt.y*pxPerTwips, &pt);
return pt;
}
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
nsSVGForeignObjectFrame::GetCoveredRegion()
{
// get a region from our mRect
// if (mRect.width==0 || mRect.height==0) return nsnull;
// get a region from our BBox
nsISVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame) {
NS_ERROR("null outerSVGFrame");
@@ -520,17 +524,14 @@ nsSVGForeignObjectFrame::GetCoveredRegion()
nsCOMPtr<nsISVGRenderer> renderer;
outerSVGFrame->GetRenderer(getter_AddRefs(renderer));
float pxPerTwips = GetPxPerTwips();
nsISVGRendererRegion *region = nsnull;
renderer->CreateRectRegion((mRect.x-1) * pxPerTwips,
(mRect.y-1) * pxPerTwips,
(mRect.width+2) * pxPerTwips,
(mRect.height+2) * pxPerTwips,
&region);
NS_ASSERTION(region, "could not create region");
return region;
float x, y, w, h;
GetBBoxInternal(&x, &y, &w, &h);
nsISVGRendererRegion *region = nsnull;
renderer->CreateRectRegion(x, y, w, h, &region);
NS_ASSERTION(region, "could not create region");
return region;
}
NS_IMETHODIMP
@@ -583,50 +584,48 @@ nsSVGForeignObjectFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM)
return NS_OK;
}
void
nsSVGForeignObjectFrame::GetBBoxInternal(float* aX, float *aY, float* aWidth,
float *aHeight)
{
nsCOMPtr<nsIDOMSVGMatrix> ctm = GetCanvasTM();
if (!ctm)
return;
float x, y, width, height;
mX->GetValue(&x);
mY->GetValue(&y);
mWidth->GetValue(&width);
mHeight->GetValue(&height);
TransformRect(&x, &y, &width, &height, ctm);
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::GetBBox(nsIDOMSVGRect **_retval)
{
*_retval = nsnull;
float x[4], y[4], width, height;
mX->GetValue(&x[0]);
mY->GetValue(&y[0]);
mWidth->GetValue(&width);
mHeight->GetValue(&height);
x[1] = x[0] + width;
y[1] = y[0];
x[2] = x[0] + width;
y[2] = y[0] + height;
x[3] = x[0];
y[3] = y[0] + height;
TransformPoint(x[0], y[0]);
TransformPoint(x[1], y[1]);
TransformPoint(x[2], y[2]);
TransformPoint(x[3], y[3]);
float xmin, xmax, ymin, ymax;
xmin = xmax = x[0];
ymin = ymax = y[0];
for (int i=1; i<4; i++) {
if (x[i] < xmin)
xmin = x[i];
if (y[i] < ymin)
ymin = y[i];
if (x[i] > xmax)
xmax = x[i];
if (y[i] > ymax)
ymax = y[i];
}
return NS_NewSVGRect(_retval, xmin, ymin, xmax - xmin, ymax - ymin);
float x, y, w, h;
GetBBoxInternal(&x, &y, &w, &h);
return NS_NewSVGRect(_retval, x, y, w, h);
}
//----------------------------------------------------------------------
// nsISVGContainerFrame methods:
already_AddRefed<nsIDOMSVGMatrix>
nsSVGForeignObjectFrame::GetTMIncludingOffset()
{
nsCOMPtr<nsIDOMSVGMatrix> ctm = GetCanvasTM();
if (!ctm)
return nsnull;
float svgX, svgY;
mX->GetValue(&svgX);
mY->GetValue(&svgY);
nsIDOMSVGMatrix* matrix;
ctm->Translate(svgX, svgY, &matrix);
return matrix;
}
already_AddRefed<nsIDOMSVGMatrix>
nsSVGForeignObjectFrame::GetCanvasTM()
{
@@ -786,42 +785,3 @@ float nsSVGForeignObjectFrame::GetTwipsPerPx()
{
return GetPresContext()->ScaledPixelsToTwips();
}
void nsSVGForeignObjectFrame::TransformPoint(float& x, float& y)
{
nsCOMPtr<nsIDOMSVGMatrix> ctm = GetCanvasTM();
if (!ctm)
return;
// XXX this is absurd! we need to add another method (interface
// even?) to nsIDOMSVGMatrix to make this easier. (something like
// nsIDOMSVGMatrix::TransformPoint(float*x,float*y))
nsCOMPtr<nsIDOMSVGPoint> point;
NS_NewSVGPoint(getter_AddRefs(point), x, y);
if (!point)
return;
nsCOMPtr<nsIDOMSVGPoint> xfpoint;
point->MatrixTransform(ctm, getter_AddRefs(xfpoint));
if (!xfpoint)
return;
xfpoint->GetX(&x);
xfpoint->GetY(&y);
}
void nsSVGForeignObjectFrame::TransformVector(float& x, float& y)
{
// XXX This is crazy. What we really want is
// nsIDOMSVGMatrix::TransformVector(x,y);
float x0=0.0f, y0=0.0f;
TransformPoint(x0, y0);
TransformPoint(x,y);
x -= x0;
y -= y0;
}

View File

@@ -0,0 +1,177 @@
/* -*- 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
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 ***** */
#ifndef NSSVGFOREIGNOBJECTFRAME_H__
#define NSSVGFOREIGNOBJECTFRAME_H__
#include "nsBlockFrame.h"
#include "nsISVGChildFrame.h"
#include "nsISVGContainerFrame.h"
#include "nsISVGValueObserver.h"
#include "nsWeakReference.h"
#include "nsISVGRendererRegion.h"
#include "nsIDOMSVGMatrix.h"
#include "nsIDOMSVGLength.h"
typedef nsBlockFrame nsSVGForeignObjectFrameBase;
class nsISVGFilterFrame;
class nsSVGForeignObjectFrame : public nsSVGForeignObjectFrameBase,
public nsISVGContainerFrame,
public nsISVGChildFrame,
public nsISVGValueObserver,
public nsSupportsWeakReference
{
friend nsIFrame*
NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent);
protected:
nsSVGForeignObjectFrame();
virtual ~nsSVGForeignObjectFrame();
nsresult Init();
// nsISupports interface:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
private:
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
public:
// nsIFrame:
NS_IMETHOD Init(nsPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame);
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::svgForeignObjectFrame
*/
// XXX Need to make sure that any of the code examining
// frametypes, particularly code looking at block and area
// also handles foreignObject before we return our own frametype
// virtual nsIAtom* GetType() const;
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("SVGForeignObject"), aResult);
}
#endif
// nsISVGValueObserver
NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
nsISVGValue::modificationType aModType);
NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
nsISVGValue::modificationType aModType);
// nsISupportsWeakReference
// implementation inherited from nsSupportsWeakReference
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas,
const nsRect& dirtyRectTwips,
PRBool ignoreFilter);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation);
NS_IMETHOD NotifyRedrawSuspended();
NS_IMETHOD NotifyRedrawUnsuspended();
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
NS_IMETHOD GetFilterRegion(nsISVGRendererRegion **_retval) {
*_retval = mFilterRegion;
NS_IF_ADDREF(*_retval);
return NS_OK;
}
// nsISVGContainerFrame interface:
virtual already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
virtual already_AddRefed<nsSVGCoordCtxProvider> GetCoordContextProvider();
// foreignobject public methods
/**
* @param aPt a point in the twips coordinate system of the SVG outer frame
* Transforms the point to a point in this frame's twips coordinate system
*/
nsPoint TransformPointFromOuter(nsPoint aPt);
protected:
// implementation helpers:
void Update();
already_AddRefed<nsISVGRendererRegion> DoReflow();
float GetPxPerTwips();
float GetTwipsPerPx();
// Get the bounding box relative to the outer SVG element, in user units
void GetBBoxInternal(float* aX, float *aY, float* aWidth, float *aHeight);
already_AddRefed<nsIDOMSVGMatrix> GetTMIncludingOffset();
nsresult TransformPointFromOuterPx(float aX, float aY, nsPoint* aOut);
PRBool mIsDirty;
nsCOMPtr<nsIDOMSVGLength> mX;
nsCOMPtr<nsIDOMSVGLength> mY;
nsCOMPtr<nsIDOMSVGLength> mWidth;
nsCOMPtr<nsIDOMSVGLength> mHeight;
nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;
PRBool mPropagateTransform;
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
nsCOMPtr<nsISVGRendererRegion> mFilterRegion;
nsISVGFilterFrame *mFilter;
};
#endif

View File

@@ -69,7 +69,7 @@ interface nsISVGRendererSurface;
* Mozilla-native rendering object with a call to
* nsISVGRenderer::createCanvas().
*/
[scriptable, uuid(a1ea0d56-765f-43be-88dc-e54576e5735b)]
[scriptable, uuid(81eb1fc4-ea69-45dd-b31e-fe2cbcab04a5)]
interface nsISVGRendererCanvas : nsISupports
{
/**
@@ -83,7 +83,7 @@ interface nsISVGRendererCanvas : nsISupports
* @param rect Area to be locked.
* @return Mozilla-native rendering context for the locked area.
*/
[noscript] nsIRenderingContext lockRenderingContext([const] in nsRectRef rect);
[noscript] nsIRenderingContext lockRenderingContext(in nsIDOMSVGMatrix aCTM);
/**
* Unlock the canvas portion locked with a previous call to

View File

@@ -127,7 +127,10 @@ public:
// nsISVGCairoCanvas interface:
NS_IMETHOD_(cairo_t*) GetContext() { return mCR; }
NS_IMETHOD AdjustMatrixForInitialTransform(cairo_matrix_t* aMatrix);
protected:
void SetupCairoMatrix(nsIDOMSVGMatrix *aCTM);
private:
nsCOMPtr<nsIRenderingContext> mMozContext;
nsCOMPtr<nsPresContext> mPresContext;
@@ -421,14 +424,39 @@ NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
// nsISVGRendererCanvas methods:
void nsSVGCairoCanvas::SetupCairoMatrix(nsIDOMSVGMatrix *aCTM)
{
float m[6];
float val;
aCTM->GetA(&val);
m[0] = val;
aCTM->GetB(&val);
m[1] = val;
aCTM->GetC(&val);
m[2] = val;
aCTM->GetD(&val);
m[3] = val;
aCTM->GetE(&val);
m[4] = val;
aCTM->GetF(&val);
m[5] = val;
cairo_matrix_t matrix = {m[0], m[1], m[2], m[3], m[4], m[5]};
AdjustMatrixForInitialTransform(&matrix);
cairo_set_matrix(mCR, &matrix);
}
/** Implements [noscript] nsIRenderingContext lockRenderingContext(const in nsRectRef rect); */
NS_IMETHODIMP
nsSVGCairoCanvas::LockRenderingContext(const nsRect & rect,
nsSVGCairoCanvas::LockRenderingContext(nsIDOMSVGMatrix* aCTM,
nsIRenderingContext **_retval)
{
// XXX do we need to flush?
Flush();
SetupCairoMatrix(aCTM);
*_retval = mMozContext;
NS_ADDREF(*_retval);
return NS_OK;
@@ -663,33 +691,10 @@ nsSVGCairoCanvas::SetClipRect(nsIDOMSVGMatrix *aCTM, float aX, float aY,
if (!aCTM)
return NS_ERROR_FAILURE;
float m[6];
float val;
aCTM->GetA(&val);
m[0] = val;
aCTM->GetB(&val);
m[1] = val;
aCTM->GetC(&val);
m[2] = val;
aCTM->GetD(&val);
m[3] = val;
aCTM->GetE(&val);
m[4] = val;
aCTM->GetF(&val);
m[5] = val;
cairo_matrix_t oldMatrix;
cairo_get_matrix(mCR, &oldMatrix);
cairo_matrix_t matrix = {m[0], m[1], m[2], m[3], m[4], m[5]};
cairo_matrix_t inverse = matrix;
if (cairo_matrix_invert(&inverse))
return NS_ERROR_FAILURE;
cairo_transform(mCR, &matrix);
SetupCairoMatrix(aCTM);
cairo_new_path(mCR);
cairo_rectangle(mCR, aX, aY, aWidth, aHeight);
@@ -816,28 +821,7 @@ nsSVGCairoCanvas::CompositeSurfaceMatrix(nsISVGRendererSurface *aSurface,
cairo_save(mCR);
float m[6];
float val;
aCTM->GetA(&val);
m[0] = val;
aCTM->GetB(&val);
m[1] = val;
aCTM->GetC(&val);
m[2] = val;
aCTM->GetD(&val);
m[3] = val;
aCTM->GetE(&val);
m[4] = val;
aCTM->GetF(&val);
m[5] = val;
cairo_matrix_t matrix = {m[0], m[1], m[2], m[3], m[4], m[5]};
cairo_transform(mCR, &matrix);
SetupCairoMatrix(aCTM);
cairo_set_source_surface(mCR, cairoSurface->GetSurface(), 0.0, 0.0);
cairo_paint_with_alpha(mCR, aOpacity);

View File

@@ -231,7 +231,7 @@ NS_INTERFACE_MAP_END
/** Implements [noscript] nsIRenderingContext lockRenderingContext(const in nsRectRef rect); */
NS_IMETHODIMP
nsSVGGDIPlusCanvas::LockRenderingContext(const nsRect & rect,
nsSVGGDIPlusCanvas::LockRenderingContext(nsIDOMSVGMatrix* aCTM,
nsIRenderingContext **_retval)
{
#ifdef SVG_GDIPLUS_ENABLE_OFFSCREEN_BUFFER

View File

@@ -158,13 +158,10 @@ NS_INTERFACE_MAP_END
/** Implements [noscript] nsIRenderingContext lockRenderingContext(const in nsRectRef rect); */
NS_IMETHODIMP
nsSVGLibartCanvas::LockRenderingContext(const nsRect & rect,
nsSVGLibartCanvas::LockRenderingContext(nsIDOMSVGMatrix* aCTM,
nsIRenderingContext **_retval)
{
*_retval = nsnull;
mBitmap->LockRenderingContext(rect, _retval);
if (!*_retval) return NS_ERROR_FAILURE;
return NS_OK;
return NS_ERROR_FAILURE;
}
/** Implements void unlockRenderingContext(); */