layout/svg/SVGTextFrame.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/svg/SVGTextFrame.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,698 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef MOZILLA_SVGTEXTFRAME_H
    1.10 +#define MOZILLA_SVGTEXTFRAME_H
    1.11 +
    1.12 +#include "mozilla/Attributes.h"
    1.13 +#include "mozilla/RefPtr.h"
    1.14 +#include "mozilla/gfx/2D.h"
    1.15 +#include "gfxMatrix.h"
    1.16 +#include "gfxRect.h"
    1.17 +#include "gfxSVGGlyphs.h"
    1.18 +#include "nsIContent.h"
    1.19 +#include "nsStubMutationObserver.h"
    1.20 +#include "nsSVGPaintServerFrame.h"
    1.21 +
    1.22 +class nsDisplaySVGText;
    1.23 +class nsRenderingContext;
    1.24 +class SVGTextFrame;
    1.25 +class nsTextFrame;
    1.26 +
    1.27 +typedef nsSVGDisplayContainerFrame SVGTextFrameBase;
    1.28 +
    1.29 +namespace mozilla {
    1.30 +
    1.31 +class CharIterator;
    1.32 +class nsISVGPoint;
    1.33 +class TextFrameIterator;
    1.34 +class TextNodeCorrespondenceRecorder;
    1.35 +struct TextRenderedRun;
    1.36 +class TextRenderedRunIterator;
    1.37 +
    1.38 +namespace dom {
    1.39 +class SVGIRect;
    1.40 +}
    1.41 +
    1.42 +/**
    1.43 + * Information about the positioning for a single character in an SVG <text>
    1.44 + * element.
    1.45 + *
    1.46 + * During SVG text layout, we use infinity values to represent positions and
    1.47 + * rotations that are not explicitly specified with x/y/rotate attributes.
    1.48 + */
    1.49 +struct CharPosition
    1.50 +{
    1.51 +  CharPosition()
    1.52 +    : mAngle(0),
    1.53 +      mHidden(false),
    1.54 +      mUnaddressable(false),
    1.55 +      mClusterOrLigatureGroupMiddle(false),
    1.56 +      mRunBoundary(false),
    1.57 +      mStartOfChunk(false)
    1.58 +  {
    1.59 +  }
    1.60 +
    1.61 +  CharPosition(gfxPoint aPosition, double aAngle)
    1.62 +    : mPosition(aPosition),
    1.63 +      mAngle(aAngle),
    1.64 +      mHidden(false),
    1.65 +      mUnaddressable(false),
    1.66 +      mClusterOrLigatureGroupMiddle(false),
    1.67 +      mRunBoundary(false),
    1.68 +      mStartOfChunk(false)
    1.69 +  {
    1.70 +  }
    1.71 +
    1.72 +  static CharPosition Unspecified(bool aUnaddressable)
    1.73 +  {
    1.74 +    CharPosition cp(UnspecifiedPoint(), UnspecifiedAngle());
    1.75 +    cp.mUnaddressable = aUnaddressable;
    1.76 +    return cp;
    1.77 +  }
    1.78 +
    1.79 +  bool IsAngleSpecified() const
    1.80 +  {
    1.81 +    return mAngle != UnspecifiedAngle();
    1.82 +  }
    1.83 +
    1.84 +  bool IsXSpecified() const
    1.85 +  {
    1.86 +    return mPosition.x != UnspecifiedCoord();
    1.87 +  }
    1.88 +
    1.89 +  bool IsYSpecified() const
    1.90 +  {
    1.91 +    return mPosition.y != UnspecifiedCoord();
    1.92 +  }
    1.93 +
    1.94 +  gfxPoint mPosition;
    1.95 +  double mAngle;
    1.96 +
    1.97 +  // not displayed due to falling off the end of a <textPath>
    1.98 +  bool mHidden;
    1.99 +
   1.100 +  // skipped in positioning attributes due to being collapsed-away white space
   1.101 +  bool mUnaddressable;
   1.102 +
   1.103 +  // a preceding character is what positioning attributes address
   1.104 +  bool mClusterOrLigatureGroupMiddle;
   1.105 +
   1.106 +  // rendering is split here since an explicit position or rotation was given
   1.107 +  bool mRunBoundary;
   1.108 +
   1.109 +  // an anchored chunk begins here
   1.110 +  bool mStartOfChunk;
   1.111 +
   1.112 +private:
   1.113 +  static gfxFloat UnspecifiedCoord()
   1.114 +  {
   1.115 +    return std::numeric_limits<gfxFloat>::infinity();
   1.116 +  }
   1.117 +
   1.118 +  static double UnspecifiedAngle()
   1.119 +  {
   1.120 +    return std::numeric_limits<double>::infinity();
   1.121 +  }
   1.122 +
   1.123 +  static gfxPoint UnspecifiedPoint()
   1.124 +  {
   1.125 +    return gfxPoint(UnspecifiedCoord(), UnspecifiedCoord());
   1.126 +  }
   1.127 +};
   1.128 +
   1.129 +/**
   1.130 + * A runnable to mark glyph positions as needing to be recomputed
   1.131 + * and to invalid the bounds of the SVGTextFrame frame.
   1.132 + */
   1.133 +class GlyphMetricsUpdater : public nsRunnable {
   1.134 +public:
   1.135 +  NS_DECL_NSIRUNNABLE
   1.136 +  GlyphMetricsUpdater(SVGTextFrame* aFrame) : mFrame(aFrame) { }
   1.137 +  static void Run(SVGTextFrame* aFrame);
   1.138 +  void Revoke() { mFrame = nullptr; }
   1.139 +private:
   1.140 +  SVGTextFrame* mFrame;
   1.141 +};
   1.142 +
   1.143 +// Slightly horrible callback for deferring application of opacity
   1.144 +struct SVGTextContextPaint : public gfxTextContextPaint {
   1.145 +  already_AddRefed<gfxPattern> GetFillPattern(float aOpacity,
   1.146 +                                              const gfxMatrix& aCTM) MOZ_OVERRIDE;
   1.147 +  already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity,
   1.148 +                                                const gfxMatrix& aCTM) MOZ_OVERRIDE;
   1.149 +
   1.150 +  void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
   1.151 +  float GetFillOpacity() MOZ_OVERRIDE { return mFillOpacity; }
   1.152 +
   1.153 +  void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
   1.154 +  float GetStrokeOpacity() MOZ_OVERRIDE { return mStrokeOpacity; }
   1.155 +
   1.156 +  struct Paint {
   1.157 +    Paint() : mPaintType(eStyleSVGPaintType_None) {}
   1.158 +
   1.159 +    void SetPaintServer(nsIFrame *aFrame, const gfxMatrix& aContextMatrix,
   1.160 +                        nsSVGPaintServerFrame *aPaintServerFrame) {
   1.161 +      mPaintType = eStyleSVGPaintType_Server;
   1.162 +      mPaintDefinition.mPaintServerFrame = aPaintServerFrame;
   1.163 +      mFrame = aFrame;
   1.164 +      mContextMatrix = aContextMatrix;
   1.165 +    }
   1.166 +
   1.167 +    void SetColor(const nscolor &aColor) {
   1.168 +      mPaintType = eStyleSVGPaintType_Color;
   1.169 +      mPaintDefinition.mColor = aColor;
   1.170 +    }
   1.171 +
   1.172 +    void SetContextPaint(gfxTextContextPaint *aContextPaint,
   1.173 +                         nsStyleSVGPaintType aPaintType) {
   1.174 +      NS_ASSERTION(aPaintType == eStyleSVGPaintType_ContextFill ||
   1.175 +                   aPaintType == eStyleSVGPaintType_ContextStroke,
   1.176 +                   "Invalid context paint type");
   1.177 +      mPaintType = aPaintType;
   1.178 +      mPaintDefinition.mContextPaint = aContextPaint;
   1.179 +    }
   1.180 +
   1.181 +    union {
   1.182 +      nsSVGPaintServerFrame *mPaintServerFrame;
   1.183 +      gfxTextContextPaint *mContextPaint;
   1.184 +      nscolor mColor;
   1.185 +    } mPaintDefinition;
   1.186 +
   1.187 +    nsIFrame *mFrame;
   1.188 +    // CTM defining the user space for the pattern we will use.
   1.189 +    gfxMatrix mContextMatrix;
   1.190 +    nsStyleSVGPaintType mPaintType;
   1.191 +
   1.192 +    // Device-space-to-pattern-space
   1.193 +    gfxMatrix mPatternMatrix;
   1.194 +    nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache;
   1.195 +
   1.196 +    already_AddRefed<gfxPattern> GetPattern(float aOpacity,
   1.197 +                                            nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
   1.198 +                                            const gfxMatrix& aCTM);
   1.199 +  };
   1.200 +
   1.201 +  Paint mFillPaint;
   1.202 +  Paint mStrokePaint;
   1.203 +
   1.204 +  float mFillOpacity;
   1.205 +  float mStrokeOpacity;
   1.206 +};
   1.207 +
   1.208 +} // namespace mozilla
   1.209 +
   1.210 +/**
   1.211 + * Frame class for SVG <text> elements, used when the
   1.212 + * layout.svg.css-text.enabled is true.
   1.213 + *
   1.214 + * An SVGTextFrame manages SVG text layout, painting and interaction for
   1.215 + * all descendent text content elements.  The frame tree will look like this:
   1.216 + *
   1.217 + *   SVGTextFrame                     -- for <text>
   1.218 + *     <anonymous block frame>
   1.219 + *       ns{Block,Inline,Text}Frames  -- for text nodes, <tspan>s, <a>s, etc.
   1.220 + *
   1.221 + * SVG text layout is done by:
   1.222 + *
   1.223 + *   1. Reflowing the anonymous block frame.
   1.224 + *   2. Inspecting the (app unit) positions of the glyph for each character in
   1.225 + *      the nsTextFrames underneath the anonymous block frame.
   1.226 + *   3. Determining the (user unit) positions for each character in the <text>
   1.227 + *      using the x/y/dx/dy/rotate attributes on all the text content elements,
   1.228 + *      and using the step 2 results to fill in any gaps.
   1.229 + *   4. Applying any other SVG specific text layout (anchoring and text paths)
   1.230 + *      to the positions computed in step 3.
   1.231 + *
   1.232 + * Rendering of the text is done by splitting up each nsTextFrame into ranges
   1.233 + * that can be contiguously painted.  (For example <text x="10 20">abcd</text>
   1.234 + * would have two contiguous ranges: one for the "a" and one for the "bcd".)
   1.235 + * Each range is called a "text rendered run", represented by a TextRenderedRun
   1.236 + * object.  The TextRenderedRunIterator class performs that splitting and
   1.237 + * returns a TextRenderedRun for each bit of text to be painted separately.
   1.238 + *
   1.239 + * Each rendered run is painted by calling nsTextFrame::PaintText.  If the text
   1.240 + * formatting is simple enough (solid fill, no stroking, etc.), PaintText will
   1.241 + * itself do the painting.  Otherwise, a DrawPathCallback is passed to
   1.242 + * PaintText so that we can fill the text geometry with SVG paint servers.
   1.243 + */
   1.244 +class SVGTextFrame : public SVGTextFrameBase
   1.245 +{
   1.246 +  friend nsIFrame*
   1.247 +  NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.248 +
   1.249 +  friend class mozilla::CharIterator;
   1.250 +  friend class mozilla::GlyphMetricsUpdater;
   1.251 +  friend class mozilla::TextFrameIterator;
   1.252 +  friend class mozilla::TextNodeCorrespondenceRecorder;
   1.253 +  friend struct mozilla::TextRenderedRun;
   1.254 +  friend class mozilla::TextRenderedRunIterator;
   1.255 +  friend class MutationObserver;
   1.256 +  friend class nsDisplaySVGText;
   1.257 +
   1.258 +  typedef mozilla::gfx::Path Path;
   1.259 +  typedef mozilla::SVGTextContextPaint SVGTextContextPaint;
   1.260 +
   1.261 +protected:
   1.262 +  SVGTextFrame(nsStyleContext* aContext)
   1.263 +    : SVGTextFrameBase(aContext),
   1.264 +      mFontSizeScaleFactor(1.0f),
   1.265 +      mLastContextScale(1.0f),
   1.266 +      mLengthAdjustScaleFactor(1.0f)
   1.267 +  {
   1.268 +    AddStateBits(NS_STATE_SVG_POSITIONING_DIRTY);
   1.269 +  }
   1.270 +
   1.271 +public:
   1.272 +  NS_DECL_QUERYFRAME_TARGET(SVGTextFrame)
   1.273 +  NS_DECL_QUERYFRAME
   1.274 +  NS_DECL_FRAMEARENA_HELPERS
   1.275 +
   1.276 +  // nsIFrame:
   1.277 +  virtual void Init(nsIContent* aContent,
   1.278 +                    nsIFrame*   aParent,
   1.279 +                    nsIFrame*   aPrevInFlow) MOZ_OVERRIDE;
   1.280 +
   1.281 +  virtual nsresult AttributeChanged(int32_t aNamespaceID,
   1.282 +                                    nsIAtom* aAttribute,
   1.283 +                                    int32_t aModType) MOZ_OVERRIDE;
   1.284 +
   1.285 +  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE
   1.286 +  {
   1.287 +    return GetFirstPrincipalChild()->GetContentInsertionFrame();
   1.288 +  }
   1.289 +
   1.290 +  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   1.291 +                                const nsRect&           aDirtyRect,
   1.292 +                                const nsDisplayListSet& aLists) MOZ_OVERRIDE;
   1.293 +
   1.294 +  /**
   1.295 +   * Get the "type" of the frame
   1.296 +   *
   1.297 +   * @see nsGkAtoms::svgTextFrame
   1.298 +   */
   1.299 +  virtual nsIAtom* GetType() const MOZ_OVERRIDE;
   1.300 +
   1.301 +#ifdef DEBUG_FRAME_DUMP
   1.302 +  virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE
   1.303 +  {
   1.304 +    return MakeFrameName(NS_LITERAL_STRING("SVGText"), aResult);
   1.305 +  }
   1.306 +#endif
   1.307 +
   1.308 +  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE;
   1.309 +
   1.310 +  /**
   1.311 +   * Finds the nsTextFrame for the closest rendered run to the specified point.
   1.312 +   */
   1.313 +  virtual void FindCloserFrameForSelection(nsPoint aPoint,
   1.314 +                                          FrameWithDistance* aCurrentBestFrame) MOZ_OVERRIDE;
   1.315 +
   1.316 +
   1.317 +
   1.318 +  // nsISVGChildFrame interface:
   1.319 +  virtual void NotifySVGChanged(uint32_t aFlags) MOZ_OVERRIDE;
   1.320 +  virtual nsresult PaintSVG(nsRenderingContext* aContext,
   1.321 +                            const nsIntRect* aDirtyRect,
   1.322 +                            nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
   1.323 +  virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint) MOZ_OVERRIDE;
   1.324 +  virtual void ReflowSVG() MOZ_OVERRIDE;
   1.325 +  virtual nsRect GetCoveredRegion() MOZ_OVERRIDE;
   1.326 +  virtual SVGBBox GetBBoxContribution(const Matrix& aToBBoxUserspace,
   1.327 +                                      uint32_t aFlags) MOZ_OVERRIDE;
   1.328 +
   1.329 +  // nsSVGContainerFrame methods:
   1.330 +  virtual gfxMatrix GetCanvasTM(uint32_t aFor,
   1.331 +                                nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
   1.332 +  
   1.333 +  // SVG DOM text methods:
   1.334 +  uint32_t GetNumberOfChars(nsIContent* aContent);
   1.335 +  float GetComputedTextLength(nsIContent* aContent);
   1.336 +  nsresult SelectSubString(nsIContent* aContent, uint32_t charnum, uint32_t nchars);
   1.337 +  nsresult GetSubStringLength(nsIContent* aContent, uint32_t charnum,
   1.338 +                              uint32_t nchars, float* aResult);
   1.339 +  int32_t GetCharNumAtPosition(nsIContent* aContent, mozilla::nsISVGPoint* point);
   1.340 +
   1.341 +  nsresult GetStartPositionOfChar(nsIContent* aContent, uint32_t aCharNum,
   1.342 +                                  mozilla::nsISVGPoint** aResult);
   1.343 +  nsresult GetEndPositionOfChar(nsIContent* aContent, uint32_t aCharNum,
   1.344 +                                mozilla::nsISVGPoint** aResult);
   1.345 +  nsresult GetExtentOfChar(nsIContent* aContent, uint32_t aCharNum,
   1.346 +                           mozilla::dom::SVGIRect** aResult);
   1.347 +  nsresult GetRotationOfChar(nsIContent* aContent, uint32_t aCharNum,
   1.348 +                             float* aResult);
   1.349 +
   1.350 +  // SVGTextFrame methods:
   1.351 +
   1.352 +  /**
   1.353 +   * Schedules mPositions to be recomputed and the covered region to be
   1.354 +   * updated.
   1.355 +   */
   1.356 +  void NotifyGlyphMetricsChange();
   1.357 +
   1.358 +  /**
   1.359 +   * Calls ScheduleReflowSVGNonDisplayText if this is a non-display frame,
   1.360 +   * and nsSVGUtils::ScheduleReflowSVG otherwise.
   1.361 +   */
   1.362 +  void ScheduleReflowSVG();
   1.363 +
   1.364 +  /**
   1.365 +   * Reflows the anonymous block frame of this non-display SVGTextFrame.
   1.366 +   *
   1.367 +   * When we are under nsSVGDisplayContainerFrame::ReflowSVG, we need to
   1.368 +   * reflow any SVGTextFrame frames in the subtree in case they are
   1.369 +   * being observed (by being for example in a <mask>) and the change
   1.370 +   * that caused the reflow would not already have caused a reflow.
   1.371 +   *
   1.372 +   * Note that displayed SVGTextFrames are reflowed as needed, when PaintSVG
   1.373 +   * is called or some SVG DOM method is called on the element.
   1.374 +   */
   1.375 +  void ReflowSVGNonDisplayText();
   1.376 +
   1.377 +  /**
   1.378 +   * This is a function that behaves similarly to nsSVGUtils::ScheduleReflowSVG,
   1.379 +   * but which will skip over any ancestor non-display container frames on the
   1.380 +   * way to the nsSVGOuterSVGFrame.  It exists for the situation where a
   1.381 +   * non-display <text> element has changed and needs to ensure ReflowSVG will
   1.382 +   * be called on its closest display container frame, so that
   1.383 +   * nsSVGDisplayContainerFrame::ReflowSVG will call ReflowSVGNonDisplayText on
   1.384 +   * it.
   1.385 +   *
   1.386 +   * The only case where we have to do this is in response to a style change on
   1.387 +   * a non-display <text>; the only caller of ScheduleReflowSVGNonDisplayText
   1.388 +   * currently is SVGTextFrame::DidSetStyleContext.
   1.389 +   */
   1.390 +  void ScheduleReflowSVGNonDisplayText();
   1.391 +
   1.392 +  /**
   1.393 +   * Updates the mFontSizeScaleFactor value by looking at the range of
   1.394 +   * font-sizes used within the <text>.
   1.395 +   *
   1.396 +   * @return Whether mFontSizeScaleFactor changed.
   1.397 +   */
   1.398 +  bool UpdateFontSizeScaleFactor();
   1.399 +
   1.400 +  double GetFontSizeScaleFactor() const;
   1.401 +
   1.402 +  /**
   1.403 +   * Takes a point from the <text> element's user space and
   1.404 +   * converts it to the appropriate frame user space of aChildFrame,
   1.405 +   * according to which rendered run the point hits.
   1.406 +   */
   1.407 +  gfxPoint TransformFramePointToTextChild(const gfxPoint& aPoint,
   1.408 +                                          nsIFrame* aChildFrame);
   1.409 +
   1.410 +  /**
   1.411 +   * Takes a rectangle, aRect, in the <text> element's user space, and
   1.412 +   * returns a rectangle in aChildFrame's frame user space that
   1.413 +   * covers intersections of aRect with each rendered run for text frames
   1.414 +   * within aChildFrame.
   1.415 +   */
   1.416 +  gfxRect TransformFrameRectToTextChild(const gfxRect& aRect,
   1.417 +                                        nsIFrame* aChildFrame);
   1.418 +
   1.419 +  /**
   1.420 +   * Takes an app unit rectangle in the coordinate space of a given descendant
   1.421 +   * frame of this frame, and returns a rectangle in the <text> element's user
   1.422 +   * space that covers all parts of rendered runs that intersect with the
   1.423 +   * rectangle.
   1.424 +   */
   1.425 +  gfxRect TransformFrameRectFromTextChild(const nsRect& aRect,
   1.426 +                                          nsIFrame* aChildFrame);
   1.427 +
   1.428 +private:
   1.429 +  /**
   1.430 +   * Mutation observer used to watch for text positioning attribute changes
   1.431 +   * on descendent text content elements (like <tspan>s).
   1.432 +   */
   1.433 +  class MutationObserver : public nsStubMutationObserver {
   1.434 +  public:
   1.435 +    MutationObserver()
   1.436 +      : mFrame(nullptr)
   1.437 +    {
   1.438 +    }
   1.439 +
   1.440 +    void StartObserving(SVGTextFrame* aFrame)
   1.441 +    {
   1.442 +      NS_ASSERTION(!mFrame, "should not be observing yet!");
   1.443 +      mFrame = aFrame;
   1.444 +      aFrame->GetContent()->AddMutationObserver(this);
   1.445 +    }
   1.446 +
   1.447 +    virtual ~MutationObserver()
   1.448 +    {
   1.449 +      if (mFrame) {
   1.450 +        mFrame->GetContent()->RemoveMutationObserver(this);
   1.451 +      }
   1.452 +    }
   1.453 +
   1.454 +    // nsISupports
   1.455 +    NS_DECL_ISUPPORTS
   1.456 +
   1.457 +    // nsIMutationObserver
   1.458 +    NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   1.459 +    NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   1.460 +    NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
   1.461 +    NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   1.462 +    NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
   1.463 +
   1.464 +  private:
   1.465 +    SVGTextFrame* mFrame;
   1.466 +  };
   1.467 +
   1.468 +  /**
   1.469 +   * Reflows the anonymous block child if it is dirty or has dirty
   1.470 +   * children, or if the SVGTextFrame itself is dirty.
   1.471 +   */
   1.472 +  void MaybeReflowAnonymousBlockChild();
   1.473 +
   1.474 +  /**
   1.475 +   * Performs the actual work of reflowing the anonymous block child.
   1.476 +   */
   1.477 +  void DoReflow();
   1.478 +
   1.479 +  /**
   1.480 +   * Recomputes mPositions by calling DoGlyphPositioning if this information
   1.481 +   * is out of date.
   1.482 +   */
   1.483 +  void UpdateGlyphPositioning();
   1.484 +
   1.485 +  /**
   1.486 +   * Populates mPositions with positioning information for each character
   1.487 +   * within the <text>.
   1.488 +   */
   1.489 +  void DoGlyphPositioning();
   1.490 +
   1.491 +  /**
   1.492 +   * Converts the specified index into mPositions to an addressable
   1.493 +   * character index (as can be used with the SVG DOM text methods)
   1.494 +   * relative to the specified text child content element.
   1.495 +   *
   1.496 +   * @param aIndex The global character index.
   1.497 +   * @param aContent The descendant text child content element that
   1.498 +   *   the returned addressable index will be relative to; null
   1.499 +   *   means the same as the <text> element.
   1.500 +   * @return The addressable index, or -1 if the index cannot be
   1.501 +   *   represented as an addressable index relative to aContent.
   1.502 +   */
   1.503 +  int32_t
   1.504 +  ConvertTextElementCharIndexToAddressableIndex(int32_t aIndex,
   1.505 +                                                nsIContent* aContent);
   1.506 +
   1.507 +  /**
   1.508 +   * Recursive helper for ResolvePositions below.
   1.509 +   *
   1.510 +   * @param aContent The current node.
   1.511 +   * @param aIndex The current character index.
   1.512 +   * @param aInTextPath Whether we are currently under a <textPath> element.
   1.513 +   * @param aForceStartOfChunk Whether the next character we find should start a
   1.514 +   *   new anchored chunk.
   1.515 +   * @return The character index we got up to.
   1.516 +   */
   1.517 +  uint32_t ResolvePositions(nsIContent* aContent, uint32_t aIndex,
   1.518 +                            bool aInTextPath, bool& aForceStartOfChunk,
   1.519 +                            nsTArray<gfxPoint>& aDeltas);
   1.520 +
   1.521 +  /**
   1.522 +   * Initializes mPositions with character position information based on
   1.523 +   * x/y/rotate attributes, leaving unspecified values in the array if a position
   1.524 +   * was not given for that character.  Also fills aDeltas with values based on
   1.525 +   * dx/dy attributes.
   1.526 +   *
   1.527 +   * @param aRunPerGlyph Whether mPositions should record that a new run begins
   1.528 +   *   at each glyph.
   1.529 +   * @return True if we recorded any positions.
   1.530 +   */
   1.531 +  bool ResolvePositions(nsTArray<gfxPoint>& aDeltas, bool aRunPerGlyph);
   1.532 +
   1.533 +  /**
   1.534 +   * Determines the position, in app units, of each character in the <text> as
   1.535 +   * laid out by reflow, and appends them to aPositions.  Any characters that
   1.536 +   * are undisplayed or trimmed away just get the last position.
   1.537 +   */
   1.538 +  void DetermineCharPositions(nsTArray<nsPoint>& aPositions);
   1.539 +
   1.540 +  /**
   1.541 +   * Sets mStartOfChunk to true for each character in mPositions that starts a
   1.542 +   * line of text.
   1.543 +   */
   1.544 +  void AdjustChunksForLineBreaks();
   1.545 +
   1.546 +  /**
   1.547 +   * Adjusts recorded character positions in mPositions to account for glyph
   1.548 +   * boundaries.  Four things are done:
   1.549 +   *
   1.550 +   *   1. mClusterOrLigatureGroupMiddle is set to true for all such characters.
   1.551 +   *
   1.552 +   *   2. Any run and anchored chunk boundaries that begin in the middle of a
   1.553 +   *      cluster/ligature group get moved to the start of the next
   1.554 +   *      cluster/ligature group.
   1.555 +   *
   1.556 +   *   3. The position of any character in the middle of a cluster/ligature
   1.557 +   *      group is updated to take into account partial ligatures and any
   1.558 +   *      rotation the glyph as a whole has.  (The values that come out of
   1.559 +   *      DetermineCharPositions which then get written into mPositions in
   1.560 +   *      ResolvePositions store the same position value for each part of the
   1.561 +   *      ligature.)
   1.562 +   *
   1.563 +   *   4. The rotation of any character in the middle of a cluster/ligature
   1.564 +   *      group is set to the rotation of the first character.
   1.565 +   */
   1.566 +  void AdjustPositionsForClusters();
   1.567 +
   1.568 +  /**
   1.569 +   * Updates the character positions stored in mPositions to account for
   1.570 +   * text anchoring.
   1.571 +   */
   1.572 +  void DoAnchoring();
   1.573 +
   1.574 +  /**
   1.575 +   * Updates character positions in mPositions for those characters inside a
   1.576 +   * <textPath>.
   1.577 +   */
   1.578 +  void DoTextPathLayout();
   1.579 +
   1.580 +  /**
   1.581 +   * Returns whether we need to render the text using
   1.582 +   * nsTextFrame::DrawPathCallbacks rather than directly painting
   1.583 +   * the text frames.
   1.584 +   *
   1.585 +   * @param aShouldPaintSVGGlyphs (out) Whether SVG glyphs in the text
   1.586 +   *   should be painted.
   1.587 +   */
   1.588 +  bool ShouldRenderAsPath(nsRenderingContext* aContext, nsTextFrame* aFrame,
   1.589 +                          bool& aShouldPaintSVGGlyphs);
   1.590 +
   1.591 +  // Methods to get information for a <textPath> frame.
   1.592 +  nsIFrame* GetTextPathPathFrame(nsIFrame* aTextPathFrame);
   1.593 +  mozilla::TemporaryRef<Path> GetTextPath(nsIFrame* aTextPathFrame);
   1.594 +  gfxFloat GetOffsetScale(nsIFrame* aTextPathFrame);
   1.595 +  gfxFloat GetStartOffset(nsIFrame* aTextPathFrame);
   1.596 +
   1.597 +  DrawMode SetupCairoState(gfxContext* aContext,
   1.598 +                           nsIFrame* aFrame,
   1.599 +                           gfxTextContextPaint* aOuterContextPaint,
   1.600 +                           gfxTextContextPaint** aThisContextPaint);
   1.601 +
   1.602 +  /**
   1.603 +   * Sets up the stroke style for |aFrame| in |aContext| and stores stroke
   1.604 +   * pattern information in |aThisContextPaint|.
   1.605 +   */
   1.606 +  bool SetupCairoStroke(gfxContext* aContext,
   1.607 +                        nsIFrame* aFrame,
   1.608 +                        gfxTextContextPaint* aOuterContextPaint,
   1.609 +                        SVGTextContextPaint* aThisContextPaint);
   1.610 +
   1.611 +  /**
   1.612 +   * Sets up the fill style for |aFrame| in |aContext| and stores fill pattern
   1.613 +   * information in |aThisContextPaint|.
   1.614 +   */
   1.615 +  bool SetupCairoFill(gfxContext* aContext,
   1.616 +                      nsIFrame* aFrame,
   1.617 +                      gfxTextContextPaint* aOuterContextPaint,
   1.618 +                      SVGTextContextPaint* aThisContextPaint);
   1.619 +
   1.620 +  /**
   1.621 +   * Stores in |aTargetPaint| information on how to reconstruct the current
   1.622 +   * fill or stroke pattern. Will also set the paint opacity to transparent if
   1.623 +   * the paint is set to "none".
   1.624 +   * @param aOuterContextPaint pattern information from the outer text context
   1.625 +   * @param aTargetPaint where to store the current pattern information
   1.626 +   * @param aFillOrStroke member pointer to the paint we are setting up
   1.627 +   * @param aProperty the frame property descriptor of the fill or stroke paint
   1.628 +   *   server frame
   1.629 +   */
   1.630 +  void SetupInheritablePaint(gfxContext* aContext,
   1.631 +                             nsIFrame* aFrame,
   1.632 +                             float& aOpacity,
   1.633 +                             gfxTextContextPaint* aOuterContextPaint,
   1.634 +                             SVGTextContextPaint::Paint& aTargetPaint,
   1.635 +                             nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
   1.636 +                             const FramePropertyDescriptor* aProperty);
   1.637 +
   1.638 +  /**
   1.639 +   * The MutationObserver we have registered for the <text> element subtree.
   1.640 +   */
   1.641 +  MutationObserver mMutationObserver;
   1.642 +
   1.643 +  /**
   1.644 +   * Cached canvasTM value.
   1.645 +   */
   1.646 +  nsAutoPtr<gfxMatrix> mCanvasTM;
   1.647 +
   1.648 +  /**
   1.649 +   * The number of characters in the DOM after the final nsTextFrame.  For
   1.650 +   * example, with
   1.651 +   *
   1.652 +   *   <text>abcd<tspan display="none">ef</tspan></text>
   1.653 +   *
   1.654 +   * mTrailingUndisplayedCharacters would be 2.
   1.655 +   */
   1.656 +  uint32_t mTrailingUndisplayedCharacters;
   1.657 +
   1.658 +  /**
   1.659 +   * Computed position information for each DOM character within the <text>.
   1.660 +   */
   1.661 +  nsTArray<mozilla::CharPosition> mPositions;
   1.662 +
   1.663 +  /**
   1.664 +   * mFontSizeScaleFactor is used to cause the nsTextFrames to create text
   1.665 +   * runs with a font size different from the actual font-size property value.
   1.666 +   * This is used so that, for example with:
   1.667 +   *
   1.668 +   *   <svg>
   1.669 +   *     <g transform="scale(2)">
   1.670 +   *       <text font-size="10">abc</text>
   1.671 +   *     </g>
   1.672 +   *   </svg>
   1.673 +   *
   1.674 +   * a font size of 20 would be used.  It's preferable to use a font size that
   1.675 +   * is identical or close to the size that the text will appear on the screen,
   1.676 +   * because at very small or large font sizes, text metrics will be computed
   1.677 +   * differently due to the limited precision that text runs have.
   1.678 +   *
   1.679 +   * mFontSizeScaleFactor is the amount the actual font-size property value
   1.680 +   * should be multiplied by to cause the text run font size to (a) be within a
   1.681 +   * "reasonable" range, and (b) be close to the actual size to be painted on
   1.682 +   * screen.  (The "reasonable" range as determined by some #defines in
   1.683 +   * SVGTextFrame.cpp is 8..200.)
   1.684 +   */
   1.685 +  float mFontSizeScaleFactor;
   1.686 +
   1.687 +  /**
   1.688 +   * The scale of the context that we last used to compute mFontSizeScaleFactor.
   1.689 +   * We record this so that we can tell when our scale transform has changed
   1.690 +   * enough to warrant reflowing the text.
   1.691 +   */
   1.692 +  float mLastContextScale;
   1.693 +
   1.694 +  /**
   1.695 +   * The amount that we need to scale each rendered run to account for
   1.696 +   * lengthAdjust="spacingAndGlyphs".
   1.697 +   */
   1.698 +  float mLengthAdjustScaleFactor;
   1.699 +};
   1.700 +
   1.701 +#endif

mercurial