~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/layout/svg/base/src/nsSVGGlyphFrame.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
4
 *
 
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/
 
9
 *
 
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
 
13
 * License.
 
14
 *
 
15
 * The Original Code is the Mozilla SVG project.
 
16
 *
 
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.
 
21
 *
 
22
 * Contributor(s):
 
23
 *    Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
 
24
 *
 
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.
 
36
 *
 
37
 * ----- END LICENSE BLOCK ----- */
 
38
 
 
39
#include "nsFrame.h"
 
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"
 
53
#include "nsCRT.h"
 
54
#include "prdtoa.h"
 
55
#include "nsIDOMSVGRect.h"
 
56
#include "nsILookAndFeel.h"
 
57
#include "nsTextFragment.h"
 
58
 
 
59
typedef nsFrame nsSVGGlyphFrameBase;
 
60
 
 
61
class nsSVGGlyphFrame : public nsSVGGlyphFrameBase,
 
62
                        public nsISVGGlyphGeometrySource, // : nsISVGGlyphMetricsSource : nsISVGGeometrySource
 
63
                        public nsISVGGlyphFragmentLeaf, // : nsISVGGlyphFragmentNode
 
64
                        public nsISVGChildFrame
 
65
{
 
66
protected:
 
67
  friend nsresult
 
68
  NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsIContent* aContent,
 
69
                      nsIFrame* parentFrame, nsIFrame** aNewFrame);
 
70
  nsSVGGlyphFrame();
 
71
  virtual ~nsSVGGlyphFrame();
 
72
 
 
73
public:
 
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; }
 
78
 
 
79
  // nsIFrame interface:
 
80
  NS_IMETHOD
 
81
  Init(nsIPresContext*  aPresContext,
 
82
       nsIContent*      aContent,
 
83
       nsIFrame*        aParent,
 
84
       nsStyleContext*  aContext,
 
85
       nsIFrame*        aPrevInFlow);
 
86
 
 
87
  NS_IMETHOD  CharacterDataChanged(nsIPresContext* aPresContext,
 
88
                                   nsIContent*     aChild,
 
89
                                   PRBool          aAppend);
 
90
 
 
91
  NS_IMETHOD  SetSelected(nsIPresContext* aPresContext,
 
92
                          nsIDOMRange*    aRange,
 
93
                          PRBool          aSelected,
 
94
                          nsSpread        aSpread);
 
95
  NS_IMETHOD  GetSelected(PRBool *aSelected) const;
 
96
  NS_IMETHOD  IsSelectable(PRBool* aIsSelectable, PRUint8* aSelectStyle);
 
97
 
 
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);
 
107
  
 
108
  // nsISVGGeometrySource interface: 
 
109
  NS_DECL_NSISVGGEOMETRYSOURCE
 
110
 
 
111
  // nsISVGGlyphMetricsSource interface:
 
112
  NS_DECL_NSISVGGLYPHMETRICSSOURCE
 
113
 
 
114
  // nsISVGGlyphGeometrySource interface:
 
115
  NS_DECL_NSISVGGLYPHGEOMETRYSOURCE
 
116
 
 
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();
 
126
 
 
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();
 
135
  
 
136
protected:
 
137
  void UpdateGeometry(PRUint32 flags, PRBool bRedraw=PR_TRUE);
 
138
  void UpdateMetrics(PRUint32 flags);
 
139
  void UpdateFragmentTree();
 
140
  nsISVGOuterSVGFrame *GetOuterSVGFrame();
 
141
  nsISVGTextFrame *GetTextFrame();
 
142
  
 
143
  nsCOMPtr<nsISVGRendererGlyphGeometry> mGeometry;
 
144
  nsCOMPtr<nsISVGRendererGlyphMetrics> mMetrics;
 
145
  float mX, mY;
 
146
  PRUint32 mCharOffset;
 
147
  PRUint32 mGeometryUpdateFlags;
 
148
  PRUint32 mMetricsUpdateFlags;
 
149
  PRBool mFragmentTreeDirty;
 
150
  nsString mCharacterData;
 
151
};
 
152
 
 
153
//----------------------------------------------------------------------
 
154
// Implementation
 
155
 
 
156
nsresult
 
157
NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* parentFrame,
 
158
                    nsIFrame** aNewFrame)
 
159
{
 
160
  *aNewFrame = nsnull;
 
161
 
 
162
#ifdef DEBUG
 
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");
 
167
  
 
168
  nsCOMPtr<nsITextContent> tc = do_QueryInterface(aContent);
 
169
  NS_ASSERTION(tc, "trying to construct an SVGGlyphFrame for wrong content element");
 
170
#endif
 
171
  
 
172
  nsSVGGlyphFrame* it = new (aPresShell) nsSVGGlyphFrame;
 
173
  if (nsnull == it)
 
174
    return NS_ERROR_OUT_OF_MEMORY;
 
175
 
 
176
  *aNewFrame = it;
 
177
 
 
178
  return NS_OK;
 
179
}
 
