Bug 347245 - Remove nsSVGCairoGlyphGeometry. r=longson, sr=roc

This commit is contained in:
tor%cs.brown.edu 2006-08-23 18:16:15 +00:00
Родитель d271fb2657
Коммит 534787a02a
13 изменённых файлов: 338 добавлений и 785 удалений

Просмотреть файл

@ -112,6 +112,25 @@ nsSVGGeometryFrame::InitSVG()
return NS_OK;
}
NS_IMETHODIMP
nsSVGGeometryFrame::Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow)
{
mContent = aContent;
NS_IF_ADDREF(mContent);
mParent = aParent;
if (mContent) {
mContent->SetMayHaveFrame(PR_TRUE);
}
InitSVG();
DidSetStyleContext();
return NS_OK;
}
NS_IMETHODIMP
nsSVGGeometryFrame::DidSetStyleContext()
{

Просмотреть файл

@ -62,6 +62,9 @@ public:
virtual void Destroy();
// nsIFrame interface:
NS_IMETHOD Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow);
NS_IMETHOD DidSetStyleContext();
// nsISupports interface:

Просмотреть файл

@ -52,6 +52,9 @@
#include "nsSVGPoint.h"
#include "nsSVGRect.h"
#include "nsDOMError.h"
#include "nsSVGMatrix.h"
#include "nsISVGCairoCanvas.h"
#include "cairo.h"
//----------------------------------------------------------------------
// Implementation
@ -81,7 +84,6 @@ nsSVGGlyphFrame::nsSVGGlyphFrame(nsStyleContext* aContext)
// nsISupports methods
NS_INTERFACE_MAP_BEGIN(nsSVGGlyphFrame)
NS_INTERFACE_MAP_ENTRY(nsISVGGlyphGeometrySource)
NS_INTERFACE_MAP_ENTRY(nsISVGGlyphFragmentLeaf)
NS_INTERFACE_MAP_ENTRY(nsISVGGlyphFragmentNode)
NS_INTERFACE_MAP_ENTRY(nsISVGChildFrame)
@ -90,43 +92,6 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGGlyphFrameBase)
//----------------------------------------------------------------------
// nsIFrame methods
NS_IMETHODIMP
nsSVGGlyphFrame::Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow)
{
// rv = nsSVGGlyphFrameBase::Init(aPresContext, aContent, aParent, aPrevInFlow);
mContent = aContent;
NS_IF_ADDREF(mContent);
mParent = aParent;
if (mContent) {
mContent->SetMayHaveFrame(PR_TRUE);
}
// construct our glyphmetrics & glyphgeometry objects:
nsSVGOuterSVGFrame* outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame) {
NS_ERROR("No outerSVGFrame");
DidSetStyleContext();
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsISVGRenderer> renderer;
outerSVGFrame->GetRenderer(getter_AddRefs(renderer));
if (renderer) {
renderer->CreateGlyphGeometry(getter_AddRefs(mGeometry));
}
nsSVGGlyphFrameBase::InitSVG();
DidSetStyleContext();
if (!renderer || !mGeometry)
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsSVGGlyphFrame::CharacterDataChanged(nsPresContext* aPresContext,
nsIContent* aChild,
@ -230,16 +195,112 @@ nsSVGGlyphFrame::IsFrameOfType(PRUint32 aFlags) const
//----------------------------------------------------------------------
// nsISVGChildFrame methods
static void
LoopCharacters(cairo_t *aCtx, nsAString &aText, nsSVGCharacterPosition *aCP,
void (*aFunc)(cairo_t *cr, const char *utf8))
{
if (!aCP) {
aFunc(aCtx, NS_ConvertUTF16toUTF8(aText).get());
} else {
for (PRUint32 i = 0; i < aText.Length(); i++) {
/* character actually on the path? */
if (aCP[i].draw == PR_FALSE)
continue;
cairo_matrix_t matrix;
cairo_get_matrix(aCtx, &matrix);
cairo_move_to(aCtx, aCP[i].x, aCP[i].y);
cairo_rotate(aCtx, aCP[i].angle);
aFunc(aCtx, NS_ConvertUTF16toUTF8(Substring(aText, i, 1)).get());
cairo_set_matrix(aCtx, &matrix);
}
}
}
NS_IMETHODIMP
nsSVGGlyphFrame::PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect)
{
#ifdef DEBUG
//printf("nsSVGGlyphFrame(%p)::Paint\n", this);
#endif
if (!GetStyleVisibility()->IsVisible())
return NS_OK;
mGeometry->Render(this, canvas);
nsCOMPtr<nsISVGCairoCanvas> cairoCanvas = do_QueryInterface(canvas);
NS_ASSERTION(cairoCanvas, "wrong svg render context for geometry!");
if (!cairoCanvas) {
return NS_ERROR_FAILURE;
}
nsAutoString text;
GetCharacterData(text);
if (text.IsEmpty()) {
return NS_OK;
}
nsAutoArrayPtr<nsSVGCharacterPosition> cp;
cairo_t *ctx = cairoCanvas->GetContext();
SelectFont(ctx);
nsresult rv = GetCharacterPosition(ctx, getter_Transfers(cp));
PRUint16 renderMode;
cairo_matrix_t matrix;
canvas->GetRenderMode(&renderMode);
if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL) {
/* save/pop the state so we don't screw up the xform */
cairo_save(ctx);
}
else {
cairo_get_matrix(ctx, &matrix);
}
rv = GetGlobalTransform(ctx, cairoCanvas);
if (NS_FAILED(rv)) {
if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL)
cairo_restore(ctx);
return rv;
}
if (!cp)
cairo_move_to(ctx, mX, mY);
if (renderMode != nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL) {
if (GetClipRule() == NS_STYLE_FILL_RULE_EVENODD)
cairo_set_fill_rule(ctx, CAIRO_FILL_RULE_EVEN_ODD);
else
cairo_set_fill_rule(ctx, CAIRO_FILL_RULE_WINDING);
if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_CLIP_MASK) {
cairo_set_antialias(ctx, CAIRO_ANTIALIAS_NONE);
cairo_set_source_rgba(ctx, 1.0f, 1.0f, 1.0f, 1.0f);
LoopCharacters(ctx, text, cp, cairo_show_text);
} else {
LoopCharacters(ctx, text, cp, cairo_text_path);
}
cairo_set_matrix(ctx, &matrix);
return NS_OK;
}
void *closure;
if (HasFill() && NS_SUCCEEDED(SetupCairoFill(canvas, ctx, &closure))) {
LoopCharacters(ctx, text, cp, cairo_show_text);
CleanupCairoFill(ctx, closure);
}
if (HasStroke() && NS_SUCCEEDED(SetupCairoStroke(canvas, ctx, &closure))) {
cairo_new_path(ctx);
if (!cp)
cairo_move_to(ctx, mX, mY);
LoopCharacters(ctx, text, cp, cairo_text_path);
cairo_stroke(ctx);
CleanupCairoStroke(ctx, closure);
cairo_new_path(ctx);
}
cairo_restore(ctx);
return NS_OK;
}
@ -252,7 +313,7 @@ nsSVGGlyphFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
// test for hit:
*hit = nsnull;
if (!mRect.Contains(x, y))
if (!mRect.Contains(nscoord(x), nscoord(y)))
return NS_OK;
PRBool events = PR_FALSE;
@ -289,8 +350,7 @@ nsSVGGlyphFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
if (!events)
return NS_OK;
PRBool isHit;
mGeometry->ContainsPoint(this, x, y, &isHit);
PRBool isHit = ContainsPoint(x, y);
if (isHit)
*hit = this;
@ -306,7 +366,85 @@ nsSVGGlyphFrame::GetCoveredRegion()
NS_IMETHODIMP
nsSVGGlyphFrame::UpdateCoveredRegion()
{
mGeometry->GetCoveredRegion(this, &mRect);
mRect.Empty();
PRBool hasFill = HasFill();
PRBool hasStroke = HasStroke();
if (!hasFill && !hasStroke) {
return NS_OK;
}
nsAutoString text;
GetCharacterData(text);
if (text.IsEmpty()) {
return NS_OK;
}
nsAutoArrayPtr<nsSVGCharacterPosition> cp;
nsSVGAutoGlyphHelperContext ctx(this);
nsresult rv = GetCharacterPosition(ctx, getter_Transfers(cp));
NS_ENSURE_SUCCESS(rv, rv);
rv = GetGlobalTransform(ctx, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
if (!cp)
cairo_move_to(ctx, mX, mY);
if (!cp) {
if (hasStroke) {
cairo_text_path(ctx, NS_ConvertUTF16toUTF8(text).get());
} else {
cairo_text_extents_t extent;
cairo_text_extents(ctx,
NS_ConvertUTF16toUTF8(text).get(),
&extent);
cairo_rectangle(ctx, mX + extent.x_bearing, mY + extent.y_bearing,
extent.width, extent.height);
}
} else {
cairo_matrix_t matrix;
for (PRUint32 i=0; i<text.Length(); i++) {
/* character actually on the path? */
if (cp[i].draw == PR_FALSE)
continue;
cairo_get_matrix(ctx, &matrix);
cairo_move_to(ctx, cp[i].x, cp[i].y);
cairo_rotate(ctx, cp[i].angle);
if (hasStroke) {
cairo_text_path(ctx, NS_ConvertUTF16toUTF8(Substring(text, i, 1)).get());
} else {
cairo_text_extents_t extent;
cairo_text_extents(ctx,
NS_ConvertUTF16toUTF8(Substring(text, i, 1)).get(),
&extent);
cairo_rel_move_to(ctx, extent.x_bearing, extent.y_bearing);
cairo_rel_line_to(ctx, extent.width, 0);
cairo_rel_line_to(ctx, 0, extent.height);
cairo_rel_line_to(ctx, -extent.width, 0);
cairo_close_path(ctx);
}
cairo_set_matrix(ctx, &matrix);
}
}
double xmin, ymin, xmax, ymax;
if (hasStroke) {
SetupCairoStrokeGeometry(ctx);
cairo_stroke_extents(ctx, &xmin, &ymin, &xmax, &ymax);
} else {
cairo_fill_extents(ctx, &xmin, &ymin, &xmax, &ymax);
}
cairo_user_to_device(ctx, &xmin, &ymin);
cairo_user_to_device(ctx, &xmax, &ymax);
mRect = nsSVGUtils::ToBoundingPixelRect(xmin, ymin, xmax, ymax);
return NS_OK;
}
@ -348,9 +486,35 @@ nsSVGGlyphFrame::GetBBox(nsIDOMSVGRect **_retval)
{
*_retval = nsnull;
if (mGeometry)
return mGeometry->GetBoundingBox(this, _retval);
return NS_ERROR_FAILURE;
nsAutoString text;
GetCharacterData(text);
if (text.IsEmpty())
return NS_OK;
nsAutoArrayPtr<nsSVGCharacterPosition> cp;
nsSVGAutoGlyphHelperContext ctx(this);
nsresult rv = GetCharacterPosition(ctx, getter_Transfers(cp));
NS_ENSURE_SUCCESS(rv, rv);
rv = GetGlobalTransform(ctx, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
if (!cp)
cairo_move_to(ctx, mX, mY);
LoopCharacters(ctx, text, cp, cairo_text_path);
double xmin, ymin, xmax, ymax;
cairo_fill_extents(ctx, &xmin, &ymin, &xmax, &ymax);
cairo_user_to_device(ctx, &xmin, &ymin);
cairo_user_to_device(ctx, &xmax, &ymax);
return NS_NewSVGRect(_retval, xmin, ymin, xmax - xmin, ymax - ymin);
}
//----------------------------------------------------------------------
@ -453,37 +617,11 @@ nsSVGGlyphFrame::GetCharacterPosition(cairo_t *ctx,
}
//----------------------------------------------------------------------
// nsISVGGlyphGeometrySource methods:
/* readonly attribute float x; */
NS_IMETHODIMP
nsSVGGlyphFrame::GetX(float *aX)
{
*aX = mX;
return NS_OK;
}
/* readonly attribute float y; */
NS_IMETHODIMP
nsSVGGlyphFrame::GetY(float *aY)
{
*aY = mY;
return NS_OK;
}
/* readonly attribute boolean hasHighlight; */
NS_IMETHODIMP
nsSVGGlyphFrame::GetHasHighlight(PRBool *aHasHighlight)
{
*aHasHighlight = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
return NS_OK;
}
// Utilities for converting from indices in the uncompressed content
// element strings to compressed frame string and back:
int CompressIndex(int index, const nsTextFragment*fragment)
static int
CompressIndex(int index, const nsTextFragment*fragment)
{
int ci=0;
if (fragment->Is2b()) {
@ -522,23 +660,24 @@ int CompressIndex(int index, const nsTextFragment*fragment)
return ci;
}
int UncompressIndex(int index, PRBool bRightAffinity, const nsTextFragment*fragment)
static int
UncompressIndex(int index, PRBool bRightAffinity, const nsTextFragment*fragment)
{
// XXX
return index;
}
/* [noscript] void getHighlight (out unsigned long charnum, out unsigned long nchars, out nscolor foreground, out nscolor background); */
NS_IMETHODIMP
nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars, nscolor *foreground, nscolor *background)
nsresult
nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
nscolor *foreground, nscolor *background)
{
*foreground = NS_RGB(255,255,255);
*background = NS_RGB(0,0,0);
*charnum=0;
*nchars=0;
PRBool hasHighlight;
GetHasHighlight(&hasHighlight);
PRBool hasHighlight =
(mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
if (!hasHighlight) {
NS_ERROR("nsSVGGlyphFrame::GetHighlight() called by renderer when there is no highlight");
@ -1232,7 +1371,7 @@ void nsSVGGlyphFrame::UpdateGeometry(PRBool bRedraw,
return;
outerSVGFrame->InvalidateRect(mRect);
mGeometry->GetCoveredRegion(this, &mRect);
UpdateCoveredRegion();
nsRect filterRect;
filterRect = nsSVGUtils::FindFilterInvalidation(this);
@ -1276,6 +1415,92 @@ nsSVGGlyphFrame::GetTextFrame()
return containerFrame->GetTextFrame();
}
PRBool
nsSVGGlyphFrame::ContainsPoint(float x, float y)
{
nsAutoString text;
GetCharacterData(text);
if (text.IsEmpty())
return PR_FALSE;
nsAutoArrayPtr<nsSVGCharacterPosition> cp;
nsSVGAutoGlyphHelperContext ctx(this);
nsresult rv = GetCharacterPosition(ctx, getter_Transfers(cp));
NS_ENSURE_SUCCESS(rv, PR_FALSE);
rv = GetGlobalTransform(ctx, nsnull);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
float xx = 0, yy = 0;
if (!cp) {
xx = mX;
yy = mY;
}
cairo_matrix_t matrix;
for (PRUint32 i = 0; i < text.Length(); i++) {
/* character actually on the path? */
if (cp && cp[i].draw == PR_FALSE)
continue;
cairo_get_matrix(ctx, &matrix);
if (cp) {
cairo_move_to(ctx, cp[i].x, cp[i].y);
cairo_rotate(ctx, cp[i].angle);
} else {
cairo_move_to(ctx, xx, yy);
}
cairo_text_extents_t extent;
cairo_text_extents(ctx,
NS_ConvertUTF16toUTF8(Substring(text, i, 1)).get(),
&extent);
cairo_rel_move_to(ctx, extent.x_bearing, extent.y_bearing);
cairo_rel_line_to(ctx, extent.width, 0);
cairo_rel_line_to(ctx, 0, extent.height);
cairo_rel_line_to(ctx, -extent.width, 0);
cairo_close_path(ctx);
cairo_set_matrix(ctx, &matrix);
if (!cp) {
xx += extent.x_advance;
yy += extent.y_advance;
}
}
cairo_identity_matrix(ctx);
return cairo_in_fill(ctx, x, y);
}
nsresult
nsSVGGlyphFrame::GetGlobalTransform(cairo_t *ctx,
nsISVGCairoCanvas* aCanvas)
{
nsCOMPtr<nsIDOMSVGMatrix> ctm;
GetCanvasTM(getter_AddRefs(ctm));
NS_ASSERTION(ctm, "graphic source didn't specify a ctm");
cairo_matrix_t matrix = NS_ConvertSVGMatrixToCairo(ctm);
if (aCanvas) {
aCanvas->AdjustMatrixForInitialTransform(&matrix);
}
cairo_matrix_t inverse = matrix;
if (cairo_matrix_invert(&inverse)) {
cairo_identity_matrix(ctx);
return NS_ERROR_FAILURE;
}
cairo_set_matrix(ctx, &matrix);
return NS_OK;
}
//----------------------------------------------------------------------
// helper class

Просмотреть файл

@ -40,13 +40,12 @@
#define __NS_SVGGLYPHFRAME_H__
#include "nsSVGGeometryFrame.h"
#include "nsISVGGlyphGeometrySource.h"
#include "nsISVGGlyphFragmentLeaf.h"
#include "nsISVGChildFrame.h"
#include "nsISVGRendererGlyphGeometry.h"
class nsSVGTextFrame;
class nsSVGGlyphFrame;
class nsISVGCairoCanvas;
struct nsSVGCharacterPosition {
PRBool draw;
@ -77,7 +76,6 @@ private:
typedef nsSVGGeometryFrame nsSVGGlyphFrameBase;
class nsSVGGlyphFrame : public nsSVGGlyphFrameBase,
public nsISVGGlyphGeometrySource,
public nsISVGGlyphFragmentLeaf, // : nsISVGGlyphFragmentNode
public nsISVGChildFrame
{
@ -94,11 +92,6 @@ public:
NS_IMETHOD_(nsrefcnt) Release() { return 1; }
// nsIFrame interface:
NS_IMETHOD
Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow);
NS_IMETHOD CharacterDataChanged(nsPresContext* aPresContext,
nsIContent* aChild,
PRBool aAppend);
@ -146,9 +139,6 @@ public:
NS_IMETHOD GetCanvasTM(nsIDOMSVGMatrix * *aCTM);
virtual nsresult UpdateGraphic(PRBool suppressInvalidation = PR_FALSE);
// nsISVGGlyphGeometrySource interface:
NS_DECL_NSISVGGLYPHGEOMETRYSOURCE
// nsISVGGlyphFragmentLeaf interface:
NS_IMETHOD GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval);
NS_IMETHOD GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval);
@ -190,8 +180,11 @@ protected:
void UpdateMetrics();
void UpdateFragmentTree();
nsSVGTextFrame *GetTextFrame();
nsCOMPtr<nsISVGRendererGlyphGeometry> mGeometry;
PRBool ContainsPoint(float x, float y);
nsresult GetGlobalTransform(cairo_t *ctx, nsISVGCairoCanvas *aCanvas);
nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
nscolor *foreground, nscolor *background);
float mX, mY;
PRUint8 mWhitespaceHandling;
PRPackedBool mFragmentTreeDirty;

Просмотреть файл

@ -121,25 +121,6 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGPathGeometryFrameBase)
//----------------------------------------------------------------------
// nsIFrame methods
NS_IMETHODIMP
nsSVGPathGeometryFrame::Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow)
{
mContent = aContent;
NS_IF_ADDREF(mContent);
mParent = aParent;
if (mContent) {
mContent->SetMayHaveFrame(PR_TRUE);
}
InitSVG();
DidSetStyleContext();
return NS_OK;
}
NS_IMETHODIMP
nsSVGPathGeometryFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,

