00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "nsFrame.h"
00040 #include "nsISVGRendererGlyphGeometry.h"
00041 #include "nsISVGRendererGlyphMetrics.h"
00042 #include "nsISVGRenderer.h"
00043 #include "nsISVGGlyphGeometrySource.h"
00044 #include "nsISVGGlyphFragmentLeaf.h"
00045 #include "nsITextContent.h"
00046 #include "nsISVGChildFrame.h"
00047 #include "nsISVGOuterSVGFrame.h"
00048 #include "nsISVGTextFrame.h"
00049 #include "nsISVGRendererRegion.h"
00050 #include "nsISVGContainerFrame.h"
00051 #include "nsISVGTextContainerFrame.h"
00052 #include "nsReadableUtils.h"
00053 #include "nsCRT.h"
00054 #include "prdtoa.h"
00055 #include "nsIDOMSVGRect.h"
00056 #include "nsILookAndFeel.h"
00057 #include "nsTextFragment.h"
00058
00059 typedef nsFrame nsSVGGlyphFrameBase;
00060
00061 class nsSVGGlyphFrame : public nsSVGGlyphFrameBase,
00062 public nsISVGGlyphGeometrySource,
00063 public nsISVGGlyphFragmentLeaf,
00064 public nsISVGChildFrame
00065 {
00066 protected:
00067 friend nsresult
00068 NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsIContent* aContent,
00069 nsIFrame* parentFrame, nsIFrame** aNewFrame);
00070 nsSVGGlyphFrame();
00071 virtual ~nsSVGGlyphFrame();
00072
00073 public:
00074
00075 NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
00076 NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
00077 NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
00078
00079
00080 NS_IMETHOD
00081 Init(nsIPresContext* aPresContext,
00082 nsIContent* aContent,
00083 nsIFrame* aParent,
00084 nsStyleContext* aContext,
00085 nsIFrame* aPrevInFlow);
00086
00087 NS_IMETHOD ContentChanged(nsIPresContext* aPresContext,
00088 nsIContent* aChild,
00089 nsISupports* aSubContent);
00090
00091 NS_IMETHOD SetSelected(nsIPresContext* aPresContext,
00092 nsIDOMRange* aRange,
00093 PRBool aSelected,
00094 nsSpread aSpread);
00095 NS_IMETHOD GetSelected(PRBool *aSelected) const;
00096 NS_IMETHOD IsSelectable(PRBool* aIsSelectable, PRUint8* aSelectStyle);
00097
00098
00099 NS_IMETHOD Paint(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips);
00100 NS_IMETHOD GetFrameForPoint(float x, float y, nsIFrame** hit);
00101 NS_IMETHOD_(already_AddRefed<nsISVGRendererRegion>) GetCoveredRegion();
00102 NS_IMETHOD InitialUpdate();
00103 NS_IMETHOD NotifyCTMChanged();
00104 NS_IMETHOD NotifyRedrawSuspended();
00105 NS_IMETHOD NotifyRedrawUnsuspended();
00106 NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
00107
00108
00109 NS_DECL_NSISVGGEOMETRYSOURCE
00110
00111
00112 NS_DECL_NSISVGGLYPHMETRICSSOURCE
00113
00114
00115 NS_DECL_NSISVGGLYPHGEOMETRYSOURCE
00116
00117
00118 NS_IMETHOD_(void) SetGlyphPosition(float x, float y);
00119 NS_IMETHOD_(float) GetGlyphPositionX();
00120 NS_IMETHOD_(float) GetGlyphPositionY();
00121 NS_IMETHOD GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics);
00122 NS_IMETHOD_(PRBool) IsStartOfChunk();
00123 NS_IMETHOD_(void) GetAdjustedPosition( float &x, float &y);
00124 NS_IMETHOD_(PRUint32) GetNumberOfChars();
00125 NS_IMETHOD_(PRUint32) GetCharNumberOffset();
00126
00127
00128 NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetFirstGlyphFragment();
00129 NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetNextGlyphFragment();
00130 NS_IMETHOD_(PRUint32) BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch);
00131 NS_IMETHOD_(void) NotifyMetricsSuspended();
00132 NS_IMETHOD_(void) NotifyMetricsUnsuspended();
00133 NS_IMETHOD_(void) NotifyGlyphFragmentTreeSuspended();
00134 NS_IMETHOD_(void) NotifyGlyphFragmentTreeUnsuspended();
00135
00136 protected:
00137 void UpdateGeometry(PRUint32 flags, PRBool bRedraw=PR_TRUE);
00138 void UpdateMetrics(PRUint32 flags);
00139 void UpdateFragmentTree();
00140 nsISVGOuterSVGFrame *GetOuterSVGFrame();
00141 nsISVGTextFrame *GetTextFrame();
00142
00143 nsCOMPtr<nsISVGRendererGlyphGeometry> mGeometry;
00144 nsCOMPtr<nsISVGRendererGlyphMetrics> mMetrics;
00145 float mX, mY;
00146 PRUint32 mCharOffset;
00147 PRUint32 mGeometryUpdateFlags;
00148 PRUint32 mMetricsUpdateFlags;
00149 PRBool mFragmentTreeDirty;
00150 nsString mCharacterData;
00151 };
00152
00153
00154
00155
00156 nsresult
00157 NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* parentFrame,
00158 nsIFrame** aNewFrame)
00159 {
00160 *aNewFrame = nsnull;
00161
00162 #ifdef DEBUG
00163 NS_ASSERTION(parentFrame, "null parent");
00164 nsISVGTextContainerFrame *text_container;
00165 parentFrame->QueryInterface(NS_GET_IID(nsISVGTextContainerFrame), (void**)&text_container);
00166 NS_ASSERTION(text_container, "trying to construct an SVGGlyphFrame for an invalid container");
00167
00168 nsCOMPtr<nsITextContent> tc = do_QueryInterface(aContent);
00169 NS_ASSERTION(tc, "trying to construct an SVGGlyphFrame for wrong content element");
00170 #endif
00171
00172 nsSVGGlyphFrame* it = new (aPresShell) nsSVGGlyphFrame;
00173 if (nsnull == it)
00174 return NS_ERROR_OUT_OF_MEMORY;
00175
00176 *aNewFrame = it;
00177
00178 return NS_OK;
00179 }
00180
00181 nsSVGGlyphFrame::nsSVGGlyphFrame()
00182 : mGeometryUpdateFlags(0), mMetricsUpdateFlags(0),
00183 mCharOffset(0), mFragmentTreeDirty(PR_FALSE)
00184 {
00185 }
00186
00187 nsSVGGlyphFrame::~nsSVGGlyphFrame()
00188 {
00189
00190 }
00191
00192
00193
00194
00195
00196 NS_INTERFACE_MAP_BEGIN(nsSVGGlyphFrame)
00197 NS_INTERFACE_MAP_ENTRY(nsISVGGeometrySource)
00198 NS_INTERFACE_MAP_ENTRY(nsISVGGlyphMetricsSource)
00199 NS_INTERFACE_MAP_ENTRY(nsISVGGlyphGeometrySource)
00200 NS_INTERFACE_MAP_ENTRY(nsISVGGlyphFragmentLeaf)
00201 NS_INTERFACE_MAP_ENTRY(nsISVGGlyphFragmentNode)
00202 NS_INTERFACE_MAP_ENTRY(nsISVGChildFrame)
00203 NS_INTERFACE_MAP_END_INHERITING(nsSVGGlyphFrameBase)
00204
00205
00206
00207
00208 NS_IMETHODIMP
00209 nsSVGGlyphFrame::Init(nsIPresContext* aPresContext,
00210 nsIContent* aContent,
00211 nsIFrame* aParent,
00212 nsStyleContext* aContext,
00213 nsIFrame* aPrevInFlow)
00214 {
00215
00216
00217
00218 mContent = aContent;
00219 NS_IF_ADDREF(mContent);
00220 mParent = aParent;
00221
00222
00223 nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
00224 if (!outerSVGFrame) {
00225 NS_ERROR("No outerSVGFrame");
00226 return NS_ERROR_FAILURE;
00227 }
00228 nsCOMPtr<nsISVGRenderer> renderer;
00229 outerSVGFrame->GetRenderer(getter_AddRefs(renderer));
00230
00231 renderer->CreateGlyphMetrics(this, getter_AddRefs(mMetrics));
00232 if (!mMetrics) return NS_ERROR_FAILURE;
00233
00234 renderer->CreateGlyphGeometry(this, getter_AddRefs(mGeometry));
00235 if (!mGeometry) return NS_ERROR_FAILURE;
00236
00237
00238 SetStyleContext(aPresContext, aContext);
00239
00240 return NS_OK;
00241 }
00242
00243 NS_IMETHODIMP
00244 nsSVGGlyphFrame::ContentChanged(nsIPresContext* aPresContext,
00245 nsIContent* aChild,
00246 nsISupports* aSubContent)
00247 {
00248 #ifdef DEBUG
00249
00250 #endif
00251 nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
00252 if (!outerSVGFrame) {
00253 NS_ERROR("No outerSVGFrame");
00254 return NS_ERROR_FAILURE;
00255 }
00256
00257 outerSVGFrame->SuspendRedraw();
00258 UpdateFragmentTree();
00259 UpdateMetrics(nsISVGGeometrySource::UPDATEMASK_ALL);
00260 UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_ALL);
00261 outerSVGFrame->UnsuspendRedraw();
00262
00263 return NS_OK;
00264 }
00265
00266 NS_IMETHODIMP
00267 nsSVGGlyphFrame::SetSelected(nsIPresContext* aPresContext,
00268 nsIDOMRange* aRange,
00269 PRBool aSelected,
00270 nsSpread aSpread)
00271 {
00272 #if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
00273 printf("nsSVGGlyphFrame(%p)::SetSelected()\n", this);
00274 #endif
00275
00276
00277
00278 PRBool selectable;
00279 IsSelectable(&selectable, nsnull);
00280 if (!selectable)
00281 return NS_OK;
00282
00283 nsFrameState frameState;
00284 GetFrameState(&frameState);
00285 if ( aSelected ){
00286 frameState |= NS_FRAME_SELECTED_CONTENT;
00287 }
00288 else
00289 frameState &= ~NS_FRAME_SELECTED_CONTENT;
00290 SetFrameState(frameState);
00291
00292 UpdateGeometry(nsISVGGlyphGeometrySource::UPDATEMASK_HIGHLIGHT |
00293 nsISVGGlyphGeometrySource::UPDATEMASK_HAS_HIGHLIGHT,
00294 PR_FALSE);
00295
00296 return NS_OK;
00297 }
00298
00299 NS_IMETHODIMP
00300 nsSVGGlyphFrame::GetSelected(PRBool *aSelected) const
00301 {
00302 nsresult rv = nsSVGGlyphFrameBase::GetSelected(aSelected);
00303 #if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
00304 printf("nsSVGGlyphFrame(%p)::GetSelected()=%d\n", this, *aSelected);
00305 #endif
00306 return rv;
00307 }
00308
00309 NS_IMETHODIMP
00310 nsSVGGlyphFrame::IsSelectable(PRBool* aIsSelectable,
00311 PRUint8* aSelectStyle)
00312 {
00313 nsresult rv = nsSVGGlyphFrameBase::IsSelectable(aIsSelectable, aSelectStyle);
00314 #if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
00315 printf("nsSVGGlyphFrame(%p)::IsSelectable()=(%d,%d)\n", this, *aIsSelectable, aSelectStyle);
00316 #endif
00317 return rv;
00318 }
00319
00320
00321
00322
00323
00324 NS_IMETHODIMP
00325 nsSVGGlyphFrame::Paint(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips)
00326 {
00327 #ifdef DEBUG
00328
00329 #endif
00330 mGeometry->Render(canvas);
00331 return NS_OK;
00332 }
00333
00334 NS_IMETHODIMP
00335 nsSVGGlyphFrame::GetFrameForPoint(float x, float y, nsIFrame** hit)
00336 {
00337 #ifdef DEBUG
00338
00339 #endif
00340
00341 *hit = nsnull;
00342 PRBool isHit;
00343 mGeometry->ContainsPoint(x, y, &isHit);
00344 if (isHit)
00345 *hit = this;
00346
00347 return NS_OK;
00348 }
00349
00350 NS_IMETHODIMP_(already_AddRefed<nsISVGRendererRegion>)
00351 nsSVGGlyphFrame::GetCoveredRegion()
00352 {
00353 nsISVGRendererRegion *region = nsnull;
00354 mGeometry->GetCoveredRegion(®ion);
00355 return region;
00356 }
00357
00358 NS_IMETHODIMP
00359 nsSVGGlyphFrame::InitialUpdate()
00360 {
00361 nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
00362 if (!outerSVGFrame) {
00363 NS_ERROR("No outerSVGFrame");
00364 return NS_ERROR_FAILURE;
00365 }
00366
00367 outerSVGFrame->SuspendRedraw();
00368 UpdateFragmentTree();
00369 UpdateMetrics(nsISVGGeometrySource::UPDATEMASK_ALL);
00370 UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_ALL);
00371 outerSVGFrame->UnsuspendRedraw();
00372
00373 return NS_OK;
00374 }
00375
00376 NS_IMETHODIMP
00377 nsSVGGlyphFrame::NotifyCTMChanged()
00378 {
00379 UpdateGeometry(nsISVGGeometrySource::UPDATEMASK_CTM);
00380
00381 return NS_OK;
00382 }
00383
00384 NS_IMETHODIMP
00385 nsSVGGlyphFrame::NotifyRedrawSuspended()
00386 {
00387
00388 return NS_OK;
00389 }
00390
00391 NS_IMETHODIMP
00392 nsSVGGlyphFrame::NotifyRedrawUnsuspended()
00393 {
00394 NS_ASSERTION(!mMetricsUpdateFlags, "dirty metrics in nsSVGGlyphFrame::NotifyRedrawUnsuspended");
00395 NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::NotifyRedrawUnsuspended");
00396
00397 if (mGeometryUpdateFlags != 0) {
00398 nsCOMPtr<nsISVGRendererRegion> dirty_region;
00399 mGeometry->Update(mGeometryUpdateFlags, getter_AddRefs(dirty_region));
00400 if (dirty_region) {
00401 nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame();
00402 if (outerSVGFrame)
00403 outerSVGFrame->InvalidateRegion(dirty_region, PR_TRUE);
00404 }
00405 mGeometryUpdateFlags = 0;
00406 }
00407 return NS_OK;
00408 }
00409
00410 NS_IMETHODIMP
00411 nsSVGGlyphFrame::GetBBox(nsIDOMSVGRect **_retval)
00412 {
00413 *_retval = nsnull;
00414
00415 nsresult rv = mMetrics->GetBoundingBox(_retval);
00416 if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
00417
00418
00419 float x,y;
00420 (*_retval)->GetX(&x);
00421 (*_retval)->GetY(&y);
00422 (*_retval)->SetX(x+mX);
00423 (*_retval)->SetY(y+mY);
00424
00425 return NS_OK;
00426 }
00427
00428
00429
00430
00431
00432 NS_IMETHODIMP
00433 nsSVGGlyphFrame::GetPresContext(nsIPresContext * *aPresContext)
00434 {
00435
00436 *aPresContext = nsSVGGlyphFrameBase::GetPresContext();
00437 NS_ADDREF(*aPresContext);
00438 return NS_OK;
00439 }
00440
00441
00442 NS_IMETHODIMP
00443 nsSVGGlyphFrame::GetCTM(nsIDOMSVGMatrix * *aCTM)
00444 {
00445 *aCTM = nsnull;
00446
00447 nsISVGTextFrame * textframe = GetTextFrame();
00448 NS_ASSERTION(textframe, "null textframe");
00449
00450 return textframe->GetCTM(aCTM);
00451 }
00452
00453
00454 NS_IMETHODIMP
00455 nsSVGGlyphFrame::GetStrokeOpacity(float *aStrokeOpacity)
00456 {
00457 *aStrokeOpacity = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeOpacity;
00458 return NS_OK;
00459 }
00460
00461
00462 NS_IMETHODIMP
00463 nsSVGGlyphFrame::GetStrokeWidth(float *aStrokeWidth)
00464 {
00465 *aStrokeWidth = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeWidth;
00466 return NS_OK;
00467 }
00468
00469
00470 NS_IMETHODIMP
00471 nsSVGGlyphFrame::GetStrokeDashArray(float **arr, PRUint32 *count)
00472 {
00473 *arr = nsnull;
00474 *count = 0;
00475
00476 const nsString &dasharrayString = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeDasharray;
00477 if (dasharrayString.Length() == 0) return NS_OK;
00478
00479
00480
00481 char *str = ToNewCString(dasharrayString);
00482
00483
00484
00485
00486 int i=0;
00487 char* cp = str;
00488 while (*cp) {
00489 if (*cp == ',')
00490 ++i;
00491 ++cp;
00492 }
00493 ++i;
00494
00495
00496
00497 *arr = (float*) nsMemory::Alloc(i * sizeof(float));
00498
00499 cp = str;
00500 char *elem;
00501 while ((elem = nsCRT::strtok(cp, "',", &cp))) {
00502 char *end;
00503 (*arr)[(*count)++] = (float) PR_strtod(elem, &end);
00504 #ifdef DEBUG
00505
00506 #endif
00507 }
00508
00509 nsMemory::Free(str);
00510
00511 return NS_OK;
00512 }
00513
00514
00515 NS_IMETHODIMP
00516 nsSVGGlyphFrame::GetStrokeDashoffset(float *aStrokeDashoffset)
00517 {
00518 *aStrokeDashoffset = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeDashoffset;
00519 return NS_OK;
00520 }
00521
00522
00523 NS_IMETHODIMP
00524 nsSVGGlyphFrame::GetStrokeLinecap(PRUint16 *aStrokeLinecap)
00525 {
00526 *aStrokeLinecap = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeLinecap;
00527 return NS_OK;
00528 }
00529
00530
00531 NS_IMETHODIMP
00532 nsSVGGlyphFrame::GetStrokeLinejoin(PRUint16 *aStrokeLinejoin)
00533 {
00534 *aStrokeLinejoin = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeLinejoin;
00535 return NS_OK;
00536 }
00537
00538
00539 NS_IMETHODIMP
00540 nsSVGGlyphFrame::GetStrokeMiterlimit(float *aStrokeMiterlimit)
00541 {
00542 *aStrokeMiterlimit = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStrokeMiterlimit;
00543 return NS_OK;
00544 }
00545
00546
00547 NS_IMETHODIMP
00548 nsSVGGlyphFrame::GetFillOpacity(float *aFillOpacity)
00549 {
00550 *aFillOpacity = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFillOpacity;
00551 return NS_OK;
00552 }
00553
00554
00555 NS_IMETHODIMP
00556 nsSVGGlyphFrame::GetFillRule(PRUint16 *aFillRule)
00557 {
00558 *aFillRule = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFillRule;
00559 return NS_OK;
00560 }
00561
00562
00563 NS_IMETHODIMP
00564 nsSVGGlyphFrame::GetStrokePaintType(PRUint16 *aStrokePaintType)
00565 {
00566 *aStrokePaintType = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStroke.mType;
00567 return NS_OK;
00568 }
00569
00570
00571 NS_IMETHODIMP
00572 nsSVGGlyphFrame::GetStrokePaint(nscolor *aStrokePaint)
00573 {
00574 *aStrokePaint = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mStroke.mColor;
00575 return NS_OK;
00576 }
00577
00578
00579 NS_IMETHODIMP
00580 nsSVGGlyphFrame::GetFillPaintType(PRUint16 *aFillPaintType)
00581 {
00582 *aFillPaintType = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFill.mType;
00583 return NS_OK;
00584 }
00585
00586
00587 NS_IMETHODIMP
00588 nsSVGGlyphFrame::GetFillPaint(nscolor *aFillPaint)
00589 {
00590 *aFillPaint = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mFill.mColor;
00591 return NS_OK;
00592 }
00593
00594
00595
00596
00597
00598 NS_IMETHODIMP
00599 nsSVGGlyphFrame::GetFont(nsFont *aFont)
00600 {
00601 *aFont = ((const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font))->mFont;
00602
00603
00604
00605
00606
00607 NS_ASSERTION(mParent, "no parent");
00608 nsStyleContext *parentContext = mParent->GetStyleContext();
00609 NS_ASSERTION(parentContext, "no style context on parent");
00610
00611 PRUint8 styleDecorations =
00612 ((const nsStyleTextReset*)parentContext->GetStyleData(eStyleStruct_TextReset))->mTextDecoration;
00613 if (styleDecorations & NS_STYLE_TEXT_DECORATION_UNDERLINE)
00614 aFont->decorations |= NS_FONT_DECORATION_UNDERLINE;
00615 if (styleDecorations & NS_STYLE_TEXT_DECORATION_OVERLINE)
00616 aFont->decorations |= NS_FONT_DECORATION_OVERLINE;
00617 if (styleDecorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH)
00618 aFont->decorations |= NS_FONT_DECORATION_LINE_THROUGH;
00619
00620 return NS_OK;
00621 }
00622
00623
00624 NS_IMETHODIMP
00625 nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
00626 {
00627 aCharacterData = mCharacterData;
00628 return NS_OK;
00629 }
00630
00631
00632 NS_IMETHODIMP
00633 nsSVGGlyphFrame::GetTextRendering(PRUint16 *aTextRendering)
00634 {
00635 *aTextRendering = ((const nsStyleSVG*) mStyleContext->GetStyleData(eStyleStruct_SVG))->mTextRendering;
00636 return NS_OK;
00637 }
00638
00639
00640
00641
00642
00643 NS_IMETHODIMP
00644 nsSVGGlyphFrame::GetMetrics(nsISVGRendererGlyphMetrics * *aMetrics)
00645 {
00646 *aMetrics = mMetrics;
00647 NS_ADDREF(*aMetrics);
00648 return NS_OK;
00649 }
00650
00651
00652 NS_IMETHODIMP
00653 nsSVGGlyphFrame::GetX(float *aX)
00654 {
00655 *aX = mX;
00656 return NS_OK;
00657 }
00658
00659
00660 NS_IMETHODIMP
00661 nsSVGGlyphFrame::GetY(float *aY)
00662 {
00663 *aY = mY;
00664 return NS_OK;
00665 }
00666
00667
00668 NS_IMETHODIMP
00669 nsSVGGlyphFrame::GetHasHighlight(PRBool *aHasHighlight)
00670 {
00671 nsFrameState frameState;
00672 GetFrameState(&frameState);
00673 *aHasHighlight = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
00674
00675 return NS_OK;
00676 }
00677
00678
00679
00680
00681 int CompressIndex(int index, const nsTextFragment*fragment)
00682 {
00683 int ci=0;
00684 if (fragment->Is2b()) {
00685 const PRUnichar *data=fragment->Get2b();
00686 while(*data && index) {
00687 if (XP_IS_SPACE_W(*data)){
00688 do {
00689 ++data;
00690 --index;
00691 }while(XP_IS_SPACE_W(*data) && index);
00692 }
00693 else {
00694 ++data;
00695 --index;
00696 }
00697 ++ci;
00698 }
00699 }
00700 else {
00701 const char *data=fragment->Get1b();
00702 while(*data && index) {
00703 if (XP_IS_SPACE_W(*data)){
00704 do {
00705 ++data;
00706 --index;
00707 }while(XP_IS_SPACE_W(*data) && index);
00708 }
00709 else {
00710 ++data;
00711 --index;
00712 }
00713 ++ci;
00714 }
00715 }
00716
00717 return ci;
00718 }
00719
00720 int UncompressIndex(int index, PRBool bRightAffinity, const nsTextFragment*fragment)
00721 {
00722
00723 return index;
00724 }
00725
00726
00727 NS_IMETHODIMP
00728 nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars, nscolor *foreground, nscolor *background)
00729 {
00730 *foreground = NS_RGB(255,255,255);
00731 *background = NS_RGB(0,0,0);
00732 *charnum=0;
00733 *nchars=0;
00734
00735 PRBool hasHighlight;
00736 GetHasHighlight(&hasHighlight);
00737
00738 if (!hasHighlight) {
00739 NS_ERROR("nsSVGGlyphFrame::GetHighlight() called by renderer when there is no highlight");
00740 return NS_ERROR_FAILURE;
00741 }
00742
00743
00744 nsIPresContext *presContext = nsSVGGlyphFrameBase::GetPresContext();
00745
00746 nsCOMPtr<nsITextContent> tc = do_QueryInterface(mContent);
00747 NS_ASSERTION(tc, "no textcontent interface");
00748
00749
00750
00751 const nsTextFragment*fragment=nsnull;
00752 tc->GetText(&fragment);
00753 NS_ASSERTION(fragment, "null text fragment");
00754
00755
00756
00757 SelectionDetails *details = nsnull;
00758 {
00759 nsCOMPtr<nsIFrameSelection> frameSelection;
00760 {
00761 nsCOMPtr<nsISelectionController> controller;
00762 GetSelectionController(presContext, getter_AddRefs(controller));
00763
00764 if (!controller) {
00765 NS_ERROR("no selection controller");
00766 return NS_ERROR_FAILURE;
00767 }
00768 frameSelection = do_QueryInterface(controller);
00769 }
00770 if (!frameSelection) {
00771 nsCOMPtr<nsIPresShell> shell;
00772 presContext->GetShell(getter_AddRefs(shell));
00773 NS_ASSERTION(shell, "no presshell");
00774 shell->GetFrameSelection(getter_AddRefs(frameSelection));
00775 }
00776 if (!frameSelection) {
00777 NS_ERROR("no frameselection interface");
00778 return NS_ERROR_FAILURE;
00779 }
00780
00781 PRInt32 length;
00782 tc->GetTextLength(&length);
00783
00784 frameSelection->LookUpSelection(mContent, 0, length,
00785 &details, PR_FALSE);
00786 }
00787
00788 #if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
00789 {
00790 SelectionDetails *dp = details;
00791 printf("nsSVGGlyphFrame(%p)::GetHighlight() [\n", this);
00792 while (dp) {
00793 printf("selection detail: %d(%d)->%d(%d) type %d\n",
00794 dp->mStart, CompressIndex(dp->mStart, fragment),
00795 dp->mEnd, CompressIndex(dp->mEnd, fragment),
00796 dp->mType);
00797 dp = dp->mNext;
00798 }
00799 printf("]\n");
00800
00801 }
00802 #endif
00803
00804 if (details) {
00805 NS_ASSERTION(details->mNext==nsnull, "can't do multiple selection ranges");
00806
00807 *charnum=CompressIndex(details->mStart, fragment);
00808 *nchars=CompressIndex(details->mEnd, fragment)-*charnum;
00809
00810 nsCOMPtr<nsILookAndFeel> look;
00811 presContext->GetLookAndFeel(getter_AddRefs(look));
00812 NS_ASSERTION(look, "no LookAndFeel");
00813 if (look) {
00814 look->GetColor(nsILookAndFeel::eColor_TextSelectBackground, *background);
00815 look->GetColor(nsILookAndFeel::eColor_TextSelectForeground, *foreground);
00816 }
00817
00818 SelectionDetails *dp = details;
00819 while ((dp=details->mNext) != nsnull) {
00820 delete details;
00821 details = dp;
00822 }
00823 delete details;
00824 }
00825
00826 return NS_OK;
00827 }
00828
00829
00830
00831
00832
00833 NS_IMETHODIMP_(void)
00834 nsSVGGlyphFrame::SetGlyphPosition(float x, float y)
00835 {
00836 mX = x;
00837 mY = y;
00838 UpdateGeometry(nsISVGGlyphGeometrySource::UPDATEMASK_X |
00839 nsISVGGlyphGeometrySource::UPDATEMASK_Y);
00840 }
00841
00842 NS_IMETHODIMP_(float)
00843 nsSVGGlyphFrame::GetGlyphPositionX()
00844 {
00845 return mX;
00846 }
00847
00848 NS_IMETHODIMP_(float)
00849 nsSVGGlyphFrame::GetGlyphPositionY()
00850 {
00851 return mY;
00852 }
00853
00854
00855 NS_IMETHODIMP
00856 nsSVGGlyphFrame::GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics)
00857 {
00858 *metrics = mMetrics;
00859 NS_ADDREF(*metrics);
00860 return NS_OK;
00861 }
00862
00863 NS_IMETHODIMP_(PRBool)
00864 nsSVGGlyphFrame::IsStartOfChunk()
00865 {
00866
00867
00868
00869
00870 return PR_FALSE;
00871 }
00872
00873 NS_IMETHODIMP_(void)
00874 nsSVGGlyphFrame::GetAdjustedPosition( float &x, float &y)
00875 {
00876 }
00877
00878 NS_IMETHODIMP_(PRUint32)
00879 nsSVGGlyphFrame::GetNumberOfChars()
00880 {
00881 return mCharacterData.Length();
00882 }
00883
00884 NS_IMETHODIMP_(PRUint32)
00885 nsSVGGlyphFrame::GetCharNumberOffset()
00886 {
00887 return mCharOffset;
00888 }
00889
00890
00891
00892
00893 NS_IMETHODIMP_(nsISVGGlyphFragmentLeaf *)
00894 nsSVGGlyphFrame::GetFirstGlyphFragment()
00895 {
00896 return this;
00897 }
00898
00899 NS_IMETHODIMP_(nsISVGGlyphFragmentLeaf *)
00900 nsSVGGlyphFrame::GetNextGlyphFragment()
00901 {
00902 nsIFrame* sibling = mNextSibling;
00903 while (sibling) {
00904 nsISVGGlyphFragmentNode *node = nsnull;
00905 sibling->QueryInterface(NS_GET_IID(nsISVGGlyphFragmentNode), (void**)&node);
00906 if (node)
00907 return node->GetFirstGlyphFragment();
00908 sibling->GetNextSibling(&sibling);
00909 }
00910
00911
00912
00913 NS_ASSERTION(mParent, "null parent");
00914 nsISVGGlyphFragmentNode *node = nsnull;
00915 mParent->QueryInterface(NS_GET_IID(nsISVGGlyphFragmentNode), (void**)&node);
00916 return node ? node->GetNextGlyphFragment() : nsnull;
00917 }
00918
00919 NS_IMETHODIMP_(PRUint32)
00920 nsSVGGlyphFrame::BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch)
00921 {
00922
00923
00924
00925 mCharOffset = charNum;
00926 nsCOMPtr<nsITextContent> tc = do_QueryInterface(mContent);
00927
00928 PRInt32 length;
00929 tc->GetTextLength(&length);
00930 if (length==0) {
00931 #ifdef DEBUG
00932 printf("Glyph frame with zero length text\n");
00933 #endif
00934 mCharacterData = NS_LITERAL_STRING("");
00935 return charNum;
00936 }
00937
00938 tc->CopyText(mCharacterData);
00939 mCharacterData.CompressWhitespace(charNum==0, lastBranch);
00940
00941 return charNum+mCharacterData.Length();
00942 }
00943
00944 NS_IMETHODIMP_(void)
00945 nsSVGGlyphFrame::NotifyMetricsSuspended()
00946 {
00947
00948 }
00949
00950 NS_IMETHODIMP_(void)
00951 nsSVGGlyphFrame::NotifyMetricsUnsuspended()
00952 {
00953 NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::NotifyMetricsUnsuspended");
00954
00955 if (mMetricsUpdateFlags != 0) {
00956 PRBool metricsDirty;
00957 mMetrics->Update(mMetricsUpdateFlags, &metricsDirty);
00958 if (metricsDirty) {
00959 mGeometryUpdateFlags |= nsISVGGlyphGeometrySource::UPDATEMASK_METRICS;
00960 nsISVGTextFrame* text_frame = GetTextFrame();
00961 NS_ASSERTION(text_frame, "null text frame");
00962 if (text_frame)
00963 text_frame->NotifyGlyphMetricsChange(this);
00964 }
00965 mMetricsUpdateFlags = 0;
00966 }
00967 }
00968
00969 NS_IMETHODIMP_(void)
00970 nsSVGGlyphFrame::NotifyGlyphFragmentTreeSuspended()
00971 {
00972
00973 }
00974
00975 NS_IMETHODIMP_(void)
00976 nsSVGGlyphFrame::NotifyGlyphFragmentTreeUnsuspended()
00977 {
00978 if (mFragmentTreeDirty) {
00979 nsISVGTextFrame* text_frame = GetTextFrame();
00980 NS_ASSERTION(text_frame, "null text frame");
00981 if (text_frame)
00982 text_frame->NotifyGlyphFragmentTreeChange(this);
00983 mFragmentTreeDirty = PR_FALSE;
00984 }
00985 }
00986
00987
00988
00989
00990
00991
00992 void nsSVGGlyphFrame::UpdateGeometry(PRUint32 flags, PRBool bRedraw)
00993 {
00994 mGeometryUpdateFlags |= flags;
00995
00996 nsISVGOuterSVGFrame *outerSVGFrame = GetOuterSVGFrame();
00997 if (!outerSVGFrame) {
00998 NS_ERROR("null outerSVGFrame");
00999 return;
01000 }
01001
01002 PRBool suspended;
01003 outerSVGFrame->IsRedrawSuspended(&suspended);
01004 if (!suspended) {
01005 NS_ASSERTION(!mMetricsUpdateFlags, "dirty metrics in nsSVGGlyphFrame::UpdateGeometry");
01006 NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::UpdateGeometry");
01007 nsCOMPtr<nsISVGRendererRegion> dirty_region;
01008 mGeometry->Update(mGeometryUpdateFlags, getter_AddRefs(dirty_region));
01009 if (dirty_region)
01010 outerSVGFrame->InvalidateRegion(dirty_region, bRedraw);
01011 mGeometryUpdateFlags = 0;
01012 }
01013 }
01014
01015 void nsSVGGlyphFrame::UpdateMetrics(PRUint32 flags)
01016 {
01017 mMetricsUpdateFlags |= flags;
01018
01019 nsISVGTextFrame* text_frame = GetTextFrame();
01020 if (!text_frame) {
01021 NS_ERROR("null text_frame");
01022 return;
01023 }
01024
01025 PRBool suspended = text_frame->IsMetricsSuspended();
01026 if (!suspended) {
01027 NS_ASSERTION(!mFragmentTreeDirty, "dirty fragmenttree in nsSVGGlyphFrame::UpdateMetrics");
01028 PRBool metricsDirty;
01029 mMetrics->Update(mMetricsUpdateFlags, &metricsDirty);
01030 if (metricsDirty) {
01031 mGeometryUpdateFlags |= nsISVGGlyphGeometrySource::UPDATEMASK_METRICS;
01032 text_frame->NotifyGlyphMetricsChange(this);
01033 }
01034 mMetricsUpdateFlags = 0;
01035 }
01036 }
01037
01038 void nsSVGGlyphFrame::UpdateFragmentTree()
01039 {
01040 mFragmentTreeDirty = PR_TRUE;
01041
01042 nsISVGTextFrame* text_frame = GetTextFrame();
01043 if (!text_frame) {
01044 NS_ERROR("null text_frame");
01045 return;
01046 }
01047
01048 PRBool suspended = text_frame->IsGlyphFragmentTreeSuspended();
01049 if (!suspended) {
01050 text_frame->NotifyGlyphFragmentTreeChange(this);
01051 mFragmentTreeDirty = PR_FALSE;
01052 }
01053 }
01054
01055 nsISVGOuterSVGFrame *
01056 nsSVGGlyphFrame::GetOuterSVGFrame()
01057 {
01058 NS_ASSERTION(mParent, "null parent");
01059
01060 nsISVGContainerFrame *containerFrame;
01061 mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), (void**)&containerFrame);
01062 if (!containerFrame) {
01063 NS_ERROR("invalid container");
01064 return nsnull;
01065 }
01066
01067 return containerFrame->GetOuterSVGFrame();
01068 }
01069
01070 nsISVGTextFrame *
01071 nsSVGGlyphFrame::GetTextFrame()
01072 {
01073 NS_ASSERTION(mParent, "null parent");
01074
01075 nsISVGTextContainerFrame *containerFrame;
01076 mParent->QueryInterface(NS_GET_IID(nsISVGTextContainerFrame), (void**)&containerFrame);
01077 if (!containerFrame) {
01078 NS_ERROR("invalid container");
01079 return nsnull;
01080 }
01081
01082 return containerFrame->GetTextFrame();
01083 }