1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ----- BEGIN LICENSE BLOCK -----
3
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Mozilla Public License
6
* Version 1.1 (the "License"); you may not use this file except in
7
* compliance with the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/MPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is the Mozilla SVG project.
17
* The Initial Developer of the Original Code is
18
* Crocodile Clips Ltd..
19
* Portions created by the Initial Developer are Copyright (C) 2002
20
* the Initial Developer. All Rights Reserved.
23
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
25
* Alternatively, the contents of this file may be used under the terms of
26
* either the GNU General Public License Version 2 or later (the "GPL"), or
27
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
* in which case the provisions of the GPL or the LGPL are applicable instead
29
* of those above. If you wish to allow use of your version of this file only
30
* under the terms of either the GPL or the LGPL, and not to allow others to
31
* use your version of this file under the terms of the NPL, indicate your
32
* decision by deleting the provisions above and replace them with the notice
33
* and other provisions required by the GPL or the LGPL. If you do not delete
34
* the provisions above, a recipient may use your version of this file under
35
* the terms of any one of the MPL, the GPL or the LGPL.
37
* ----- END LICENSE BLOCK ----- */
40
#include "nsISVGRendererGlyphGeometry.h"
41
#include "nsISVGRendererGlyphMetrics.h"
42
#include "nsISVGRenderer.h"
43
#include "nsISVGGlyphGeometrySource.h"
44
#include "nsISVGGlyphFragmentLeaf.h"
45
#include "nsITextContent.h"
46
#include "nsISVGChildFrame.h"
47
#include "nsISVGOuterSVGFrame.h"
48
#include "nsISVGTextFrame.h"
49
#include "nsISVGRendererRegion.h"
50
#include "nsISVGContainerFrame.h"
51
#include "nsISVGTextContainerFrame.h"
52
#include "nsReadableUtils.h"
55
#include "nsIDOMSVGRect.h"
56
#include "nsILookAndFeel.h"
57
#include "nsTextFragment.h"
59
typedef nsFrame nsSVGGlyphFrameBase;
61
class nsSVGGlyphFrame : public nsSVGGlyphFrameBase,
62
public nsISVGGlyphGeometrySource, // : nsISVGGlyphMetricsSource : nsISVGGeometrySource
63
public nsISVGGlyphFragmentLeaf, // : nsISVGGlyphFragmentNode
64
public nsISVGChildFrame
68
NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsIContent* aContent,
69
nsIFrame* parentFrame, nsIFrame** aNewFrame);
71
virtual ~nsSVGGlyphFrame();
74
// nsISupports interface:
75
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
76
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
77
NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
79
// nsIFrame interface:
81
Init(nsIPresContext* aPresContext,
84
nsStyleContext* aContext,
85
nsIFrame* aPrevInFlow);
87
NS_IMETHOD CharacterDataChanged(nsIPresContext* aPresContext,
91
NS_IMETHOD SetSelected(nsIPresContext* aPresContext,
95
NS_IMETHOD GetSelected(PRBool *aSelected) const;
96
NS_IMETHOD IsSelectable(PRBool* aIsSelectable, PRUint8* aSelectStyle);
98
// nsISVGChildFrame interface:
99
NS_IMETHOD Paint(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips);
100
NS_IMETHOD GetFrameForPoint(float x, float y, nsIFrame** hit);
101
NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
102
NS_IMETHOD InitialUpdate();
103
NS_IMETHOD NotifyCTMChanged();
104
NS_IMETHOD NotifyRedrawSuspended();
105
NS_IMETHOD NotifyRedrawUnsuspended();
106
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
108
// nsISVGGeometrySource interface:
109
NS_DECL_NSISVGGEOMETRYSOURCE
111
// nsISVGGlyphMetricsSource interface:
112
NS_DECL_NSISVGGLYPHMETRICSSOURCE
114
// nsISVGGlyphGeometrySource interface:
115
NS_DECL_NSISVGGLYPHGEOMETRYSOURCE
117
// nsISVGGlyphFragmentLeaf interface:
118
NS_IMETHOD_(void) SetGlyphPosition(float x, float y);
119
NS_IMETHOD_(float) GetGlyphPositionX();
120
NS_IMETHOD_(float) GetGlyphPositionY();
121
NS_IMETHOD GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics);
122
NS_IMETHOD_(PRBool) IsStartOfChunk(); // == is new absolutely positioned chunk.
123
NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y);
124
NS_IMETHOD_(PRUint32) GetNumberOfChars();
125
NS_IMETHOD_(PRUint32) GetCharNumberOffset();
127
// nsISVGGlyphFragmentNode interface:
128
NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetFirstGlyphFragment();
129
NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetNextGlyphFragment();
130
NS_IMETHOD_(PRUint32) BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch);
131
NS_IMETHOD_(void) NotifyMetricsSuspended();
132
NS_IMETHOD_(void) NotifyMetricsUnsuspended();
133
NS_IMETHOD_(void) NotifyGlyphFragmentTreeSuspended();
134
NS_IMETHOD_(void) NotifyGlyphFragmentTreeUnsuspended();
137
void UpdateGeometry(PRUint32 flags, PRBool bRedraw=PR_TRUE);
138
void UpdateMetrics(PRUint32 flags);
139
void UpdateFragmentTree();
140
nsISVGOuterSVGFrame *GetOuterSVGFrame();
141
nsISVGTextFrame *GetTextFrame();
143
nsCOMPtr<nsISVGRendererGlyphGeometry> mGeometry;
144
nsCOMPtr<nsISVGRendererGlyphMetrics> mMetrics;
146
PRUint32 mCharOffset;
147
PRUint32 mGeometryUpdateFlags;
148
PRUint32 mMetricsUpdateFlags;
149
PRBool mFragmentTreeDirty;
150
nsString mCharacterData;
153
//----------------------------------------------------------------------
157
NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* parentFrame,
158
nsIFrame** aNewFrame)
163
NS_ASSERTION(parentFrame, "null parent");
164
nsISVGTextContainerFrame *text_container;
165
parentFrame->QueryInterface(NS_GET_IID(nsISVGTextContainerFrame), (void**)&text_container);
166
NS_ASSERTION(text_container, "trying to construct an SVGGlyphFrame for an invalid container");
168
nsCOMPtr<nsITextContent> tc = do_QueryInterface(aContent);
169
NS_ASSERTION(tc, "trying to construct an SVGGlyphFrame for wrong content element");
172
nsSVGGlyphFrame* it = new (aPresShell) nsSVGGlyphFrame;
174
return NS_ERROR_OUT_OF_MEMORY;
181
nsSVGGlyphFrame::nsSVGGlyphFrame()
182
: mGeometryUpdateFlags(0), mMetricsUpdateFlags(0),
183
mCharOffset(0), mFragmentTreeDirty(PR_FALSE)
187
nsSVGGlyphFrame::~nsSVGGlyphFrame()
193
//----------------------------------------------------------------------
194
// nsISupports methods
196
NS_INTERFACE_MAP_BEGIN(nsSVGGlyphFrame)
197
NS_INTERFACE_MAP_ENTRY(nsISVGGeometrySource)
198
NS_INTERFACE_MAP_ENTRY(nsISVGGlyphMetricsSource)
199
NS_INTERFACE_MAP_ENTRY(nsISVGGlyphGeometrySource)
200
NS_INTERFACE_MAP_ENTRY(nsISVGGlyphFragmentLeaf)
201
NS_INTERFACE_MAP_ENTRY(nsISVGGlyphFragmentNode)
202
NS_INTERFACE_MAP_ENTRY(nsISVGChildFrame)
203
NS_INTERFACE_MAP_END_INHERITING(nsSVGGlyphFrameBase)
205
//----------------------------------------------------------------------
209
nsSVGGlyphFrame::Init(nsIPresContext* aPresContext,
210
nsIContent* aContent,
212
nsStyleContext* aContext,
213
nsIFrame* aPrevInFlow)
215
// rv = nsSVGGlyphFrameBase::Init(aPresContext, aContent, aParent,
216
// aContext, aPrevInFlow);
219
NS_IF_ADDREF(mContent);
222
// construct our glyphmetrics & glyphgeometry objects:
223
nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
224
if (!outerSVGFrame) {
225
NS_ERROR("No outerSVGFrame");
226
return NS_ERROR_FAILURE;
228
nsCOMPtr<nsISVGRenderer> renderer;
229
outerSVGFrame->GetRenderer(getter_AddRefs(renderer));
231
renderer->CreateGlyphMetrics(this, getter_AddRefs(mMetrics));
232
if (!mMetrics) return NS_ERROR_FAILURE;
234
renderer->CreateGlyphGeometry(this, getter_AddRefs(mGeometry));
235
if (!mGeometry) return NS_ERROR_FAILURE;
238
SetStyleContext(aPresContext, aContext);
244
nsSVGGlyphFrame::CharacterDataChanged(nsIPresContext* aPresContext,
249
// printf("** nsSVGGlyphFrame::CharacterDataChanged\n");
251
nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
252
if (!outerSVGFrame) {
253
NS_ERROR("No outerSVGFrame");
254
return NS_ERROR_FAILURE;
257
outerSVGFrame->SuspendRedraw();
258
UpdateFragmentTree();
259
UpdateMetrics(nsISVGGeometrySource::UPDATEMASK_ALL);
260
UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_ALL);
261
outerSVGFrame->UnsuspendRedraw();
267
nsSVGGlyphFrame::SetSelected(nsIPresContext* aPresContext,
272
#if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
273
printf("nsSVGGlyphFrame(%p)::SetSelected()\n", this);
275
// return nsSVGGlyphFrameBase::SetSelected(aPresContext, aRange, aSelected, aSpread);
277
// check whether style allows selection
279
IsSelectable(&selectable, nsnull);
284
mState |= NS_FRAME_SELECTED_CONTENT;
287
mState &= ~NS_FRAME_SELECTED_CONTENT;
289
UpdateGeometry(nsISVGGlyphGeometrySource::UPDATEMASK_HIGHLIGHT |
290
nsISVGGlyphGeometrySource::UPDATEMASK_HAS_HIGHLIGHT,
297
nsSVGGlyphFrame::GetSelected(PRBool *aSelected) const
299
nsresult rv = nsSVGGlyphFrameBase::GetSelected(aSelected);
300
#if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
301
printf("nsSVGGlyphFrame(%p)::GetSelected()=%d\n", this, *aSelected);
307
nsSVGGlyphFrame::IsSelectable(PRBool* aIsSelectable,
308
PRUint8* aSelectStyle)
310
nsresult rv = nsSVGGlyphFrameBase::IsSelectable(aIsSelectable, aSelectStyle);
311
#if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
312
printf("nsSVGGlyphFrame(%p)::IsSelectable()=(%d,%d)\n", this, *aIsSelectable, aSelectStyle);
318
//----------------------------------------------------------------------
319
// nsISVGChildFrame methods
322
nsSVGGlyphFrame::Paint(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips)
325
//printf("nsSVGGlyphFrame(%p)::Paint\n", this);
327
mGeometry->Render(canvas);
332
nsSVGGlyphFrame::GetFrameForPoint(float x, float y, nsIFrame** hit)
335
//printf("nsSVGGlyphFrame(%p)::GetFrameForPoint\n", this);
340
mGeometry->ContainsPoint(x, y, &isHit);
347
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
348
nsSVGGlyphFrame::GetCoveredRegion()
350
nsISVGRendererRegion *region = nsnull;
351
mGeometry->GetCoveredRegion(®ion);
356
nsSVGGlyphFrame::InitialUpdate()
358
nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
359
if (!outerSVGFrame) {
360
NS_ERROR("No outerSVGFrame");
361
return NS_ERROR_FAILURE;
364
outerSVGFrame->SuspendRedraw();
365
UpdateFragmentTree();
366
UpdateMetrics(nsISVGGeometrySource::UPDATEMASK_ALL);
367
UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_ALL);
368
outerSVGFrame->UnsuspendRedraw();
374
nsSVGGlyphFrame::NotifyCTMChanged()
376
UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_CTM);
382
nsSVGGlyphFrame::NotifyRedrawSuspended()
384
// XXX should we cache the fact that redraw is suspended?
389
nsSVGGlyphFrame::NotifyRedrawUnsuspended()
391
NS_ASSERTION(!mMetricsUpdateFlags, "dirty metrics in nsSVGGlyphFrame::NotifyRedrawUnsuspended");
392
NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::NotifyRedrawUnsuspended");
394
if (mGeometryUpdateFlags != 0) {
395
nsCOMPtr<nsISVGRendererRegion> dirty_region;
396
mGeometry->Update(mGeometryUpdateFlags, getter_AddRefs(dirty_region));
398
nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
400
outerSVGFrame->InvalidateRegion(dirty_region, PR_TRUE);
402
mGeometryUpdateFlags = 0;
408
nsSVGGlyphFrame::GetBBox(nsIDOMSVGRect **_retval)
412
nsresult rv = mMetrics->GetBoundingBox(_retval);
413
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
415
// offset the bounds by the position of this glyph fragment:
417
(*_retval)->GetX(&x);
418
(*_retval)->GetY(&y);
419
(*_retval)->SetX(x+mX);
420
(*_retval)->SetY(y+mY);
425
//----------------------------------------------------------------------
426
// nsISVGGeometrySource methods:
428
/* [noscript] readonly attribute nsIPresContext presContext; */
430
nsSVGGlyphFrame::GetPresContext(nsIPresContext * *aPresContext)
432
// XXX gcc 3.2.2 requires the explicit 'nsSVGGlyphFrameBase::' qualification
433
*aPresContext = nsSVGGlyphFrameBase::GetPresContext();
434
NS_ADDREF(*aPresContext);
438
/* readonly attribute nsIDOMSVGMatrix CTM; */
440
nsSVGGlyphFrame::GetCTM(nsIDOMSVGMatrix * *aCTM)
444
nsISVGTextFrame * textframe = GetTextFrame();
445
NS_ASSERTION(textframe, "null textframe");
447
return textframe->GetCTM(aCTM);
450
/* readonly attribute float strokeOpacity; */
452
nsSVGGlyphFrame::GetStrokeOpacity(float *aStrokeOpacity)
454
*aStrokeOpacity = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeOpacity;
458
/* readonly attribute float strokeWidth; */
460
nsSVGGlyphFrame::GetStrokeWidth(float *aStrokeWidth)
462
*aStrokeWidth = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeWidth;
466
/* void getStrokeDashArray ([array, size_is (count)] out float arr, out unsigned long count); */
468
nsSVGGlyphFrame::GetStrokeDashArray(float **arr, PRUint32 *count)
473
const nsString &dasharrayString = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeDasharray;
474
if (dasharrayString.Length() == 0) return NS_OK;
476
// XXX parsing of the dasharray string should be done elsewhere
478
char *str = ToNewCString(dasharrayString);
480
// array elements are separated by commas. count them to get our max
492
// now get the elements
494
*arr = (float*) nsMemory::Alloc(i * sizeof(float));
498
while ((elem = nsCRT::strtok(cp, "',", &cp))) {
500
(*arr)[(*count)++] = (float) PR_strtod(elem, &end);
502
//printf("[%f]",(*arr)[(*count)-1]);
511
/* readonly attribute float strokeDashoffset; */
513
nsSVGGlyphFrame::GetStrokeDashoffset(float *aStrokeDashoffset)
515
*aStrokeDashoffset = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeDashoffset;
519
/* readonly attribute unsigned short strokeLinecap; */
521
nsSVGGlyphFrame::GetStrokeLinecap(PRUint16 *aStrokeLinecap)
523
*aStrokeLinecap = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeLinecap;
527
/* readonly attribute unsigned short strokeLinejoin; */
529
nsSVGGlyphFrame::GetStrokeLinejoin(PRUint16 *aStrokeLinejoin)
531
*aStrokeLinejoin = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeLinejoin;
535
/* readonly attribute float strokeMiterlimit; */
537
nsSVGGlyphFrame::GetStrokeMiterlimit(float *aStrokeMiterlimit)
539
*aStrokeMiterlimit = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeMiterlimit;
543
/* readonly attribute float fillOpacity; */
545
nsSVGGlyphFrame::GetFillOpacity(float *aFillOpacity)
547
*aFillOpacity = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFillOpacity;
551
/* readonly attribute unsigned short fillRule; */
553
nsSVGGlyphFrame::GetFillRule(PRUint16 *aFillRule)
555
*aFillRule = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFillRule;
559
/* readonly attribute unsigned short strokePaintType; */
561
nsSVGGlyphFrame::GetStrokePaintType(PRUint16 *aStrokePaintType)
563
*aStrokePaintType = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStroke.mType;
567
/* [noscript] readonly attribute nscolor strokePaint; */
569
nsSVGGlyphFrame::GetStrokePaint(nscolor *aStrokePaint)
571
*aStrokePaint = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStroke.mColor;
575
/* readonly attribute unsigned short fillPaintType; */
577
nsSVGGlyphFrame::GetFillPaintType(PRUint16 *aFillPaintType)
579
*aFillPaintType = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFill.mType;
583
/* [noscript] readonly attribute nscolor fillPaint; */
585
nsSVGGlyphFrame::GetFillPaint(nscolor *aFillPaint)
587
*aFillPaint = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFill.mColor;
591
//----------------------------------------------------------------------
592
// nsISVGGlyphMetricsSource methods:
594
/* [noscript] readonly attribute nsFont font; */
596
nsSVGGlyphFrame::GetFont(nsFont *aFont)
598
*aFont = ((const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font))->mFont;
600
// XXX eventually we will have to treat decorations separately from
601
// fonts, because they can have a different color than the current
604
NS_ASSERTION(mParent, "no parent");
605
nsStyleContext *parentContext = mParent->GetStyleContext();
606
NS_ASSERTION(parentContext, "no style context on parent");
608
PRUint8 styleDecorations =
609
((const nsStyleTextReset*)parentContext->GetStyleData(eStyleStruct_TextReset))->mTextDecoration;
610
if (styleDecorations & NS_STYLE_TEXT_DECORATION_UNDERLINE)
611
aFont->decorations |= NS_FONT_DECORATION_UNDERLINE;
612
if (styleDecorations & NS_STYLE_TEXT_DECORATION_OVERLINE)
613
aFont->decorations |= NS_FONT_DECORATION_OVERLINE;
614
if (styleDecorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH)
615
aFont->decorations |= NS_FONT_DECORATION_LINE_THROUGH;
620
/* readonly attribute DOMString characterData; */
622
nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
624
aCharacterData = mCharacterData;
628
/* readonly attribute unsigned short textRendering; */
630
nsSVGGlyphFrame::GetTextRendering(PRUint16 *aTextRendering)
632
*aTextRendering = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mTextRendering;
636
//----------------------------------------------------------------------
637
// nsISVGGlyphGeometrySource methods:
639
/* readonly attribute nsISVGRendererGlyphMetrics metrics; */
641
nsSVGGlyphFrame::GetMetrics(nsISVGRendererGlyphMetrics * *aMetrics)
643
*aMetrics = mMetrics;
644
NS_ADDREF(*aMetrics);
648
/* readonly attribute float x; */
650
nsSVGGlyphFrame::GetX(float *aX)
656
/* readonly attribute float y; */
658
nsSVGGlyphFrame::GetY(float *aY)
664
/* readonly attribute boolean hasHighlight; */
666
nsSVGGlyphFrame::GetHasHighlight(PRBool *aHasHighlight)
668
*aHasHighlight = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
674
// Utilities for converting from indices in the uncompressed content
675
// element strings to compressed frame string and back:
676
int CompressIndex(int index, const nsTextFragment*fragment)
679
if (fragment->Is2b()) {
680
const PRUnichar *data=fragment->Get2b();
681
while(*data && index) {
682
if (XP_IS_SPACE_W(*data)){
686
}while(XP_IS_SPACE_W(*data) && index);
696
const char *data=fragment->Get1b();
697
while(*data && index) {
698
if (XP_IS_SPACE_W(*data)){
702
}while(XP_IS_SPACE_W(*data) && index);
715
int UncompressIndex(int index, PRBool bRightAffinity, const nsTextFragment*fragment)
721
/* [noscript] void getHighlight (out unsigned long charnum, out unsigned long nchars, out nscolor foreground, out nscolor background); */
723
nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars, nscolor *foreground, nscolor *background)
725
*foreground = NS_RGB(255,255,255);
726
*background = NS_RGB(0,0,0);
731
GetHasHighlight(&hasHighlight);
734
NS_ERROR("nsSVGGlyphFrame::GetHighlight() called by renderer when there is no highlight");
735
return NS_ERROR_FAILURE;
738
// XXX gcc 3.2.2 requires the explicit 'nsSVGGlyphFrameBase::' qualification
739
nsIPresContext *presContext = nsSVGGlyphFrameBase::GetPresContext();
741
nsCOMPtr<nsITextContent> tc = do_QueryInterface(mContent);
742
NS_ASSERTION(tc, "no textcontent interface");
744
// The selection ranges are relative to the uncompressed text in
745
// the content element. We'll need the text fragment:
746
const nsTextFragment*fragment=nsnull;
747
tc->GetText(&fragment);
748
NS_ASSERTION(fragment, "null text fragment");
751
// get the selection details
752
SelectionDetails *details = nsnull;
754
nsCOMPtr<nsIFrameSelection> frameSelection;
756
nsCOMPtr<nsISelectionController> controller;
757
GetSelectionController(presContext, getter_AddRefs(controller));
760
NS_ERROR("no selection controller");
761
return NS_ERROR_FAILURE;
763
frameSelection = do_QueryInterface(controller);
765
if (!frameSelection) {
766
presContext->PresShell()->GetFrameSelection(getter_AddRefs(frameSelection));
768
if (!frameSelection) {
769
NS_ERROR("no frameselection interface");
770
return NS_ERROR_FAILURE;
774
tc->GetTextLength(&length);
776
frameSelection->LookUpSelection(mContent, 0, length,
780
#if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
782
SelectionDetails *dp = details;
783
printf("nsSVGGlyphFrame(%p)::GetHighlight() [\n", this);
785
printf("selection detail: %d(%d)->%d(%d) type %d\n",
786
dp->mStart, CompressIndex(dp->mStart, fragment),
787
dp->mEnd, CompressIndex(dp->mEnd, fragment),
797
NS_ASSERTION(details->mNext==nsnull, "can't do multiple selection ranges");
799
*charnum=CompressIndex(details->mStart, fragment);
800
*nchars=CompressIndex(details->mEnd, fragment)-*charnum;
802
nsILookAndFeel *look = presContext->LookAndFeel();
804
look->GetColor(nsILookAndFeel::eColor_TextSelectBackground, *background);
805
look->GetColor(nsILookAndFeel::eColor_TextSelectForeground, *foreground);
807
SelectionDetails *dp = details;
808
while ((dp=details->mNext) != nsnull) {
819
//----------------------------------------------------------------------
820
// nsISVGGlyphFragmentLeaf interface:
823
nsSVGGlyphFrame::SetGlyphPosition(float x, float y)
827
UpdateGeometry(nsISVGGlyphGeometrySource::UPDATEMASK_X |
828
nsISVGGlyphGeometrySource::UPDATEMASK_Y);
831
NS_IMETHODIMP_(float)
832
nsSVGGlyphFrame::GetGlyphPositionX()
837
NS_IMETHODIMP_(float)
838
nsSVGGlyphFrame::GetGlyphPositionY()
845
nsSVGGlyphFrame::GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics)
852
NS_IMETHODIMP_(PRBool)
853
nsSVGGlyphFrame::IsStartOfChunk()
855
// this fragment is a chunk if it has a corresponding absolute
856
// position adjustment in an ancestors' x or y array. (At the moment
857
// we don't map the full arrays, but only the first elements.)
863
nsSVGGlyphFrame::GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y)
867
NS_IMETHODIMP_(PRUint32)
868
nsSVGGlyphFrame::GetNumberOfChars()
870
return mCharacterData.Length();
873
NS_IMETHODIMP_(PRUint32)
874
nsSVGGlyphFrame::GetCharNumberOffset()
879
//----------------------------------------------------------------------
880
// nsISVGGlyphFragmentNode interface:
882
NS_IMETHODIMP_(nsISVGGlyphFragmentLeaf *)
883
nsSVGGlyphFrame::GetFirstGlyphFragment()
888
NS_IMETHODIMP_(nsISVGGlyphFragmentLeaf *)
889
nsSVGGlyphFrame::GetNextGlyphFragment()
891
nsIFrame* sibling = mNextSibling;
893
nsISVGGlyphFragmentNode *node = nsnull;
894
sibling->QueryInterface(NS_GET_IID(nsISVGGlyphFragmentNode), (void**)&node);
896
return node->GetFirstGlyphFragment();
897
sibling = sibling->GetNextSibling();
900
// no more siblings. go back up the tree.
902
NS_ASSERTION(mParent, "null parent");
903
nsISVGGlyphFragmentNode *node = nsnull;
904
mParent->QueryInterface(NS_GET_IID(nsISVGGlyphFragmentNode), (void**)&node);
905
return node ? node->GetNextGlyphFragment() : nsnull;
908
NS_IMETHODIMP_(PRUint32)
909
nsSVGGlyphFrame::BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch)
911
// XXX actually we should be building a new fragment for each chunk here...
914
mCharOffset = charNum;
915
nsCOMPtr<nsITextContent> tc = do_QueryInterface(mContent);
918
tc->GetTextLength(&length);
921
printf("Glyph frame with zero length text\n");
923
mCharacterData = NS_LITERAL_STRING("");
927
tc->CopyText(mCharacterData);
928
mCharacterData.CompressWhitespace(charNum==0, lastBranch);
930
return charNum+mCharacterData.Length();
934
nsSVGGlyphFrame::NotifyMetricsSuspended()
940
nsSVGGlyphFrame::NotifyMetricsUnsuspended()
942
NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::NotifyMetricsUnsuspended");
944
if (mMetricsUpdateFlags != 0) {
946
mMetrics->Update(mMetricsUpdateFlags, &metricsDirty);
948
mGeometryUpdateFlags |= nsISVGGlyphGeometrySource::UPDATEMASK_METRICS;
949
nsISVGTextFrame* text_frame = GetTextFrame();
950
NS_ASSERTION(text_frame, "null text frame");
952
text_frame->NotifyGlyphMetricsChange(this);
954
mMetricsUpdateFlags = 0;
959
nsSVGGlyphFrame::NotifyGlyphFragmentTreeSuspended()
965
nsSVGGlyphFrame::NotifyGlyphFragmentTreeUnsuspended()
967
if (mFragmentTreeDirty) {
968
nsISVGTextFrame* text_frame = GetTextFrame();
969
NS_ASSERTION(text_frame, "null text frame");
971
text_frame->NotifyGlyphFragmentTreeChange(this);
972
mFragmentTreeDirty = PR_FALSE;
978
//----------------------------------------------------------------------
981
void nsSVGGlyphFrame::UpdateGeometry(PRUint32 flags, PRBool bRedraw)
983
mGeometryUpdateFlags |= flags;
985
nsISVGOuterSVGFrame *outerSVGFrame = GetOuterSVGFrame();
986
if (!outerSVGFrame) {
987
NS_ERROR("null outerSVGFrame");
992
outerSVGFrame->IsRedrawSuspended(&suspended);
994
NS_ASSERTION(!mMetricsUpdateFlags, "dirty metrics in nsSVGGlyphFrame::UpdateGeometry");
995
NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::UpdateGeometry");
996
nsCOMPtr<nsISVGRendererRegion> dirty_region;
997
mGeometry->Update(mGeometryUpdateFlags, getter_AddRefs(dirty_region));
999
outerSVGFrame->InvalidateRegion(dirty_region, bRedraw);
1000
mGeometryUpdateFlags = 0;
1004
void nsSVGGlyphFrame::UpdateMetrics(PRUint32 flags)
1006
mMetricsUpdateFlags |= flags;
1008
nsISVGTextFrame* text_frame = GetTextFrame();
1010
NS_ERROR("null text_frame");
1014
PRBool suspended = text_frame->IsMetricsSuspended();
1016
NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::UpdateMetrics");
1017
PRBool metricsDirty;
1018
mMetrics->Update(mMetricsUpdateFlags, &metricsDirty);
1020
mGeometryUpdateFlags |= nsISVGGlyphGeometrySource::UPDATEMASK_METRICS;
1021
text_frame->NotifyGlyphMetricsChange(this);
1023
mMetricsUpdateFlags = 0;
1027
void nsSVGGlyphFrame::UpdateFragmentTree()
1029
mFragmentTreeDirty = PR_TRUE;
1031
nsISVGTextFrame* text_frame = GetTextFrame();
1033
NS_ERROR("null text_frame");
1037
PRBool suspended = text_frame->IsGlyphFragmentTreeSuspended();
1039
text_frame->NotifyGlyphFragmentTreeChange(this);
1040
mFragmentTreeDirty = PR_FALSE;
1044
nsISVGOuterSVGFrame *
1045
nsSVGGlyphFrame::GetOuterSVGFrame()
1047
NS_ASSERTION(mParent, "null parent");
1049
nsISVGContainerFrame *containerFrame;
1050
mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), (void**)&containerFrame);
1051
if (!containerFrame) {
1052
NS_ERROR("invalid container");
1056
return containerFrame->GetOuterSVGFrame();
1060
nsSVGGlyphFrame::GetTextFrame()
1062
NS_ASSERTION(mParent, "null parent");
1064
nsISVGTextContainerFrame *containerFrame;
1065
mParent->QueryInterface(NS_GET_IID(nsISVGTextContainerFrame), (void**)&containerFrame);
1066
if (!containerFrame) {
1067
NS_ERROR("invalid container");
1071
return containerFrame->GetTextFrame();