Просмотреть файл

@ -72,11 +72,6 @@ public:
NS_IMETHOD_(nsrefcnt) Release() { return 1; }
// nsIFrame interface:
NS_IMETHOD
Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow);
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);

Просмотреть файл

@ -45,10 +45,8 @@ MODULE = layout
XPIDL_MODULE = gksvgrenderer
XPIDLSRCS = \
nsISVGGlyphGeometrySource.idl \
nsISVGRenderer.idl \
nsISVGRendererCanvas.idl \
nsISVGRendererGlyphGeometry.idl \
nsISVGRendererSurface.idl \
$(NULL)

Просмотреть файл

@ -1,79 +0,0 @@
/* -*- Mode: IDL; 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) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex@croczilla.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 ***** */
#include "nsISupports.idl"
native nscolor(nscolor);
/**
* \addtogroup rendering_backend_interfaces Rendering Backend Interfaces
* @{
*/
/**
* Abstracts a description of a 'composite glyph' (character string
* with associated font and styling information) in the SVG rendering
* backend for use by a rendering engine's nsISVGRendererGlyphGeometry
* objects. This interface contains absolute positioning and other
* information, such as e.g. individual character highlighting,
* which doesn't affect the actual metrics of the glyph.
*
* @nosubgrouping
*/
[uuid(2d27485b-b147-4601-b0c4-fcd440145cab)]
interface nsISVGGlyphGeometrySource : nsISupports
{
/**
* @name Glyph start position
* @{
*/
readonly attribute float x; // start position of glyph *before* applying CanvasTM
readonly attribute float y;
/** @} */
/**
* @name Partial highlighting for selection feedback
* @{
*/
readonly attribute boolean hasHighlight;
void getHighlight(out unsigned long charnum, out unsigned long nchars,
out nscolor foreground, out nscolor background);
/** @} */
};
/** @} */