180
 
 
181
nsSVGGlyphFrame::nsSVGGlyphFrame()
 
182
    : mGeometryUpdateFlags(0), mMetricsUpdateFlags(0),
 
183
      mCharOffset(0), mFragmentTreeDirty(PR_FALSE)
 
184
{
 
185
}
 
186
 
 
187
nsSVGGlyphFrame::~nsSVGGlyphFrame()
 
188
{
 
189
 
 
190
}
 
191
 
 
192
 
 
193
//----------------------------------------------------------------------
 
194
// nsISupports methods
 
195
 
 
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)
 
204
 
 
205
//----------------------------------------------------------------------
 
206
// nsIFrame methods
 
207
 
 
208
NS_IMETHODIMP
 
209
nsSVGGlyphFrame::Init(nsIPresContext*  aPresContext,
 
210
                      nsIContent*      aContent,
 
211
                      nsIFrame*        aParent,
 
212
                      nsStyleContext*  aContext,
 
213
                      nsIFrame*        aPrevInFlow)
 
214
{
 
215
//  rv = nsSVGGlyphFrameBase::Init(aPresContext, aContent, aParent,
 
216
//                                 aContext, aPrevInFlow);
 
217
 
 
218
  mContent = aContent;
 
219
  NS_IF_ADDREF(mContent);
 
220
  mParent = aParent;
 
221
 
 
222
  // construct our glyphmetrics & glyphgeometry objects:
 
223
  nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
 
224
  if (!outerSVGFrame) {
 
225
    NS_ERROR("No outerSVGFrame");
 
226
    return NS_ERROR_FAILURE;
 
227
  }
 
228
  nsCOMPtr<nsISVGRenderer> renderer;
 
229
  outerSVGFrame->GetRenderer(getter_AddRefs(renderer));
 
230
 
 
231
  renderer->CreateGlyphMetrics(this, getter_AddRefs(mMetrics));
 
232
  if (!mMetrics) return NS_ERROR_FAILURE;
 
233
  
 
234
  renderer->CreateGlyphGeometry(this, getter_AddRefs(mGeometry));
 
235
  if (!mGeometry) return NS_ERROR_FAILURE;
 
236
  
 
237
  
 
238
  SetStyleContext(aPresContext, aContext);
 
239
    
 
240
  return NS_OK;
 
241
}
 
242
 
 
243
NS_IMETHODIMP
 
244
nsSVGGlyphFrame::CharacterDataChanged(nsIPresContext* aPresContext,
 
245
                                      nsIContent*     aChild,
 
246
                                      PRBool          aAppend)
 
247
{
 
248
#ifdef DEBUG
 
249
//  printf("** nsSVGGlyphFrame::CharacterDataChanged\n");
 
250
#endif
 
251
  nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
 
252
  if (!outerSVGFrame) {
 
253
    NS_ERROR("No outerSVGFrame");
 
254
    return NS_ERROR_FAILURE;
 
255
  }
 
256
  
 
257
  outerSVGFrame->SuspendRedraw();
 
258
  UpdateFragmentTree();
 
259
  UpdateMetrics(nsISVGGeometrySource::UPDATEMASK_ALL);
 
260
  UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_ALL);
 
261
  outerSVGFrame->UnsuspendRedraw();
 
262
 
 
263
  return NS_OK;
 
264
}
 
265
 
 
266
NS_IMETHODIMP
 
267
nsSVGGlyphFrame::SetSelected(nsIPresContext* aPresContext,
 
268
                             nsIDOMRange*    aRange,
 
269
                             PRBool          aSelected,
 
270
                             nsSpread        aSpread)
 
271
{
 
272
#if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
 
273
  printf("nsSVGGlyphFrame(%p)::SetSelected()\n", this);
 
274
#endif
 
275
//  return nsSVGGlyphFrameBase::SetSelected(aPresContext, aRange, aSelected, aSpread);
 
276
 
 
277
  // check whether style allows selection
 
278
  PRBool  selectable;
 
279
  IsSelectable(&selectable, nsnull);
 
280
  if (!selectable)
 
281
    return NS_OK;
 
282
  
 
283
  if ( aSelected ){
 
284
    mState |=  NS_FRAME_SELECTED_CONTENT;
 
285
  }
 
286
  else
 
287
    mState &= ~NS_FRAME_SELECTED_CONTENT;
 
288
 
 
289
  UpdateGeometry(nsISVGGlyphGeometrySource::UPDATEMASK_HIGHLIGHT |
 
290
                 nsISVGGlyphGeometrySource::UPDATEMASK_HAS_HIGHLIGHT,
 
291
                 PR_FALSE);  
 
292
 
 
293
  return NS_OK;
 
294
}
 
295
 
 
296
NS_IMETHODIMP
 
297
nsSVGGlyphFrame::GetSelected(PRBool *aSelected) const
 
298
{
 
299
  nsresult rv = nsSVGGlyphFrameBase::GetSelected(aSelected);
 
300
#if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
 
301
  printf("nsSVGGlyphFrame(%p)::GetSelected()=%d\n", this, *aSelected);
 
302
#endif
 
303
  return rv;
 
304
}
 
