layout/svg/SVGTextFrame.h

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef MOZILLA_SVGTEXTFRAME_H
michael@0 7 #define MOZILLA_SVGTEXTFRAME_H
michael@0 8
michael@0 9 #include "mozilla/Attributes.h"
michael@0 10 #include "mozilla/RefPtr.h"
michael@0 11 #include "mozilla/gfx/2D.h"
michael@0 12 #include "gfxMatrix.h"
michael@0 13 #include "gfxRect.h"
michael@0 14 #include "gfxSVGGlyphs.h"
michael@0 15 #include "nsIContent.h"
michael@0 16 #include "nsStubMutationObserver.h"
michael@0 17 #include "nsSVGPaintServerFrame.h"
michael@0 18
michael@0 19 class nsDisplaySVGText;
michael@0 20 class nsRenderingContext;
michael@0 21 class SVGTextFrame;
michael@0 22 class nsTextFrame;
michael@0 23
michael@0 24 typedef nsSVGDisplayContainerFrame SVGTextFrameBase;
michael@0 25
michael@0 26 namespace mozilla {
michael@0 27
michael@0 28 class CharIterator;
michael@0 29 class nsISVGPoint;
michael@0 30 class TextFrameIterator;
michael@0 31 class TextNodeCorrespondenceRecorder;
michael@0 32 struct TextRenderedRun;
michael@0 33 class TextRenderedRunIterator;
michael@0 34
michael@0 35 namespace dom {
michael@0 36 class SVGIRect;
michael@0 37 }
michael@0 38
michael@0 39 /**
michael@0 40 * Information about the positioning for a single character in an SVG <text>
michael@0 41 * element.
michael@0 42 *
michael@0 43 * During SVG text layout, we use infinity values to represent positions and
michael@0 44 * rotations that are not explicitly specified with x/y/rotate attributes.
michael@0 45 */
michael@0 46 struct CharPosition
michael@0 47 {
michael@0 48 CharPosition()
michael@0 49 : mAngle(0),
michael@0 50 mHidden(false),
michael@0 51 mUnaddressable(false),
michael@0 52 mClusterOrLigatureGroupMiddle(false),
michael@0 53 mRunBoundary(false),
michael@0 54 mStartOfChunk(false)
michael@0 55 {
michael@0 56 }
michael@0 57
michael@0 58 CharPosition(gfxPoint aPosition, double aAngle)
michael@0 59 : mPosition(aPosition),
michael@0 60 mAngle(aAngle),
michael@0 61 mHidden(false),
michael@0 62 mUnaddressable(false),
michael@0 63 mClusterOrLigatureGroupMiddle(false),
michael@0 64 mRunBoundary(false),
michael@0 65 mStartOfChunk(false)
michael@0 66 {
michael@0 67 }
michael@0 68
michael@0 69 static CharPosition Unspecified(bool aUnaddressable)
michael@0 70 {
michael@0 71 CharPosition cp(UnspecifiedPoint(), UnspecifiedAngle());
michael@0 72 cp.mUnaddressable = aUnaddressable;
michael@0 73 return cp;
michael@0 74 }
michael@0 75
michael@0 76 bool IsAngleSpecified() const
michael@0 77 {
michael@0 78 return mAngle != UnspecifiedAngle();
michael@0 79 }
michael@0 80
michael@0 81 bool IsXSpecified() const
michael@0 82 {
michael@0 83 return mPosition.x != UnspecifiedCoord();
michael@0 84 }
michael@0 85
michael@0 86 bool IsYSpecified() const
michael@0 87 {
michael@0 88 return mPosition.y != UnspecifiedCoord();
michael@0 89 }
michael@0 90
michael@0 91 gfxPoint mPosition;
michael@0 92 double mAngle;
michael@0 93
michael@0 94 // not displayed due to falling off the end of a <textPath>
michael@0 95 bool mHidden;
michael@0 96
michael@0 97 // skipped in positioning attributes due to being collapsed-away white space
michael@0 98 bool mUnaddressable;
michael@0 99
michael@0 100 // a preceding character is what positioning attributes address
michael@0 101 bool mClusterOrLigatureGroupMiddle;
michael@0 102
michael@0 103 // rendering is split here since an explicit position or rotation was given
michael@0 104 bool mRunBoundary;
michael@0 105
michael@0 106 // an anchored chunk begins here
michael@0 107 bool mStartOfChunk;
michael@0 108
michael@0 109 private:
michael@0 110 static gfxFloat UnspecifiedCoord()
michael@0 111 {
michael@0 112 return std::numeric_limits<gfxFloat>::infinity();
michael@0 113 }
michael@0 114
michael@0 115 static double UnspecifiedAngle()
michael@0 116 {
michael@0 117 return std::numeric_limits<double>::infinity();
michael@0 118 }
michael@0 119
michael@0 120 static gfxPoint UnspecifiedPoint()
michael@0 121 {
michael@0 122 return gfxPoint(UnspecifiedCoord(), UnspecifiedCoord());
michael@0 123 }
michael@0 124 };
michael@0 125
michael@0 126 /**
michael@0 127 * A runnable to mark glyph positions as needing to be recomputed
michael@0 128 * and to invalid the bounds of the SVGTextFrame frame.
michael@0 129 */
michael@0 130 class GlyphMetricsUpdater : public nsRunnable {
michael@0 131 public:
michael@0 132 NS_DECL_NSIRUNNABLE
michael@0 133 GlyphMetricsUpdater(SVGTextFrame* aFrame) : mFrame(aFrame) { }
michael@0 134 static void Run(SVGTextFrame* aFrame);
michael@0 135 void Revoke() { mFrame = nullptr; }
michael@0 136 private:
michael@0 137 SVGTextFrame* mFrame;
michael@0 138 };
michael@0 139
michael@0 140 // Slightly horrible callback for deferring application of opacity
michael@0 141 struct SVGTextContextPaint : public gfxTextContextPaint {
michael@0 142 already_AddRefed<gfxPattern> GetFillPattern(float aOpacity,
michael@0 143 const gfxMatrix& aCTM) MOZ_OVERRIDE;
michael@0 144 already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity,
michael@0 145 const gfxMatrix& aCTM) MOZ_OVERRIDE;
michael@0 146
michael@0 147 void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
michael@0 148 float GetFillOpacity() MOZ_OVERRIDE { return mFillOpacity; }
michael@0 149
michael@0 150 void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
michael@0 151 float GetStrokeOpacity() MOZ_OVERRIDE { return mStrokeOpacity; }
michael@0 152
michael@0 153 struct Paint {
michael@0 154 Paint() : mPaintType(eStyleSVGPaintType_None) {}
michael@0 155
michael@0 156 void SetPaintServer(nsIFrame *aFrame, const gfxMatrix& aContextMatrix,
michael@0 157 nsSVGPaintServerFrame *aPaintServerFrame) {
michael@0 158 mPaintType = eStyleSVGPaintType_Server;
michael@0 159 mPaintDefinition.mPaintServerFrame = aPaintServerFrame;
michael@0 160 mFrame = aFrame;
michael@0 161 mContextMatrix = aContextMatrix;
michael@0 162 }
michael@0 163
michael@0 164 void SetColor(const nscolor &aColor) {
michael@0 165 mPaintType = eStyleSVGPaintType_Color;
michael@0 166 mPaintDefinition.mColor = aColor;
michael@0 167 }
michael@0 168
michael@0 169 void SetContextPaint(gfxTextContextPaint *aContextPaint,
michael@0 170 nsStyleSVGPaintType aPaintType) {
michael@0 171 NS_ASSERTION(aPaintType == eStyleSVGPaintType_ContextFill ||
michael@0 172 aPaintType == eStyleSVGPaintType_ContextStroke,
michael@0 173 "Invalid context paint type");
michael@0 174 mPaintType = aPaintType;
michael@0 175 mPaintDefinition.mContextPaint = aContextPaint;
michael@0 176 }
michael@0 177
michael@0 178 union {
michael@0 179 nsSVGPaintServerFrame *mPaintServerFrame;
michael@0 180 gfxTextContextPaint *mContextPaint;
michael@0 181 nscolor mColor;
michael@0 182 } mPaintDefinition;
michael@0 183
michael@0 184 nsIFrame *mFrame;
michael@0 185 // CTM defining the user space for the pattern we will use.
michael@0 186 gfxMatrix mContextMatrix;
michael@0 187 nsStyleSVGPaintType mPaintType;
michael@0 188
michael@0 189 // Device-space-to-pattern-space
michael@0 190 gfxMatrix mPatternMatrix;
michael@0 191 nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache;
michael@0 192
michael@0 193 already_AddRefed<gfxPattern> GetPattern(float aOpacity,
michael@0 194 nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
michael@0 195 const gfxMatrix& aCTM);
michael@0 196 };
michael@0 197
michael@0 198 Paint mFillPaint;
michael@0 199 Paint mStrokePaint;
michael@0 200
michael@0 201 float mFillOpacity;
michael@0 202 float mStrokeOpacity;
michael@0 203 };
michael@0 204
michael@0 205 } // namespace mozilla
michael@0 206
michael@0 207 /**
michael@0 208 * Frame class for SVG <text> elements, used when the
michael@0 209 * layout.svg.css-text.enabled is true.
michael@0 210 *
michael@0 211 * An SVGTextFrame manages SVG text layout, painting and interaction for
michael@0 212 * all descendent text content elements. The frame tree will look like this:
michael@0 213 *
michael@0 214 * SVGTextFrame -- for <text>
michael@0 215 * <anonymous block frame>
michael@0 216 * ns{Block,Inline,Text}Frames -- for text nodes, <tspan>s, <a>s, etc.
michael@0 217 *
michael@0 218 * SVG text layout is done by:
michael@0 219 *
michael@0 220 * 1. Reflowing the anonymous block frame.
michael@0 221 * 2. Inspecting the (app unit) positions of the glyph for each character in
michael@0 222 * the nsTextFrames underneath the anonymous block frame.
michael@0 223 * 3. Determining the (user unit) positions for each character in the <text>
michael@0 224 * using the x/y/dx/dy/rotate attributes on all the text content elements,
michael@0 225 * and using the step 2 results to fill in any gaps.
michael@0 226 * 4. Applying any other SVG specific text layout (anchoring and text paths)
michael@0 227 * to the positions computed in step 3.
michael@0 228 *
michael@0 229 * Rendering of the text is done by splitting up each nsTextFrame into ranges
michael@0 230 * that can be contiguously painted. (For example <text x="10 20">abcd</text>
michael@0 231 * would have two contiguous ranges: one for the "a" and one for the "bcd".)
michael@0 232 * Each range is called a "text rendered run", represented by a TextRenderedRun
michael@0 233 * object. The TextRenderedRunIterator class performs that splitting and
michael@0 234 * returns a TextRenderedRun for each bit of text to be painted separately.
michael@0 235 *
michael@0 236 * Each rendered run is painted by calling nsTextFrame::PaintText. If the text
michael@0 237 * formatting is simple enough (solid fill, no stroking, etc.), PaintText will
michael@0 238 * itself do the painting. Otherwise, a DrawPathCallback is passed to
michael@0 239 * PaintText so that we can fill the text geometry with SVG paint servers.
michael@0 240 */
michael@0 241 class SVGTextFrame : public SVGTextFrameBase
michael@0 242 {
michael@0 243 friend nsIFrame*
michael@0 244 NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
michael@0 245
michael@0 246 friend class mozilla::CharIterator;
michael@0 247 friend class mozilla::GlyphMetricsUpdater;
michael@0 248 friend class mozilla::TextFrameIterator;
michael@0 249 friend class mozilla::TextNodeCorrespondenceRecorder;
michael@0 250 friend struct mozilla::TextRenderedRun;
michael@0 251 friend class mozilla::TextRenderedRunIterator;
michael@0 252 friend class MutationObserver;
michael@0 253 friend class nsDisplaySVGText;
michael@0 254
michael@0 255 typedef mozilla::gfx::Path Path;
michael@0 256 typedef mozilla::SVGTextContextPaint SVGTextContextPaint;
michael@0 257
michael@0 258 protected:
michael@0 259 SVGTextFrame(nsStyleContext* aContext)
michael@0 260 : SVGTextFrameBase(aContext),
michael@0 261 mFontSizeScaleFactor(1.0f),
michael@0 262 mLastContextScale(1.0f),
michael@0 263 mLengthAdjustScaleFactor(1.0f)
michael@0 264 {
michael@0 265 AddStateBits(NS_STATE_SVG_POSITIONING_DIRTY);
michael@0 266 }
michael@0 267
michael@0 268 public:
michael@0 269 NS_DECL_QUERYFRAME_TARGET(SVGTextFrame)
michael@0 270 NS_DECL_QUERYFRAME
michael@0 271 NS_DECL_FRAMEARENA_HELPERS
michael@0 272
michael@0 273 // nsIFrame:
michael@0 274 virtual void Init(nsIContent* aContent,
michael@0 275 nsIFrame* aParent,
michael@0 276 nsIFrame* aPrevInFlow) MOZ_OVERRIDE;
michael@0 277
michael@0 278 virtual nsresult AttributeChanged(int32_t aNamespaceID,
michael@0 279 nsIAtom* aAttribute,
michael@0 280 int32_t aModType) MOZ_OVERRIDE;
michael@0 281
michael@0 282 virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE
michael@0 283 {
michael@0 284 return GetFirstPrincipalChild()->GetContentInsertionFrame();
michael@0 285 }
michael@0 286
michael@0 287 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
michael@0 288 const nsRect& aDirtyRect,
michael@0 289 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
michael@0 290
michael@0 291 /**
michael@0 292 * Get the "type" of the frame
michael@0 293 *
michael@0 294 * @see nsGkAtoms::svgTextFrame
michael@0 295 */
michael@0 296 virtual nsIAtom* GetType() const MOZ_OVERRIDE;
michael@0 297
michael@0 298 #ifdef DEBUG_FRAME_DUMP
michael@0 299 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE
michael@0 300 {
michael@0 301 return MakeFrameName(NS_LITERAL_STRING("SVGText"), aResult);
michael@0 302 }
michael@0 303 #endif
michael@0 304
michael@0 305 virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE;
michael@0 306
michael@0 307 /**
michael@0 308 * Finds the nsTextFrame for the closest rendered run to the specified point.
michael@0 309 */
michael@0 310 virtual void FindCloserFrameForSelection(nsPoint aPoint,
michael@0 311 FrameWithDistance* aCurrentBestFrame) MOZ_OVERRIDE;
michael@0 312
michael@0 313
michael@0 314
michael@0 315 // nsISVGChildFrame interface:
michael@0 316 virtual void NotifySVGChanged(uint32_t aFlags) MOZ_OVERRIDE;
michael@0 317 virtual nsresult PaintSVG(nsRenderingContext* aContext,
michael@0 318 const nsIntRect* aDirtyRect,
michael@0 319 nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
michael@0 320 virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint) MOZ_OVERRIDE;
michael@0 321 virtual void ReflowSVG() MOZ_OVERRIDE;
michael@0 322 virtual nsRect GetCoveredRegion() MOZ_OVERRIDE;
michael@0 323 virtual SVGBBox GetBBoxContribution(const Matrix& aToBBoxUserspace,
michael@0 324 uint32_t aFlags) MOZ_OVERRIDE;
michael@0 325
michael@0 326 // nsSVGContainerFrame methods:
michael@0 327 virtual gfxMatrix GetCanvasTM(uint32_t aFor,
michael@0 328 nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
michael@0 329
michael@0 330 // SVG DOM text methods:
michael@0 331 uint32_t GetNumberOfChars(nsIContent* aContent);
michael@0 332 float GetComputedTextLength(nsIContent* aContent);
michael@0 333 nsresult SelectSubString(nsIContent* aContent, uint32_t charnum, uint32_t nchars);
michael@0 334 nsresult GetSubStringLength(nsIContent* aContent, uint32_t charnum,
michael@0 335 uint32_t nchars, float* aResult);
michael@0 336 int32_t GetCharNumAtPosition(nsIContent* aContent, mozilla::nsISVGPoint* point);
michael@0 337
michael@0 338 nsresult GetStartPositionOfChar(nsIContent* aContent, uint32_t aCharNum,
michael@0 339 mozilla::nsISVGPoint** aResult);
michael@0 340 nsresult GetEndPositionOfChar(nsIContent* aContent, uint32_t aCharNum,
michael@0 341 mozilla::nsISVGPoint** aResult);
michael@0 342 nsresult GetExtentOfChar(nsIContent* aContent, uint32_t aCharNum,
michael@0 343 mozilla::dom::SVGIRect** aResult);
michael@0 344 nsresult GetRotationOfChar(nsIContent* aContent, uint32_t aCharNum,
michael@0 345 float* aResult);
michael@0 346
michael@0 347 // SVGTextFrame methods:
michael@0 348
michael@0 349 /**
michael@0 350 * Schedules mPositions to be recomputed and the covered region to be
michael@0 351 * updated.
michael@0 352 */
michael@0 353 void NotifyGlyphMetricsChange();
michael@0 354
michael@0 355 /**
michael@0 356 * Calls ScheduleReflowSVGNonDisplayText if this is a non-display frame,
michael@0 357 * and nsSVGUtils::ScheduleReflowSVG otherwise.
michael@0 358 */
michael@0 359 void ScheduleReflowSVG();
michael@0 360
michael@0 361 /**
michael@0 362 * Reflows the anonymous block frame of this non-display SVGTextFrame.
michael@0 363 *
michael@0 364 * When we are under nsSVGDisplayContainerFrame::ReflowSVG, we need to
michael@0 365 * reflow any SVGTextFrame frames in the subtree in case they are
michael@0 366 * being observed (by being for example in a <mask>) and the change
michael@0 367 * that caused the reflow would not already have caused a reflow.
michael@0 368 *
michael@0 369 * Note that displayed SVGTextFrames are reflowed as needed, when PaintSVG
michael@0 370 * is called or some SVG DOM method is called on the element.
michael@0 371 */
michael@0 372 void ReflowSVGNonDisplayText();
michael@0 373
michael@0 374 /**
michael@0 375 * This is a function that behaves similarly to nsSVGUtils::ScheduleReflowSVG,
michael@0 376 * but which will skip over any ancestor non-display container frames on the
michael@0 377 * way to the nsSVGOuterSVGFrame. It exists for the situation where a
michael@0 378 * non-display <text> element has changed and needs to ensure ReflowSVG will
michael@0 379 * be called on its closest display container frame, so that
michael@0 380 * nsSVGDisplayContainerFrame::ReflowSVG will call ReflowSVGNonDisplayText on
michael@0 381 * it.
michael@0 382 *
michael@0 383 * The only case where we have to do this is in response to a style change on
michael@0 384 * a non-display <text>; the only caller of ScheduleReflowSVGNonDisplayText
michael@0 385 * currently is SVGTextFrame::DidSetStyleContext.
michael@0 386 */
michael@0 387 void ScheduleReflowSVGNonDisplayText();
michael@0 388
michael@0 389 /**
michael@0 390 * Updates the mFontSizeScaleFactor value by looking at the range of
michael@0 391 * font-sizes used within the <text>.
michael@0 392 *
michael@0 393 * @return Whether mFontSizeScaleFactor changed.
michael@0 394 */
michael@0 395 bool UpdateFontSizeScaleFactor();
michael@0 396
michael@0 397 double GetFontSizeScaleFactor() const;
michael@0 398
michael@0 399 /**
michael@0 400 * Takes a point from the <text> element's user space and
michael@0 401 * converts it to the appropriate frame user space of aChildFrame,
michael@0 402 * according to which rendered run the point hits.
michael@0 403 */
michael@0 404 gfxPoint TransformFramePointToTextChild(const gfxPoint& aPoint,
michael@0 405 nsIFrame* aChildFrame);
michael@0 406
michael@0 407 /**
michael@0 408 * Takes a rectangle, aRect, in the <text> element's user space, and
michael@0 409 * returns a rectangle in aChildFrame's frame user space that
michael@0 410 * covers intersections of aRect with each rendered run for text frames
michael@0 411 * within aChildFrame.
michael@0 412 */
michael@0 413 gfxRect TransformFrameRectToTextChild(const gfxRect& aRect,
michael@0 414 nsIFrame* aChildFrame);
michael@0 415
michael@0 416 /**
michael@0 417 * Takes an app unit rectangle in the coordinate space of a given descendant
michael@0 418 * frame of this frame, and returns a rectangle in the <text> element's user
michael@0 419 * space that covers all parts of rendered runs that intersect with the
michael@0 420 * rectangle.
michael@0 421 */
michael@0 422 gfxRect TransformFrameRectFromTextChild(const nsRect& aRect,
michael@0 423 nsIFrame* aChildFrame);
michael@0 424
michael@0 425 private:
michael@0 426 /**
michael@0 427 * Mutation observer used to watch for text positioning attribute changes
michael@0 428 * on descendent text content elements (like <tspan>s).
michael@0 429 */
michael@0 430 class MutationObserver : public nsStubMutationObserver {
michael@0 431 public:
michael@0 432 MutationObserver()
michael@0 433 : mFrame(nullptr)
michael@0 434 {
michael@0 435 }
michael@0 436
michael@0 437 void StartObserving(SVGTextFrame* aFrame)
michael@0 438 {
michael@0 439 NS_ASSERTION(!mFrame, "should not be observing yet!");
michael@0 440 mFrame = aFrame;
michael@0 441 aFrame->GetContent()->AddMutationObserver(this);
michael@0 442 }
michael@0 443
michael@0 444 virtual ~MutationObserver()
michael@0 445 {
michael@0 446 if (mFrame) {
michael@0 447 mFrame->GetContent()->RemoveMutationObserver(this);
michael@0 448 }
michael@0 449 }
michael@0 450
michael@0 451 // nsISupports
michael@0 452 NS_DECL_ISUPPORTS
michael@0 453
michael@0 454 // nsIMutationObserver
michael@0 455 NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
michael@0 456 NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
michael@0 457 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
michael@0 458 NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
michael@0 459 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
michael@0 460
michael@0 461 private:
michael@0 462 SVGTextFrame* mFrame;
michael@0 463 };
michael@0 464
michael@0 465 /**
michael@0 466 * Reflows the anonymous block child if it is dirty or has dirty
michael@0 467 * children, or if the SVGTextFrame itself is dirty.
michael@0 468 */
michael@0 469 void MaybeReflowAnonymousBlockChild();
michael@0 470
michael@0 471 /**
michael@0 472 * Performs the actual work of reflowing the anonymous block child.
michael@0 473 */
michael@0 474 void DoReflow();
michael@0 475
michael@0 476 /**
michael@0 477 * Recomputes mPositions by calling DoGlyphPositioning if this information
michael@0 478 * is out of date.
michael@0 479 */
michael@0 480 void UpdateGlyphPositioning();
michael@0 481
michael@0 482 /**
michael@0 483 * Populates mPositions with positioning information for each character
michael@0 484 * within the <text>.
michael@0 485 */
michael@0 486 void DoGlyphPositioning();
michael@0 487
michael@0 488 /**
michael@0 489 * Converts the specified index into mPositions to an addressable
michael@0 490 * character index (as can be used with the SVG DOM text methods)
michael@0 491 * relative to the specified text child content element.
michael@0 492 *
michael@0 493 * @param aIndex The global character index.
michael@0 494 * @param aContent The descendant text child content element that
michael@0 495 * the returned addressable index will be relative to; null
michael@0 496 * means the same as the <text> element.
michael@0 497 * @return The addressable index, or -1 if the index cannot be
michael@0 498 * represented as an addressable index relative to aContent.
michael@0 499 */
michael@0 500 int32_t
michael@0 501 ConvertTextElementCharIndexToAddressableIndex(int32_t aIndex,
michael@0 502 nsIContent* aContent);
michael@0 503
michael@0 504 /**
michael@0 505 * Recursive helper for ResolvePositions below.
michael@0 506 *
michael@0 507 * @param aContent The current node.
michael@0 508 * @param aIndex The current character index.
michael@0 509 * @param aInTextPath Whether we are currently under a <textPath> element.
michael@0 510 * @param aForceStartOfChunk Whether the next character we find should start a
michael@0 511 * new anchored chunk.
michael@0 512 * @return The character index we got up to.
michael@0 513 */
michael@0 514 uint32_t ResolvePositions(nsIContent* aContent, uint32_t aIndex,
michael@0 515 bool aInTextPath, bool& aForceStartOfChunk,
michael@0 516 nsTArray<gfxPoint>& aDeltas);
michael@0 517
michael@0 518 /**
michael@0 519 * Initializes mPositions with character position information based on
michael@0 520 * x/y/rotate attributes, leaving unspecified values in the array if a position
michael@0 521 * was not given for that character. Also fills aDeltas with values based on
michael@0 522 * dx/dy attributes.
michael@0 523 *
michael@0 524 * @param aRunPerGlyph Whether mPositions should record that a new run begins
michael@0 525 * at each glyph.
michael@0 526 * @return True if we recorded any positions.
michael@0 527 */
michael@0 528 bool ResolvePositions(nsTArray<gfxPoint>& aDeltas, bool aRunPerGlyph);
michael@0 529
michael@0 530 /**
michael@0 531 * Determines the position, in app units, of each character in the <text> as
michael@0 532 * laid out by reflow, and appends them to aPositions. Any characters that
michael@0 533 * are undisplayed or trimmed away just get the last position.
michael@0 534 */
michael@0 535 void DetermineCharPositions(nsTArray<nsPoint>& aPositions);
michael@0 536
michael@0 537 /**
michael@0 538 * Sets mStartOfChunk to true for each character in mPositions that starts a
michael@0 539 * line of text.
michael@0 540 */
michael@0 541 void AdjustChunksForLineBreaks();
michael@0 542
michael@0 543 /**
michael@0 544 * Adjusts recorded character positions in mPositions to account for glyph
michael@0 545 * boundaries. Four things are done:
michael@0 546 *
michael@0 547 * 1. mClusterOrLigatureGroupMiddle is set to true for all such characters.
michael@0 548 *
michael@0 549 * 2. Any run and anchored chunk boundaries that begin in the middle of a
michael@0 550 * cluster/ligature group get moved to the start of the next
michael@0 551 * cluster/ligature group.
michael@0 552 *
michael@0 553 * 3. The position of any character in the middle of a cluster/ligature
michael@0 554 * group is updated to take into account partial ligatures and any
michael@0 555 * rotation the glyph as a whole has. (The values that come out of
michael@0 556 * DetermineCharPositions which then get written into mPositions in
michael@0 557 * ResolvePositions store the same position value for each part of the
michael@0 558 * ligature.)
michael@0 559 *
michael@0 560 * 4. The rotation of any character in the middle of a cluster/ligature
michael@0 561 * group is set to the rotation of the first character.
michael@0 562 */
michael@0 563 void AdjustPositionsForClusters();
michael@0 564
michael@0 565 /**
michael@0 566 * Updates the character positions stored in mPositions to account for
michael@0 567 * text anchoring.
michael@0 568 */
michael@0 569 void DoAnchoring();
michael@0 570
michael@0 571 /**
michael@0 572 * Updates character positions in mPositions for those characters inside a
michael@0 573 * <textPath>.
michael@0 574 */
michael@0 575 void DoTextPathLayout();
michael@0 576
michael@0 577 /**
michael@0 578 * Returns whether we need to render the text using
michael@0 579 * nsTextFrame::DrawPathCallbacks rather than directly painting
michael@0 580 * the text frames.
michael@0 581 *
michael@0 582 * @param aShouldPaintSVGGlyphs (out) Whether SVG glyphs in the text
michael@0 583 * should be painted.
michael@0 584 */
michael@0 585 bool ShouldRenderAsPath(nsRenderingContext* aContext, nsTextFrame* aFrame,
michael@0 586 bool& aShouldPaintSVGGlyphs);
michael@0 587
michael@0 588 // Methods to get information for a <textPath> frame.
michael@0 589 nsIFrame* GetTextPathPathFrame(nsIFrame* aTextPathFrame);
michael@0 590 mozilla::TemporaryRef<Path> GetTextPath(nsIFrame* aTextPathFrame);
michael@0 591 gfxFloat GetOffsetScale(nsIFrame* aTextPathFrame);
michael@0 592 gfxFloat GetStartOffset(nsIFrame* aTextPathFrame);
michael@0 593
michael@0 594 DrawMode SetupCairoState(gfxContext* aContext,
michael@0 595 nsIFrame* aFrame,
michael@0 596 gfxTextContextPaint* aOuterContextPaint,
michael@0 597 gfxTextContextPaint** aThisContextPaint);
michael@0 598
michael@0 599 /**
michael@0 600 * Sets up the stroke style for |aFrame| in |aContext| and stores stroke
michael@0 601 * pattern information in |aThisContextPaint|.
michael@0 602 */
michael@0 603 bool SetupCairoStroke(gfxContext* aContext,
michael@0 604 nsIFrame* aFrame,
michael@0 605 gfxTextContextPaint* aOuterContextPaint,
michael@0 606 SVGTextContextPaint* aThisContextPaint);
michael@0 607
michael@0 608 /**
michael@0 609 * Sets up the fill style for |aFrame| in |aContext| and stores fill pattern
michael@0 610 * information in |aThisContextPaint|.
michael@0 611 */
michael@0 612 bool SetupCairoFill(gfxContext* aContext,
michael@0 613 nsIFrame* aFrame,
michael@0 614 gfxTextContextPaint* aOuterContextPaint,
michael@0 615 SVGTextContextPaint* aThisContextPaint);
michael@0 616
michael@0 617 /**
michael@0 618 * Stores in |aTargetPaint| information on how to reconstruct the current
michael@0 619 * fill or stroke pattern. Will also set the paint opacity to transparent if
michael@0 620 * the paint is set to "none".
michael@0 621 * @param aOuterContextPaint pattern information from the outer text context
michael@0 622 * @param aTargetPaint where to store the current pattern information
michael@0 623 * @param aFillOrStroke member pointer to the paint we are setting up
michael@0 624 * @param aProperty the frame property descriptor of the fill or stroke paint
michael@0 625 * server frame
michael@0 626 */
michael@0 627 void SetupInheritablePaint(gfxContext* aContext,
michael@0 628 nsIFrame* aFrame,
michael@0 629 float& aOpacity,
michael@0 630 gfxTextContextPaint* aOuterContextPaint,
michael@0 631 SVGTextContextPaint::Paint& aTargetPaint,
michael@0 632 nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
michael@0 633 const FramePropertyDescriptor* aProperty);
michael@0 634
michael@0 635 /**
michael@0 636 * The MutationObserver we have registered for the <text> element subtree.
michael@0 637 */
michael@0 638 MutationObserver mMutationObserver;
michael@0 639
michael@0 640 /**
michael@0 641 * Cached canvasTM value.
michael@0 642 */
michael@0 643 nsAutoPtr<gfxMatrix> mCanvasTM;
michael@0 644
michael@0 645 /**
michael@0 646 * The number of characters in the DOM after the final nsTextFrame. For
michael@0 647 * example, with
michael@0 648 *
michael@0 649 * <text>abcd<tspan display="none">ef</tspan></text>
michael@0 650 *
michael@0 651 * mTrailingUndisplayedCharacters would be 2.
michael@0 652 */
michael@0 653 uint32_t mTrailingUndisplayedCharacters;
michael@0 654
michael@0 655 /**
michael@0 656 * Computed position information for each DOM character within the <text>.
michael@0 657 */
michael@0 658 nsTArray<mozilla::CharPosition> mPositions;
michael@0 659
michael@0 660 /**
michael@0 661 * mFontSizeScaleFactor is used to cause the nsTextFrames to create text
michael@0 662 * runs with a font size different from the actual font-size property value.
michael@0 663 * This is used so that, for example with:
michael@0 664 *
michael@0 665 * <svg>
michael@0 666 * <g transform="scale(2)">
michael@0 667 * <text font-size="10">abc</text>
michael@0 668 * </g>
michael@0 669 * </svg>
michael@0 670 *
michael@0 671 * a font size of 20 would be used. It's preferable to use a font size that
michael@0 672 * is identical or close to the size that the text will appear on the screen,
michael@0 673 * because at very small or large font sizes, text metrics will be computed
michael@0 674 * differently due to the limited precision that text runs have.
michael@0 675 *
michael@0 676 * mFontSizeScaleFactor is the amount the actual font-size property value
michael@0 677 * should be multiplied by to cause the text run font size to (a) be within a
michael@0 678 * "reasonable" range, and (b) be close to the actual size to be painted on
michael@0 679 * screen. (The "reasonable" range as determined by some #defines in
michael@0 680 * SVGTextFrame.cpp is 8..200.)
michael@0 681 */
michael@0 682 float mFontSizeScaleFactor;
michael@0 683
michael@0 684 /**
michael@0 685 * The scale of the context that we last used to compute mFontSizeScaleFactor.
michael@0 686 * We record this so that we can tell when our scale transform has changed
michael@0 687 * enough to warrant reflowing the text.
michael@0 688 */
michael@0 689 float mLastContextScale;
michael@0 690
michael@0 691 /**
michael@0 692 * The amount that we need to scale each rendered run to account for
michael@0 693 * lengthAdjust="spacingAndGlyphs".
michael@0 694 */
michael@0 695 float mLengthAdjustScaleFactor;
michael@0 696 };
michael@0 697
michael@0 698 #endif

mercurial