Просмотреть файл

@ -44,8 +44,6 @@ struct nsRect;
[ref] native nsRectRef(nsRect);
interface nsISVGRendererGlyphGeometry;
interface nsISVGRendererCanvas;
interface nsISVGRendererSurface;
interface nsIRenderingContext;
@ -70,18 +68,11 @@ interface nsPresContext;
* cross-platform libart engine
* ("@mozilla.org/svg/renderer;1?tech=LIBART").
*/
[uuid(A128A973-FE67-49be-8AEA-2C4FECF3DA34)]
[uuid(6f9315c2-f06d-47d7-bef1-4ad7ad0b1558)]
interface nsISVGRenderer : nsISupports
{
// void Init(in nsPresContext presContext);
/**
* Create a rendering engine-native glyph geometry object.
*
* @return A rendering engine-native glyph geometry object.
*/
nsISVGRendererGlyphGeometry createGlyphGeometry();
/**
* Create a rendering engine-native canvas object for the
* Mozilla-native rendering context 'ctx' and presentation context

Просмотреть файл

@ -1,108 +0,0 @@
/* -*- Mode: IDL; 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) 2002
* 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 ***** */
#include "nsISupports.idl"
%{C++
struct nsRect;
%}
native nsRect(nsRect);
interface nsISVGRendererRegion;
interface nsISVGRendererCanvas;
interface nsIDOMSVGRect;
interface nsSVGGlyphFrame;
/**
* \addtogroup renderer_interfaces Rendering Engine Interfaces
* @{
*/
/**
* One of a number of interfaces (all starting with nsISVGRenderer*)
* to be implemented by an SVG rendering engine. See nsISVGRenderer
* for more details.
*
* The SVG rendering backend uses this interface to communicate to the
* rendering engine-native glyph objects.
*
* A glyph object is instantiated by the rendering backend for a given
* nsISVGGlyphGeometrySource object with a call to
* nsISVGRenderer::createGlyphGeometry(). The glyph object is assumed
* to store a reference to its associated source object and provide
* glyph rendering and hit-testing for the (composite) glyph described
* by the nsISVGGlyphGeometrySource members.
*/
[uuid(80cb7a0d-0f0b-4624-8e03-e7ca932a2321)]
interface nsISVGRendererGlyphGeometry : nsISupports
{
/**
* Paint this object.
*
* @param canvas The canvas to render to.
*/
void render(in nsSVGGlyphFrame source, in nsISVGRendererCanvas canvas);
/**
* Get a region object describing the area covered with paint by
* this glyph geometry.
*
* @return Covered region.
*/
void getCoveredRegion(in nsSVGGlyphFrame source, out nsRect rect);
/**
* Hit-testing method. Does this glyph geometry (with all relevant
* transformations applied) contain the point x,y? Should work on a
* character-cell basis, rather than the actual character outline.
*
* @param x X-coordinate of test point. @param y Y-coordinate of
* test point.
* @return PR_TRUE if the glyph geometry contains the point,
* PR_FALSE otherwise.
*/
boolean containsPoint(in nsSVGGlyphFrame source, in float x, in float y);
/**
* Transformed bounding box (does not include stroke width)
*/
void getBoundingBox(in nsSVGGlyphFrame source, out nsIDOMSVGRect box);
};
/** @} */

Просмотреть файл

@ -74,7 +74,6 @@ REQUIRES = \
CPPSRCS = \
nsSVGRendererCairo.cpp \
nsSVGCairoCanvas.cpp \
nsSVGCairoGlyphGeometry.cpp \
nsSVGCairoSurface.cpp \
$(NULL)

Просмотреть файл

@ -1,457 +0,0 @@
/* -*- 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 Cairo Renderer project.
*
* The Initial Developer of the Original Code is IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Parts of this file contain code derived from the following files(s)
* of the Mozilla SVG project (these parts are Copyright (C) by their
* respective copyright-holders):
* layout/svg/renderer/src/gdiplus/nsSVGGDIPlusGlyphGeometry.cpp
*
* Contributor(s):
*
* 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 ***** */
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsSVGCairoGlyphGeometry.h"
#include "nsISVGRendererGlyphGeometry.h"
#include "nsISVGCairoCanvas.h"
#include "nsIDOMSVGMatrix.h"
#include "nsPromiseFlatString.h"
#include "nsPresContext.h"
#include "nsMemory.h"
#include <cairo.h>
#include "nsIDOMSVGRect.h"
#include "nsSVGRect.h"
#include "nsSVGGlyphFrame.h"
#include "nsSVGMatrix.h"
#include "nsSVGUtils.h"
/**
* \addtogroup cairo_renderer cairo Rendering Engine
* @{
*/
////////////////////////////////////////////////////////////////////////
/**
* cairo glyph geometry implementation
*/
class nsSVGCairoGlyphGeometry : public nsISVGRendererGlyphGeometry
{
protected:
friend nsresult NS_NewSVGCairoGlyphGeometry(nsISVGRendererGlyphGeometry **result);
nsresult GetGlobalTransform(nsSVGGlyphFrame *aSource,
cairo_t *ctx, nsISVGCairoCanvas* aCanvas);
public:
// nsISupports interface:
NS_DECL_ISUPPORTS
// nsISVGRendererGlyphGeometry interface:
NS_DECL_NSISVGRENDERERGLYPHGEOMETRY
};
/** @} */
//----------------------------------------------------------------------
// implementation:
nsresult
NS_NewSVGCairoGlyphGeometry(nsISVGRendererGlyphGeometry **result)
{
*result = new nsSVGCairoGlyphGeometry;
if (!*result) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*result);
return NS_OK;
}
//----------------------------------------------------------------------
// nsISupports methods:
NS_IMPL_ADDREF(nsSVGCairoGlyphGeometry)
NS_IMPL_RELEASE(nsSVGCairoGlyphGeometry)
NS_INTERFACE_MAP_BEGIN(nsSVGCairoGlyphGeometry)
NS_INTERFACE_MAP_ENTRY(nsISVGRendererGlyphGeometry)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
// nsISVGRendererGlyphGeometry methods:
static void
LoopCharacters(cairo_t *aCtx, nsAString &aText, nsSVGCharacterPosition *aCP,
void (*aFunc)(cairo_t *cr, const char *utf8))
{
if (!aCP) {
aFunc(aCtx, NS_ConvertUTF16toUTF8(aText).get());
} else {
for (PRUint32 i = 0; i < aText.Length(); i++) {
/* character actually on the path? */
if (aCP[i].draw == PR_FALSE)
continue;
cairo_matrix_t matrix;
cairo_get_matrix(aCtx, &matrix);
cairo_move_to(aCtx, aCP[i].x, aCP[i].y);
cairo_rotate(aCtx, aCP[i].angle);
aFunc(aCtx, NS_ConvertUTF16toUTF8(Substring(aText, i, 1)).get());
cairo_set_matrix(aCtx, &matrix);
}
}
}
/** Implements void render(in nsISVGRendererCanvas canvas); */
NS_IMETHODIMP
nsSVGCairoGlyphGeometry::Render(nsSVGGlyphFrame *aSource,
nsISVGRendererCanvas *canvas)
{
nsCOMPtr<nsISVGCairoCanvas> cairoCanvas = do_QueryInterface(canvas);
NS_ASSERTION(cairoCanvas, "wrong svg render context for geometry!");
if (!cairoCanvas) {
return NS_ERROR_FAILURE;
}
nsAutoString text;
aSource->GetCharacterData(text);
if (text.IsEmpty()) {
return NS_OK;
}
nsAutoArrayPtr<nsSVGCharacterPosition> cp;
cairo_t *ctx = cairoCanvas->GetContext();
aSource->SelectFont(ctx);
nsresult rv = aSource->GetCharacterPosition(ctx, getter_Transfers(cp));
PRUint16 renderMode;
cairo_matrix_t matrix;
canvas->GetRenderMode(&renderMode);
if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL) {
/* save/pop the state so we don't screw up the xform */
cairo_save(ctx);
}
else {
cairo_get_matrix(ctx, &matrix);
}
rv = GetGlobalTransform(aSource, ctx, cairoCanvas);
if (NS_FAILED(rv)) {
if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL)
cairo_restore(ctx);
return rv;
}
float x,y;
if (!cp) {
aSource->GetX(&x);
aSource->GetY(&y);
cairo_move_to(ctx, x, y);
}
if (renderMode != nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL) {
if (aSource->GetClipRule() == NS_STYLE_FILL_RULE_EVENODD)
cairo_set_fill_rule(ctx, CAIRO_FILL_RULE_EVEN_ODD);
else
cairo_set_fill_rule(ctx, CAIRO_FILL_RULE_WINDING);
if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_CLIP_MASK) {
cairo_set_antialias(ctx, CAIRO_ANTIALIAS_NONE);
cairo_set_source_rgba(ctx, 1.0f, 1.0f, 1.0f, 1.0f);
LoopCharacters(ctx, text, cp, cairo_show_text);
} else {
LoopCharacters(ctx, text, cp, cairo_text_path);
}
cairo_set_matrix(ctx, &matrix);
return NS_OK;
}
void *closure;
if (aSource->HasFill() &&
NS_SUCCEEDED(aSource->SetupCairoFill(canvas, ctx, &closure))) {
LoopCharacters(ctx, text, cp, cairo_show_text);
aSource->CleanupCairoFill(ctx, closure);
}
if (aSource->HasStroke() &&
NS_SUCCEEDED(aSource->SetupCairoStroke(canvas, ctx, &closure))) {
cairo_new_path(ctx);
if (!cp)
cairo_move_to(ctx, x, y);
LoopCharacters(ctx, text, cp, cairo_text_path);
cairo_stroke(ctx);
aSource->CleanupCairoStroke(ctx, closure);
cairo_new_path(ctx);
}
cairo_restore(ctx);
return NS_OK;
}
NS_IMETHODIMP
nsSVGCairoGlyphGeometry::GetCoveredRegion(nsSVGGlyphFrame *aSource,
nsRect *aRect)
{
aRect->Empty();
PRBool hasFill = aSource->HasFill();
PRBool hasStroke = aSource->HasStroke();
if (!hasFill && !hasStroke) {
return NS_OK;
}
nsAutoString text;
aSource->GetCharacterData(text);
if (text.IsEmpty()) {
return NS_OK;
}
nsAutoArrayPtr<nsSVGCharacterPosition> cp;
nsSVGAutoGlyphHelperContext ctx(aSource);
nsresult rv = aSource->GetCharacterPosition(ctx, getter_Transfers(cp));
NS_ENSURE_SUCCESS(rv, rv);
rv = GetGlobalTransform(aSource, ctx, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
float x,y;
if (!cp) {
aSource->GetX(&x);
aSource->GetY(&y);
cairo_move_to(ctx, x, y);
} else {
x = 0.0, y = 0.0;
}
if (!cp) {
if (hasStroke) {
cairo_text_path(ctx, NS_ConvertUTF16toUTF8(text).get());
} else {
cairo_text_extents_t extent;
cairo_text_extents(ctx,
NS_ConvertUTF16toUTF8(text).get(),
&extent);
cairo_rectangle(ctx, x + extent.x_bearing, y + extent.y_bearing,
extent.width, extent.height);
}
} else {
cairo_matrix_t matrix;
for (PRUint32 i=0; i<text.Length(); i++) {
/* character actually on the path? */
if (cp[i].draw == PR_FALSE)
continue;
cairo_get_matrix(ctx, &matrix);
cairo_move_to(ctx, cp[i].x, cp[i].y);
cairo_rotate(ctx, cp[i].angle);
if (hasStroke) {
cairo_text_path(ctx, NS_ConvertUTF16toUTF8(Substring(text, i, 1)).get());
} else {
cairo_text_extents_t extent;
cairo_text_extents(ctx,
NS_ConvertUTF16toUTF8(Substring(text, i, 1)).get(),
&extent);
cairo_rel_move_to(ctx, extent.x_bearing, extent.y_bearing);
cairo_rel_line_to(ctx, extent.width, 0);
cairo_rel_line_to(ctx, 0, extent.height);
cairo_rel_line_to(ctx, -extent.width, 0);
cairo_close_path(ctx);
}
cairo_set_matrix(ctx, &matrix);
}
}
double xmin, ymin, xmax, ymax;
if (hasStroke) {
aSource->SetupCairoStrokeGeometry(ctx);
cairo_stroke_extents(ctx, &xmin, &ymin, &xmax, &ymax);
} else {
cairo_fill_extents(ctx, &xmin, &ymin, &xmax, &ymax);
}
cairo_user_to_device(ctx, &xmin, &ymin);
cairo_user_to_device(ctx, &xmax, &ymax);
*aRect = nsSVGUtils::ToBoundingPixelRect(xmin, ymin, xmax, ymax);
return NS_OK;
}
/** Implements boolean containsPoint(in float x, in float y); */
NS_IMETHODIMP
nsSVGCairoGlyphGeometry::ContainsPoint(nsSVGGlyphFrame *aSource,
float x, float y, PRBool *_retval)
{
*_retval = PR_FALSE;
nsAutoString text;
aSource->GetCharacterData(text);
if (text.IsEmpty()) {
return NS_OK;
}
nsAutoArrayPtr<nsSVGCharacterPosition> cp;
nsSVGAutoGlyphHelperContext ctx(aSource);
nsresult rv = aSource->GetCharacterPosition(ctx, getter_Transfers(cp));
NS_ENSURE_SUCCESS(rv, rv);
rv = GetGlobalTransform(aSource, ctx, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
float xx, yy;
if (!cp) {
aSource->GetX(&xx);
aSource->GetY(&yy);
}
cairo_matrix_t matrix;
for (PRUint32 i=0; i<text.Length(); i++) {
/* character actually on the path? */
if (cp && cp[i].draw == PR_FALSE)
continue;
cairo_get_matrix(ctx, &matrix);
if (cp) {
cairo_move_to(ctx, cp[i].x, cp[i].y);
cairo_rotate(ctx, cp[i].angle);
} else {
cairo_move_to(ctx, xx, yy);
}
cairo_text_extents_t extent;
cairo_text_extents(ctx,
NS_ConvertUTF16toUTF8(Substring(text, i, 1)).get(),
&extent);
cairo_rel_move_to(ctx, extent.x_bearing, extent.y_bearing);
cairo_rel_line_to(ctx, extent.width, 0);
cairo_rel_line_to(ctx, 0, extent.height);
cairo_rel_line_to(ctx, -extent.width, 0);
cairo_close_path(ctx);
cairo_set_matrix(ctx, &matrix);
if (!cp) {
xx += extent.x_advance;
yy += extent.y_advance;
}
}
cairo_identity_matrix(ctx);
*_retval = cairo_in_fill(ctx, x, y);
return NS_OK;
}
nsresult
nsSVGCairoGlyphGeometry::GetGlobalTransform(nsSVGGlyphFrame *aSource,
cairo_t *ctx,
nsISVGCairoCanvas* aCanvas)
{
nsCOMPtr<nsIDOMSVGMatrix> ctm;
aSource->GetCanvasTM(getter_AddRefs(ctm));
NS_ASSERTION(ctm, "graphic source didn't specify a ctm");
cairo_matrix_t matrix = NS_ConvertSVGMatrixToCairo(ctm);
if (aCanvas) {
aCanvas->AdjustMatrixForInitialTransform(&matrix);
}
cairo_matrix_t inverse = matrix;
if (cairo_matrix_invert(&inverse)) {
cairo_identity_matrix(ctx);
return NS_ERROR_FAILURE;
}
cairo_set_matrix(ctx, &matrix);
return NS_OK;
}
NS_IMETHODIMP
nsSVGCairoGlyphGeometry::GetBoundingBox(nsSVGGlyphFrame *aSource,
nsIDOMSVGRect * *aBoundingBox)
{
*aBoundingBox = nsnull;
nsAutoString text;
aSource->GetCharacterData(text);
if (text.IsEmpty()) {
return NS_OK;
}
nsAutoArrayPtr<nsSVGCharacterPosition> cp;
nsSVGAutoGlyphHelperContext ctx(aSource);
nsresult rv = aSource->GetCharacterPosition(ctx, getter_Transfers(cp));
NS_ENSURE_SUCCESS(rv, rv);
rv = GetGlobalTransform(aSource, ctx, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
float x,y;
if (!cp) {
aSource->GetX(&x);
aSource->GetY(&y);
cairo_move_to(ctx, x, y);
}
LoopCharacters(ctx, text, cp, cairo_text_path);
double xmin, ymin, xmax, ymax;
cairo_fill_extents(ctx, &xmin, &ymin, &xmax, &ymax);
cairo_user_to_device(ctx, &xmin, &ymin);
cairo_user_to_device(ctx, &xmax, &ymax);
return NS_NewSVGRect(aBoundingBox, xmin, ymin, xmax - xmin, ymax - ymin);
}

Просмотреть файл

@ -98,13 +98,6 @@ NS_IMPL_ISUPPORTS1(nsSVGRendererCairo, nsISVGRenderer)
//----------------------------------------------------------------------
// nsISVGRenderer methods
/** Implements nsISVGRendererGlyphGeometry createGlyphGeometry; */
NS_IMETHODIMP
nsSVGRendererCairo::CreateGlyphGeometry(nsISVGRendererGlyphGeometry **_retval)
{
return NS_NewSVGCairoGlyphGeometry(_retval);
}
/** Implements [noscript] nsISVGRendererCanvas createCanvas(in nsIRenderingContext ctx,
in nsPresContext presContext, const in nsRectRef dirtyRect); */
NS_IMETHODIMP