305
 
 
306
NS_IMETHODIMP
 
307
nsSVGGlyphFrame::IsSelectable(PRBool* aIsSelectable,
 
308
                              PRUint8* aSelectStyle)
 
309
{
 
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);
 
313
#endif
 
314
  return rv;
 
315
}
 
316
 
 
317
 
 
318
//----------------------------------------------------------------------
 
319
// nsISVGChildFrame methods
 
320
 
 
321
NS_IMETHODIMP
 
322
nsSVGGlyphFrame::Paint(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips)
 
323
{
 
324
#ifdef DEBUG
 
325
  //printf("nsSVGGlyphFrame(%p)::Paint\n", this);
 
326
#endif
 
327
  mGeometry->Render(canvas);
 
328
  return NS_OK;
 
329
}
 
330
 
 
331
NS_IMETHODIMP
 
332
nsSVGGlyphFrame::GetFrameForPoint(float x, float y, nsIFrame** hit)
 
333
{
 
334
#ifdef DEBUG
 
335
  //printf("nsSVGGlyphFrame(%p)::GetFrameForPoint\n", this);
 
336
#endif
 
337
  // test for hit:
 
338
  *hit = nsnull;
 
339
  PRBool isHit;
 
340
  mGeometry->ContainsPoint(x, y, &isHit);
 
341
  if (isHit) 
 
342
    *hit = this;
 
343
  
 
344
  return NS_OK;
 
345
}
 
346
 
 
347
NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
 
348
nsSVGGlyphFrame::GetCoveredRegion()
 
349
{
 
350
  nsISVGRendererRegion *region = nsnull;
 
351
  mGeometry->GetCoveredRegion(&region);
 
352
  return region;
 
353
}
 
354
 
 
355
NS_IMETHODIMP
 
356
nsSVGGlyphFrame::InitialUpdate()
 
357
{
 
358
  nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
 
359
  if (!outerSVGFrame) {
 
360
    NS_ERROR("No outerSVGFrame");
 
361
    return NS_ERROR_FAILURE;
 
362
  }
 
363
  
 
364
  outerSVGFrame->SuspendRedraw();
 
365
  UpdateFragmentTree();
 
366
  UpdateMetrics(nsISVGGeometrySource::UPDATEMASK_ALL);
 
367
  UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_ALL);
 
368
  outerSVGFrame->UnsuspendRedraw();
 
369
  
 
370
  return NS_OK;
 
371
}  
 
372
 
 
373
NS_IMETHODIMP
 
374
nsSVGGlyphFrame::NotifyCTMChanged()
 
375
{
 
376
  UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_CTM);
 
377
  
 
378
  return NS_OK;
 
379
}
 
380
 
 
381
NS_IMETHODIMP
 
382
nsSVGGlyphFrame::NotifyRedrawSuspended()
 
383
{
 
384
  // XXX should we cache the fact that redraw is suspended?
 
385
  return NS_OK;
 
386
}
 
387
 
 
388
NS_IMETHODIMP
 
389
nsSVGGlyphFrame::NotifyRedrawUnsuspended()
 
390
{
 
391
  NS_ASSERTION(!mMetricsUpdateFlags, "dirty metrics in nsSVGGlyphFrame::NotifyRedrawUnsuspended");
 
392
  NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::NotifyRedrawUnsuspended");
 
393
    
 
394
  if (mGeometryUpdateFlags != 0) {
 
395
    nsCOMPtr<nsISVGRendererRegion> dirty_region;
 
396
    mGeometry->Update(mGeometryUpdateFlags, getter_AddRefs(dirty_region));
 
397
    if (dirty_region) {
 
398
      nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
 
399
      if (outerSVGFrame)
 
400
        outerSVGFrame->InvalidateRegion(dirty_region, PR_TRUE);
 
401
    }
 
402
    mGeometryUpdateFlags = 0;
 
403
  }
 
404
  return NS_OK;
 
405
}
 
406
 
 
407
NS_IMETHODIMP
 
408
nsSVGGlyphFrame::GetBBox(nsIDOMSVGRect **_retval)
 
409
{
 
410
  *_retval = nsnull;
 
411
 
 
412
  nsresult rv = mMetrics->GetBoundingBox(_retval);
 
413
  if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
 
414
  
 
415
  // offset the bounds by the position of this glyph fragment:
 
416
  float x,y;
 
417
  (*_retval)->GetX(&x);
 
418
  (*_retval)->GetY(&y);
 
419
  (*_retval)->SetX(x+mX);
 
420
  (*_retval)->SetY(y+mY);
 
421
  
 
422
  return NS_OK;
 
423
}
 
424
 
 
425
//----------------------------------------------------------------------
 
426
// nsISVGGeometrySource methods:
 
427
 
 
428
/* [noscript] readonly attribute nsIPresContext presContext; */
 
429
NS_IMETHODIMP
 
