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