430
nsSVGGlyphFrame::GetPresContext(nsIPresContext * *aPresContext)
 
431
{
 
432
  // XXX gcc 3.2.2 requires the explicit 'nsSVGGlyphFrameBase::' qualification
 
433
  *aPresContext = nsSVGGlyphFrameBase::GetPresContext();
 
434
  NS_ADDREF(*aPresContext);
 
435
  return NS_OK;
 
436
}
 
437
 
 
438
/* readonly attribute nsIDOMSVGMatrix CTM; */
 
439
NS_IMETHODIMP
 
440
nsSVGGlyphFrame::GetCTM(nsIDOMSVGMatrix * *aCTM)
 
441
{
 
442
  *aCTM = nsnull;
 
443
  
 
444
  nsISVGTextFrame * textframe = GetTextFrame();
 
445
  NS_ASSERTION(textframe, "null textframe");
 
446
  
 
447
  return textframe->GetCTM(aCTM);  
 
448
}
 
449
 
 
450
/* readonly attribute float strokeOpacity; */
 
451
NS_IMETHODIMP
 
452
nsSVGGlyphFrame::GetStrokeOpacity(float *aStrokeOpacity)
 
453
{
 
454
  *aStrokeOpacity = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeOpacity;
 
455
  return NS_OK;
 
456
}
 
457
 
 
458
/* readonly attribute float strokeWidth; */
 
459
NS_IMETHODIMP
 
460
nsSVGGlyphFrame::GetStrokeWidth(float *aStrokeWidth)
 
461
{
 
462
  *aStrokeWidth = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeWidth;
 
463
  return NS_OK;
 
464
}
 
465
 
 
466
/* void getStrokeDashArray ([array, size_is (count)] out float arr, out unsigned long count); */
 
467
NS_IMETHODIMP
 
468
nsSVGGlyphFrame::GetStrokeDashArray(float **arr, PRUint32 *count)
 
469
{
 
470
  *arr = nsnull;
 
471
  *count = 0;
 
472
  
 
473
  const nsString &dasharrayString = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeDasharray;
 
474
  if (dasharrayString.Length() == 0) return NS_OK;
 
475
 
 
476
  // XXX parsing of the dasharray string should be done elsewhere
 
477
 
 
478
  char *str = ToNewCString(dasharrayString);
 
479
 
 
480
  // array elements are separated by commas. count them to get our max
 
481
  // no of elems.
 
482
 
 
483
  int i=0;
 
484
  char* cp = str;
 
485
  while (*cp) {
 
486
    if (*cp == ',')
 
487
      ++i;
 
488
    ++cp;
 
489
  }
 
490
  ++i;
 
491
 
 
492
  // now get the elements
 
493
  
 
494
  *arr = (float*) nsMemory::Alloc(i * sizeof(float));
 
495
 
 
496
  cp = str;
 
497
  char *elem;
 
498
  while ((elem = nsCRT::strtok(cp, "',", &cp))) {
 
499
    char *end;
 
500
    (*arr)[(*count)++] = (float) PR_strtod(elem, &end);
 
501
#ifdef DEBUG
 
502
    //printf("[%f]",(*arr)[(*count)-1]);
 
503
#endif
 
504
  }
 
505
  
 
506
  nsMemory::Free(str);
 
507
 
 
508
  return NS_OK;
 
509
}
 
510
 
 
511
/* readonly attribute float strokeDashoffset; */
 
512
NS_IMETHODIMP
 
513
nsSVGGlyphFrame::GetStrokeDashoffset(float *aStrokeDashoffset)
 
514
{
 
515
  *aStrokeDashoffset = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeDashoffset;
 
516
  return NS_OK;
 
517
}
 
518
 
 
519
/* readonly attribute unsigned short strokeLinecap; */
 
520
NS_IMETHODIMP
 
521
nsSVGGlyphFrame::GetStrokeLinecap(PRUint16 *aStrokeLinecap)
 
522
{
 
523
  *aStrokeLinecap = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeLinecap;
 
524
  return NS_OK;
 
525
}
 
526
 
 
527
/* readonly attribute unsigned short strokeLinejoin; */
 
528
NS_IMETHODIMP
 
529
nsSVGGlyphFrame::GetStrokeLinejoin(PRUint16 *aStrokeLinejoin)
 
530
{
 
531
  *aStrokeLinejoin = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeLinejoin;
 
532
  return NS_OK;
 
533
}
 
534
 
 
535
/* readonly attribute float strokeMiterlimit; */
 
536
NS_IMETHODIMP
 
537
nsSVGGlyphFrame::GetStrokeMiterlimit(float *aStrokeMiterlimit)
 
538
{
 
539
  *aStrokeMiterlimit = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeMiterlimit; 
 
540
  return NS_OK;
 
541
}
 
542
 
 
543
/* readonly attribute float fillOpacity; */
 
544
NS_IMETHODIMP
 
545
nsSVGGlyphFrame::GetFillOpacity(float *aFillOpacity)
 
546
{
 
547
  *aFillOpacity = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFillOpacity;
 
548
  return NS_OK;
 
549
}
 
550
 
 
551
/* readonly attribute unsigned short fillRule; */
 
552
NS_IMETHODIMP
 
553
nsSVGGlyphFrame::GetFillRule(PRUint16 *aFillRule)
 
554
{
 
555
  *aFillRule = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFillRule;
 
556
  return NS_OK;
 
557
}
 
558
 
 
559
/* readonly attribute unsigned short strokePaintType; */
 
560
NS_IMETHODIMP
 
561
nsSVGGlyphFrame::GetStrokePaintType(PRUint16 *aStrokePaintType)
 
562
{
 
563
  *aStrokePaintType = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStroke.mType;
 
564
  return NS_OK;
 
565
}
 
566
 
 
567
/* [noscript] readonly attribute nscolor strokePaint; */
 
568
NS_IMETHODIMP
 
569
nsSVGGlyphFrame::GetStrokePaint(nscolor *aStrokePaint)
 
570
{
 
571
  *aStrokePaint = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStroke.mColor;
 
572
  return NS_OK;
 
573
}
 
574
 
 
575
/* readonly attribute unsigned short fillPaintType; */
 
576
NS_IMETHODIMP
 
577
nsSVGGlyphFrame::GetFillPaintType(PRUint16 *aFillPaintType)
 
578
{
 
579
  *aFillPaintType = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFill.mType;
 
580
  return NS_OK;
 
581
}
 
582
 
 
583
/* [noscript] readonly attribute nscolor fillPaint; */
 
584
NS_IMETHODIMP
 
585
nsSVGGlyphFrame::GetFillPaint(nscolor *aFillPaint)
 
586
{
 
587
  *aFillPaint = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFill.mColor;
 
588
  return NS_OK;
 
589
}
 
590
 
 
591
//----------------------------------------------------------------------
 
592
// nsISVGGlyphMetricsSource methods:
 
593
 
 
594
/* [noscript] readonly attribute nsFont font; */
 
595
NS_IMETHODIMP
 
596
nsSVGGlyphFrame::GetFont(nsFont *aFont)
 
597
{
 
598
  *aFont = ((const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font))->mFont;
 
599
 
 
600
  // XXX eventually we will have to treat decorations separately from
 
601
  // fonts, because they can have a different color than the current
 
602
  // glyph.
 
603
  
 
604
  NS_ASSERTION(mParent, "no parent");
 
605
  nsStyleContext *parentContext = mParent->GetStyleContext();
 
606
  NS_ASSERTION(parentContext, "no style context on parent");
 
607
  
 
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;    
 
616
  
 
617
  return NS_OK;
 
618
}
 
619
 
 
620
/* readonly attribute DOMString characterData; */
 
621
NS_IMETHODIMP
 
622
nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
 
623
{
 
624
  aCharacterData = mCharacterData;
 
625
  return NS_OK;
 
626
}
 
627
 
 
628
/* readonly attribute unsigned short textRendering; */
 
629
NS_IMETHODIMP
 
630
nsSVGGlyphFrame::GetTextRendering(PRUint16 *aTextRendering)
 
631
{
 
632
  *aTextRendering = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mTextRendering;
 
633
  return NS_OK;
 
634
}
 
635
 
 
636
//----------------------------------------------------------------------
 
637
// nsISVGGlyphGeometrySource methods:
 
638
 
 
639
/* readonly attribute nsISVGRendererGlyphMetrics metrics; */
 
640
NS_IMETHODIMP
 
641
nsSVGGlyphFrame::GetMetrics(nsISVGRendererGlyphMetrics * *aMetrics)
 
642
{
 
643
  *aMetrics = mMetrics;
 
644
  NS_ADDREF(*aMetrics);
 
645
  return NS_OK;
 
646
}
 
647
 
 
648
/* readonly attribute float x; */
 
649
NS_IMETHODIMP
 
650
nsSVGGlyphFrame::GetX(float *aX)
 
651
{
 
652
  *aX = mX;
 
653
  return NS_OK;
 
654
}
 
655
 
 
656
/* readonly attribute float y; */
 
657
NS_IMETHODIMP
 
658
nsSVGGlyphFrame::GetY(float *aY)
 
659
{
 
660
  *aY = mY;
 
661
  return NS_OK;
 
662
}
 
663
 
 
664
/* readonly attribute boolean hasHighlight; */
 
665
NS_IMETHODIMP
 
666
nsSVGGlyphFrame::GetHasHighlight(PRBool *aHasHighlight)
 
667
{
 
668
  *aHasHighlight = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
 
669
 
 
670
  return NS_OK;
 
671
}
 
672
 
 
673
 
 
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)
 
677
{
 
678
  int ci=0;
 
679
  if (fragment->Is2b()) {
 
680
    const PRUnichar *data=fragment->Get2b();
 
681
    while(*data && index) {
 
682
      if (XP_IS_SPACE_W(*data)){
 
683
        do {
 
684
          ++data;
 
685
          --index;
 
686
        }while(XP_IS_SPACE_W(*data) && index);
 
687
      }
 
688
      else {
 
689
        ++data;
 
690
        --index;
 
691
      }
 
692
      ++ci;
 
693
    }
 
694
  }
 
695
  else {
 
696
    const char *data=fragment->Get1b();
 
697
    while(*data && index) {
 
698
      if (XP_IS_SPACE_W(*data)){
 
699
        do {
 
700
          ++data;
 
701
          --index;
 
702
        }while(XP_IS_SPACE_W(*data) && index);
 
703
      }
 
704
      else {
 
705
        ++data;
 
706
        --index;
 
707
      }
 
708
      ++ci;
 
709
    }
 
710
  }
 
711
    
 
712
  return ci;
 
713
}
 
714
 
 
715
int UncompressIndex(int index, PRBool bRightAffinity, const nsTextFragment*fragment)
 
716
{
 
717
  // XXX
 
718
  return index;
 
719
}
 
720
 
 
721
/* [noscript] void getHighlight (out unsigned long charnum, out unsigned long nchars, out nscolor foreground, out nscolor background); */
 
722
NS_IMETHODIMP
 
723
nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars, nscolor *foreground, nscolor *background)
 
724
{
 
725
  *foreground = NS_RGB(255,255,255);
 
726
  *background = NS_RGB(0,0,0); 
 
727
  *charnum=0;
 
728
  *nchars=0;
 
729
 
 
730
    PRBool hasHighlight;
 
731
  GetHasHighlight(&hasHighlight);
 
732
 
 
733
  if (!hasHighlight) {
 
734
    NS_ERROR("nsSVGGlyphFrame::GetHighlight() called by renderer when there is no highlight");
 
735
    return NS_ERROR_FAILURE;
 
736
  }
 
737
 
 
738
  // XXX gcc 3.2.2 requires the explicit 'nsSVGGlyphFrameBase::' qualification
 
739
  nsIPresContext *presContext = nsSVGGlyphFrameBase::GetPresContext();
 
740
 
 
741
  nsCOMPtr<nsITextContent> tc = do_QueryInterface(mContent);
 
742
  NS_ASSERTION(tc, "no textcontent interface");
 
743
 
 
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");
 
749
 
 
750
  
 
751
  // get the selection details 
 
752
  SelectionDetails *details = nsnull;
 
753
  {
 
754
    nsCOMPtr<nsIFrameSelection> frameSelection;
 
755
    {
 
756
      nsCOMPtr<nsISelectionController> controller;
 
757
      GetSelectionController(presContext, getter_AddRefs(controller));
 
758
      
 
759
      if (!controller) {
 
760
        NS_ERROR("no selection controller");
 
761
        return NS_ERROR_FAILURE;
 
762
      }
 
763
      frameSelection = do_QueryInterface(controller);
 
764
    }
 
765
    if (!frameSelection) {
 
766
      presContext->PresShell()->GetFrameSelection(getter_AddRefs(frameSelection));
 
767
    }
 
768
    if (!frameSelection) {
 
769
      NS_ERROR("no frameselection interface");
 
770
      return NS_ERROR_FAILURE;
 
771
    }
 
772
 
 
773
    PRInt32 length;
 
774
    tc->GetTextLength(&length);
 
775
    
 
776
    frameSelection->LookUpSelection(mContent, 0, length,
 
777
                                    &details, PR_FALSE);
 
778
  }
 
779
 
 
780
#if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
 
781
  {
 
782
    SelectionDetails *dp = details;
 
783
    printf("nsSVGGlyphFrame(%p)::GetHighlight() [\n", this);
 
784
    while (dp) {
 
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),
 
788
             dp->mType);
 
789
      dp = dp->mNext;
 
790
    }
 
791
    printf("]\n");
 
792
      
 
793
  }
 
794
#endif
 
795
  
 
796
  if (details) {
 
797
    NS_ASSERTION(details->mNext==nsnull, "can't do multiple selection ranges");
 
798
 
 
799
    *charnum=CompressIndex(details->mStart, fragment);
 
800
    *nchars=CompressIndex(details->mEnd, fragment)-*charnum;  
 
801
    
 
802
    nsILookAndFeel *look = presContext->LookAndFeel();
 
803
 
 
804
    look->GetColor(nsILookAndFeel::eColor_TextSelectBackground, *background);
 
805
    look->GetColor(nsILookAndFeel::eColor_TextSelectForeground, *foreground);
 
806
 
 
807
    SelectionDetails *dp = details;
 
808
    while ((dp=details->mNext) != nsnull) {
 
809
      delete details;
 
810
      details = dp;
 
811
    }
 
812
    delete details;
 
813
  }
 
814
  
 
815
  return NS_OK;
 
816
}
 
817
 
 
818
 
 
819
//----------------------------------------------------------------------
 
820
// nsISVGGlyphFragmentLeaf interface:
 
821
 
 
822
NS_IMETHODIMP_(void)
 
823
nsSVGGlyphFrame::SetGlyphPosition(float x, float y)
 
824
{
 
825
  mX = x;
 
826
  mY = y;
 
827
  UpdateGeometry(nsISVGGlyphGeometrySource::UPDATEMASK_X |
 
828
                 nsISVGGlyphGeometrySource::UPDATEMASK_Y);
 
829
}
 
830
 
 
831
NS_IMETHODIMP_(float)
 
832
nsSVGGlyphFrame::GetGlyphPositionX()
 
833
{
 
834
  return mX;
 
835
}
 
836
 
 
837
NS_IMETHODIMP_(float)
 
838
nsSVGGlyphFrame::GetGlyphPositionY()
 
839
{
 
840
  return mY;
 
841
}
 
842
 
 
843
 
 
844
NS_IMETHODIMP
 
845
nsSVGGlyphFrame::GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics)
 
846
{
 
847
  *metrics = mMetrics;
 
848
  NS_ADDREF(*metrics);
 
849
  return NS_OK;
 
850
}
 
851
 
 
852
NS_IMETHODIMP_(PRBool)
 
853
nsSVGGlyphFrame::IsStartOfChunk()
 
854
{
 
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.)
 
858
 
 
859
  return PR_FALSE;
 
860
}
 
861
 
 
862
NS_IMETHODIMP_(void)
 
863
nsSVGGlyphFrame::GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y)
 
864
{
 
865
}
 
866
 
 
867
NS_IMETHODIMP_(PRUint32)
 
868
nsSVGGlyphFrame::GetNumberOfChars()
 
869
{
 
870
  return mCharacterData.Length();
 
871
}
 
872
 
 
873
NS_IMETHODIMP_(PRUint32)
 
874
nsSVGGlyphFrame::GetCharNumberOffset()
 
875
{
 
876
  return mCharOffset;
 
877
}
 
878
 
 
879
//----------------------------------------------------------------------
 
880
// nsISVGGlyphFragmentNode interface:
 
881
 
 
882
NS_IMETHODIMP_(nsISVGGlyphFragmentLeaf *)
 
883
nsSVGGlyphFrame::GetFirstGlyphFragment()
 
884
{
 
885
  return this;
 
886
}
 
887
 
 
888
NS_IMETHODIMP_(nsISVGGlyphFragmentLeaf *)
 
889
nsSVGGlyphFrame::GetNextGlyphFragment()
 
890
{
 
891
  nsIFrame* sibling = mNextSibling;
 
892
  while (sibling) {
 
893
    nsISVGGlyphFragmentNode *node = nsnull;
 
894
    sibling->QueryInterface(NS_GET_IID(nsISVGGlyphFragmentNode), (void**)&node);
 
895
    if (node)
 
896
      return node->GetFirstGlyphFragment();
 
897
    sibling = sibling->GetNextSibling();
 
898
  }
 
899
 
 
900
  // no more siblings. go back up the tree.
 
901
  
 
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;
 
906
}
 
907
 
 
908
NS_IMETHODIMP_(PRUint32)
 
909
nsSVGGlyphFrame::BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch)
 
910
{
 
911
  // XXX actually we should be building a new fragment for each chunk here...
 
912
 
 
913
 
 
914
  mCharOffset = charNum;
 
915
  nsCOMPtr<nsITextContent> tc = do_QueryInterface(mContent);
 
916
 
 
917
  PRInt32 length;
 
918
  tc->GetTextLength(&length);
 
919
  if (length==0) {
 
920
#ifdef DEBUG
 
921
    printf("Glyph frame with zero length text\n");
 
922
#endif
 
923
    mCharacterData = NS_LITERAL_STRING("");
 
924
    return charNum;
 
925
  }
 
926
  
 
927
  tc->CopyText(mCharacterData);
 
928
  mCharacterData.CompressWhitespace(charNum==0, lastBranch);
 
929
 
 
930
  return charNum+mCharacterData.Length();
 
931
}
 
932
 
 
933
NS_IMETHODIMP_(void)
 
934
nsSVGGlyphFrame::NotifyMetricsSuspended()
 
935
{
 
936
  // do nothing
 
937
}
 
938
 
 
939
NS_IMETHODIMP_(void)
 
940
nsSVGGlyphFrame::NotifyMetricsUnsuspended()
 
941
{
 
942
  NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::NotifyMetricsUnsuspended");
 
943
 
 
944
  if (mMetricsUpdateFlags != 0) {
 
945
    PRBool metricsDirty;
 
946
    mMetrics->Update(mMetricsUpdateFlags, &metricsDirty);
 
947
    if (metricsDirty) {
 
948
      mGeometryUpdateFlags |= nsISVGGlyphGeometrySource::UPDATEMASK_METRICS;
 
949
      nsISVGTextFrame* text_frame = GetTextFrame();
 
950
      NS_ASSERTION(text_frame, "null text frame");
 
951
      if (text_frame)
 
952
        text_frame->NotifyGlyphMetricsChange(this);
 
953
    }
 
954
    mMetricsUpdateFlags = 0;
 
955
  }   
 
956
}
 
957
 
 
958
NS_IMETHODIMP_(void)
 
959
nsSVGGlyphFrame::NotifyGlyphFragmentTreeSuspended()
 
960
{
 
961
  // do nothing
 
962
}
 
963
 
 
964
NS_IMETHODIMP_(void)
 
965
nsSVGGlyphFrame::NotifyGlyphFragmentTreeUnsuspended()
 
966
{
 
967
  if (mFragmentTreeDirty) {
 
968
    nsISVGTextFrame* text_frame = GetTextFrame();
 
969
    NS_ASSERTION(text_frame, "null text frame");
 
970
    if (text_frame)
 
971
      text_frame->NotifyGlyphFragmentTreeChange(this);
 
972
    mFragmentTreeDirty = PR_FALSE;
 
973
  }
 
974
}
 
975
 
 
976
 
 
977
 
 
978
//----------------------------------------------------------------------
 
979
//
 
980
 
 
981
void nsSVGGlyphFrame::UpdateGeometry(PRUint32 flags, PRBool bRedraw)
 
982
{
 
983
  mGeometryUpdateFlags |= flags;
 
984
  
 
985
  nsISVGOuterSVGFrame *outerSVGFrame = GetOuterSVGFrame();
 
986
  if (!outerSVGFrame) {
 
987
    NS_ERROR("null outerSVGFrame");
 
988
    return;
 
989
  }
 
990
  
 
991
  PRBool suspended;
 
992
  outerSVGFrame->IsRedrawSuspended(&suspended);
 
993
  if (!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));
 
998
    if (dirty_region)
 
999
      outerSVGFrame->InvalidateRegion(dirty_region, bRedraw);
 
1000
    mGeometryUpdateFlags = 0;
 
1001
  }  
 
1002
}
 
1003
 
 
1004
void nsSVGGlyphFrame::UpdateMetrics(PRUint32 flags)
 
1005
{
 
1006
  mMetricsUpdateFlags |= flags;
 
1007
 
 
1008
  nsISVGTextFrame* text_frame = GetTextFrame();
 
1009
  if (!text_frame) {
 
1010
    NS_ERROR("null text_frame");
 
1011
    return;
 
1012
  }
 
1013
  
 
1014
  PRBool suspended = text_frame->IsMetricsSuspended();
 
1015
  if (!suspended) {
 
1016
    NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::UpdateMetrics");
 
1017
    PRBool metricsDirty;
 
1018
    mMetrics->Update(mMetricsUpdateFlags, &metricsDirty);
 
1019
    if (metricsDirty) {
 
1020
      mGeometryUpdateFlags |= nsISVGGlyphGeometrySource::UPDATEMASK_METRICS;
 
1021
      text_frame->NotifyGlyphMetricsChange(this);
 
1022
    }
 
1023
    mMetricsUpdateFlags = 0;
 
1024
  }
 
1025
}
 
1026
 
 
1027
void nsSVGGlyphFrame::UpdateFragmentTree()
 
1028
{
 
1029
  mFragmentTreeDirty = PR_TRUE;
 
1030
    
 
1031
  nsISVGTextFrame* text_frame = GetTextFrame();
 
1032
  if (!text_frame) {
 
1033
    NS_ERROR("null text_frame");
 
1034
    return;
 
1035
  }
 
1036
  
 
1037
  PRBool suspended = text_frame->IsGlyphFragmentTreeSuspended();
 
1038
  if (!suspended) {
 
1039
    text_frame->NotifyGlyphFragmentTreeChange(this);
 
1040
    mFragmentTreeDirty = PR_FALSE;
 
1041
  }
 
1042
}
 
1043
 
 
1044
nsISVGOuterSVGFrame *
 
1045
nsSVGGlyphFrame::GetOuterSVGFrame()
 
1046
{
 
1047
  NS_ASSERTION(mParent, "null parent");
 
1048
  
 
1049
  nsISVGContainerFrame *containerFrame;
 
1050
  mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), (void**)&containerFrame);
 
1051
  if (!containerFrame) {
 
1052
    NS_ERROR("invalid container");
 
1053
    return nsnull;
 
1054
  }
 
1055
 
 
1056
  return containerFrame->GetOuterSVGFrame();  
 
1057
}
 
1058
 
 
1059
nsISVGTextFrame *
 
1060
nsSVGGlyphFrame::GetTextFrame()
 
1061
{
 
1062
  NS_ASSERTION(mParent, "null parent");
 
1063
 
 
1064
  nsISVGTextContainerFrame *containerFrame;
 
1065
  mParent->QueryInterface(NS_GET_IID(nsISVGTextContainerFrame), (void**)&containerFrame);
 
1066
  if (!containerFrame) {
 
1067
    NS_ERROR("invalid container");
 
1068
    return nsnull;
 
1069
  }
 
1070
 
 
1071
  return containerFrame->GetTextFrame();
 
1072
}