layout/base/nsCSSRendering.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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/. */
     6 /* utility functions for drawing borders and backgrounds */
     8 #ifndef nsCSSRendering_h___
     9 #define nsCSSRendering_h___
    11 #include "gfxBlur.h"
    12 #include "gfxContext.h"
    13 #include "nsLayoutUtils.h"
    14 #include "nsStyleStruct.h"
    15 #include "nsIFrame.h"
    17 class nsStyleContext;
    18 class nsPresContext;
    19 class nsRenderingContext;
    21 namespace mozilla {
    23 namespace layers {
    24 class ImageContainer;
    25 }
    27 // A CSSSizeOrRatio represents a (possibly partially specified) size for use
    28 // in computing image sizes. Either or both of the width and height might be
    29 // given. A ratio of width to height may also be given. If we at least two
    30 // of these then we can compute a concrete size, that is a width and height.
    31 struct CSSSizeOrRatio
    32 {
    33   CSSSizeOrRatio()
    34     : mRatio(0, 0)
    35     , mHasWidth(false)
    36     , mHasHeight(false) {}
    38   bool CanComputeConcreteSize() const
    39   {
    40     return mHasWidth + mHasHeight + HasRatio() >= 2;
    41   }
    42   bool IsConcrete() const { return mHasWidth && mHasHeight; }
    43   bool HasRatio() const { return mRatio.width > 0 && mRatio.height > 0; }
    44   bool IsEmpty() const
    45   {
    46     return (mHasWidth && mWidth <= 0) ||
    47            (mHasHeight && mHeight <= 0) ||
    48            mRatio.width <= 0 || mRatio.height <= 0; 
    49   }
    51   // CanComputeConcreteSize must return true when ComputeConcreteSize is
    52   // called.
    53   nsSize ComputeConcreteSize() const;
    55   void SetWidth(nscoord aWidth)
    56   {
    57     mWidth = aWidth;
    58     mHasWidth = true;
    59     if (mHasHeight) {
    60       mRatio = nsSize(mWidth, mHeight);
    61     }
    62   }
    63   void SetHeight(nscoord aHeight)
    64   {
    65     mHeight = aHeight;
    66     mHasHeight = true;
    67     if (mHasWidth) {
    68       mRatio = nsSize(mWidth, mHeight);
    69     }
    70   }
    71   void SetSize(const nsSize& aSize)
    72   {
    73     mWidth = aSize.width;
    74     mHeight = aSize.height;
    75     mHasWidth = true;
    76     mHasHeight = true;
    77     mRatio = aSize;    
    78   }
    79   void SetRatio(const nsSize& aRatio)
    80   {
    81     MOZ_ASSERT(!mHasWidth || !mHasHeight,
    82                "Probably shouldn't be setting a ratio if we have a concrete size");
    83     mRatio = aRatio;
    84   }
    86   nsSize mRatio;
    87   nscoord mWidth;
    88   nscoord mHeight;
    89   bool mHasWidth;
    90   bool mHasHeight;
    91 };
    93 }
    95 /**
    96  * This is a small wrapper class to encapsulate image drawing that can draw an
    97  * nsStyleImage image, which may internally be a real image, a sub image, or a
    98  * CSS gradient.
    99  *
   100  * @note Always call the member functions in the order of PrepareImage(),
   101  * SetSize(), and Draw*().
   102  */
   103 class nsImageRenderer {
   104 public:
   105   typedef mozilla::layers::LayerManager LayerManager;
   106   typedef mozilla::layers::ImageContainer ImageContainer;
   108   enum {
   109     FLAG_SYNC_DECODE_IMAGES = 0x01,
   110     FLAG_PAINTING_TO_WINDOW = 0x02
   111   };
   112   enum FitType
   113   {
   114     CONTAIN,
   115     COVER
   116   };
   118   nsImageRenderer(nsIFrame* aForFrame, const nsStyleImage* aImage, uint32_t aFlags);
   119   ~nsImageRenderer();
   120   /**
   121    * Populates member variables to get ready for rendering.
   122    * @return true iff the image is ready, and there is at least a pixel to
   123    * draw.
   124    */
   125   bool PrepareImage();
   127   /**
   128    * The three Compute*Size functions correspond to the sizing algorthms and
   129    * definitions from the CSS Image Values and Replaced Content spec. See
   130    * http://dev.w3.org/csswg/css-images-3/#sizing .
   131    */
   133   /**
   134    * Compute the intrinsic size of the image as defined in the CSS Image Values
   135    * spec. The intrinsic size is the unscaled size which the image would ideally
   136    * like to be in app units.
   137    */
   138   mozilla::CSSSizeOrRatio ComputeIntrinsicSize();
   140   /**
   141    * Compute the size of the rendered image using either the 'cover' or
   142    * 'contain' constraints (aFitType).
   143    * aIntrinsicRatio may be an invalid ratio, that is one or both of its
   144    * dimensions can be less than or equal to zero.
   145    */
   146   static nsSize ComputeConstrainedSize(const nsSize& aConstrainingSize,
   147                                        const nsSize& aIntrinsicRatio,
   148                                        FitType aFitType);
   149   /**
   150    * Compute the size of the rendered image (the concrete size) where no cover/
   151    * contain constraints are given. The 'default algorithm' from the CSS Image
   152    * Values spec.
   153    */
   154   static nsSize ComputeConcreteSize(const mozilla::CSSSizeOrRatio& aSpecifiedSize,
   155                                     const mozilla::CSSSizeOrRatio& aIntrinsicSize,
   156                                     const nsSize& aDefaultSize);
   158   /**
   159    * Set this image's preferred size. This will be its intrinsic size where
   160    * specified and the default size where it is not. Used as the unscaled size
   161    * when rendering the image.
   162    */
   163   void SetPreferredSize(const mozilla::CSSSizeOrRatio& aIntrinsicSize,
   164                         const nsSize& aDefaultSize);
   166   /**
   167    * Draws the image to the target rendering context.
   168    * aSrc is a rect on the source image which will be mapped to aDest.
   169    * @see nsLayoutUtils::DrawImage() for other parameters.
   170    */
   171   void Draw(nsPresContext*       aPresContext,
   172             nsRenderingContext&  aRenderingContext,
   173             const nsRect&        aDirtyRect,
   174             const nsRect&        aFill,
   175             const nsRect&        aDest,
   176             const mozilla::CSSIntRect& aSrc);
   177   /**
   178    * Draws the image to the target rendering context using background-specific
   179    * arguments.
   180    * @see nsLayoutUtils::DrawImage() for parameters.
   181    */
   182   void DrawBackground(nsPresContext*       aPresContext,
   183                       nsRenderingContext&  aRenderingContext,
   184                       const nsRect&        aDest,
   185                       const nsRect&        aFill,
   186                       const nsPoint&       aAnchor,
   187                       const nsRect&        aDirty);
   189   /**
   190    * Draw the image to a single component of a border-image style rendering.
   191    * aFill The destination rect to be drawn into
   192    * aSrc is the part of the image to be rendered into a tile (aUnitSize in
   193    * aFill), if aSrc and the dest tile are different sizes, the image will be
   194    * scaled to map aSrc onto the dest tile.
   195    * aHFill and aVFill are the repeat patterns for the component -
   196    * NS_STYLE_BORDER_IMAGE_REPEAT_*
   197    * aUnitSize The scaled size of a single source rect (in destination coords)
   198    * aIndex identifies the component: 0 1 2
   199    *                                  3 4 5
   200    *                                  6 7 8
   201    */
   202   void
   203   DrawBorderImageComponent(nsPresContext*       aPresContext,
   204                            nsRenderingContext&  aRenderingContext,
   205                            const nsRect&        aDirtyRect,
   206                            const nsRect&        aFill,
   207                            const mozilla::CSSIntRect& aSrc,
   208                            uint8_t              aHFill,
   209                            uint8_t              aVFill,
   210                            const nsSize&        aUnitSize,
   211                            uint8_t              aIndex);
   213   bool IsRasterImage();
   214   bool IsAnimatedImage();
   215   already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager);
   217   bool IsReady() { return mIsReady; }
   219 private:
   220   /**
   221    * Helper method for creating a gfxDrawable from mPaintServerFrame or 
   222    * mImageElementSurface.
   223    * Requires mType is eStyleImageType_Element.
   224    * Returns null if we cannot create the drawable.
   225    */
   226   already_AddRefed<gfxDrawable> DrawableForElement(const nsRect& aImageRect,
   227                                                    nsRenderingContext&  aRenderingContext);
   229   nsIFrame*                 mForFrame;
   230   const nsStyleImage*       mImage;
   231   nsStyleImageType          mType;
   232   nsCOMPtr<imgIContainer>   mImageContainer;
   233   nsRefPtr<nsStyleGradient> mGradientData;
   234   nsIFrame*                 mPaintServerFrame;
   235   nsLayoutUtils::SurfaceFromElementResult mImageElementSurface;
   236   bool                      mIsReady;
   237   nsSize                    mSize; // unscaled size of the image, in app units
   238   uint32_t                  mFlags;
   239 };
   241 /**
   242  * A struct representing all the information needed to paint a background
   243  * image to some target, taking into account all CSS background-* properties.
   244  * See PrepareBackgroundLayer.
   245  */
   246 struct nsBackgroundLayerState {
   247   /**
   248    * @param aFlags some combination of nsCSSRendering::PAINTBG_* flags
   249    */
   250   nsBackgroundLayerState(nsIFrame* aForFrame, const nsStyleImage* aImage, uint32_t aFlags)
   251     : mImageRenderer(aForFrame, aImage, aFlags), mCompositingOp(gfxContext::OPERATOR_OVER) {}
   253   /**
   254    * The nsImageRenderer that will be used to draw the background.
   255    */
   256   nsImageRenderer mImageRenderer;
   257   /**
   258    * A rectangle that one copy of the image tile is mapped onto. Same
   259    * coordinate system as aBorderArea/aBGClipRect passed into
   260    * PrepareBackgroundLayer.
   261    */
   262   nsRect mDestArea;
   263   /**
   264    * The actual rectangle that should be filled with (complete or partial)
   265    * image tiles. Same coordinate system as aBorderArea/aBGClipRect passed into
   266    * PrepareBackgroundLayer.
   267    */
   268   nsRect mFillArea;
   269   /**
   270    * The anchor point that should be snapped to a pixel corner. Same
   271    * coordinate system as aBorderArea/aBGClipRect passed into
   272    * PrepareBackgroundLayer.
   273    */
   274   nsPoint mAnchor;
   275   /**
   276    * The compositing operation that the image should use
   277    */
   278   gfxContext::GraphicsOperator mCompositingOp;
   279 };
   281 struct nsCSSRendering {
   282   /**
   283    * Initialize any static variables used by nsCSSRendering.
   284    */
   285   static void Init();
   287   /**
   288    * Clean up any static variables used by nsCSSRendering.
   289    */
   290   static void Shutdown();
   292   static void PaintBoxShadowInner(nsPresContext* aPresContext,
   293                                   nsRenderingContext& aRenderingContext,
   294                                   nsIFrame* aForFrame,
   295                                   const nsRect& aFrameArea,
   296                                   const nsRect& aDirtyRect);
   298   static void PaintBoxShadowOuter(nsPresContext* aPresContext,
   299                                   nsRenderingContext& aRenderingContext,
   300                                   nsIFrame* aForFrame,
   301                                   const nsRect& aFrameArea,
   302                                   const nsRect& aDirtyRect,
   303                                   float aOpacity = 1.0);
   305   static void ComputePixelRadii(const nscoord *aAppUnitsRadii,
   306                                 nscoord aAppUnitsPerPixel,
   307                                 gfxCornerSizes *oBorderRadii);
   309   /**
   310    * Render the border for an element using css rendering rules
   311    * for borders. aSkipSides is a bitmask of the sides to skip
   312    * when rendering. If 0 then no sides are skipped.
   313    */
   314   static void PaintBorder(nsPresContext* aPresContext,
   315                           nsRenderingContext& aRenderingContext,
   316                           nsIFrame* aForFrame,
   317                           const nsRect& aDirtyRect,
   318                           const nsRect& aBorderArea,
   319                           nsStyleContext* aStyleContext,
   320                           int aSkipSides = 0);
   322   /**
   323    * Like PaintBorder, but taking an nsStyleBorder argument instead of
   324    * getting it from aStyleContext.
   325    */
   326   static void PaintBorderWithStyleBorder(nsPresContext* aPresContext,
   327                                          nsRenderingContext& aRenderingContext,
   328                                          nsIFrame* aForFrame,
   329                                          const nsRect& aDirtyRect,
   330                                          const nsRect& aBorderArea,
   331                                          const nsStyleBorder& aBorderStyle,
   332                                          nsStyleContext* aStyleContext,
   333                                          int aSkipSides = 0);
   336   /**
   337    * Render the outline for an element using css rendering rules
   338    * for borders. aSkipSides is a bitmask of the sides to skip
   339    * when rendering. If 0 then no sides are skipped.
   340    */
   341   static void PaintOutline(nsPresContext* aPresContext,
   342                           nsRenderingContext& aRenderingContext,
   343                           nsIFrame* aForFrame,
   344                           const nsRect& aDirtyRect,
   345                           const nsRect& aBorderArea,
   346                           nsStyleContext* aStyleContext);
   348   /**
   349    * Render keyboard focus on an element.
   350    * |aFocusRect| is the outer rectangle of the focused element.
   351    * Uses a fixed style equivalent to "1px dotted |aColor|".
   352    * Not used for controls, because the native theme may differ.
   353    */
   354   static void PaintFocus(nsPresContext* aPresContext,
   355                          nsRenderingContext& aRenderingContext,
   356                          const nsRect& aFocusRect,
   357                          nscolor aColor);
   359   /**
   360    * Render a gradient for an element.
   361    * aDest is the rect for a single tile of the gradient on the destination.
   362    * aFill is the rect on the destination to be covered by repeated tiling of
   363    * the gradient.
   364    * aSrc is the part of the gradient to be rendered into a tile (aDest), if
   365    * aSrc and aDest are different sizes, the image will be scaled to map aSrc
   366    * onto aDest.
   367    * aIntrinsicSize is the size of the source gradient.
   368    */
   369   static void PaintGradient(nsPresContext* aPresContext,
   370                             nsRenderingContext& aRenderingContext,
   371                             nsStyleGradient* aGradient,
   372                             const nsRect& aDirtyRect,
   373                             const nsRect& aDest,
   374                             const nsRect& aFill,
   375                             const mozilla::CSSIntRect& aSrc,
   376                             const nsSize& aIntrinsiceSize);
   378   /**
   379    * Find the frame whose background style should be used to draw the
   380    * canvas background. aForFrame must be the frame for the root element
   381    * whose background style should be used. This function will return
   382    * aForFrame unless the <body> background should be propagated, in
   383    * which case we return the frame associated with the <body>'s background.
   384    */
   385   static nsIFrame* FindBackgroundStyleFrame(nsIFrame* aForFrame);
   387   /**
   388    * @return true if |aFrame| is a canvas frame, in the CSS sense.
   389    */
   390   static bool IsCanvasFrame(nsIFrame* aFrame);
   392   /**
   393    * Fill in an aBackgroundSC to be used to paint the background
   394    * for an element.  This applies the rules for propagating
   395    * backgrounds between BODY, the root element, and the canvas.
   396    * @return true if there is some meaningful background.
   397    */
   398   static bool FindBackground(nsIFrame* aForFrame,
   399                              nsStyleContext** aBackgroundSC);
   401   /**
   402    * As FindBackground, but the passed-in frame is known to be a root frame
   403    * (returned from nsCSSFrameConstructor::GetRootElementStyleFrame())
   404    * and there is always some meaningful background returned.
   405    */
   406   static nsStyleContext* FindRootFrameBackground(nsIFrame* aForFrame);
   408   /**
   409    * Returns background style information for the canvas.
   410    *
   411    * @param aForFrame
   412    *   the frame used to represent the canvas, in the CSS sense (i.e.
   413    *   nsCSSRendering::IsCanvasFrame(aForFrame) must be true)
   414    * @param aRootElementFrame
   415    *   the frame representing the root element of the document
   416    * @param aBackground
   417    *   contains background style information for the canvas on return
   418    */
   419   static nsStyleContext*
   420   FindCanvasBackground(nsIFrame* aForFrame, nsIFrame* aRootElementFrame)
   421   {
   422     NS_ABORT_IF_FALSE(IsCanvasFrame(aForFrame), "not a canvas frame");
   423     if (aRootElementFrame)
   424       return FindRootFrameBackground(aRootElementFrame);
   426     // This should always give transparent, so we'll fill it in with the
   427     // default color if needed.  This seems to happen a bit while a page is
   428     // being loaded.
   429     return aForFrame->StyleContext();
   430   }
   432   /**
   433    * Find a frame which draws a non-transparent background,
   434    * for various table-related and HR-related backwards-compatibility hacks.
   435    * This function will also stop if it finds themed frame which might draw
   436    * background.
   437    *
   438    * Be very hesitant if you're considering calling this function -- it's
   439    * usually not what you want.
   440    */
   441   static nsIFrame*
   442   FindNonTransparentBackgroundFrame(nsIFrame* aFrame,
   443                                     bool aStartAtParent = false);
   445   /**
   446    * Determine the background color to draw taking into account print settings.
   447    */
   448   static nscolor
   449   DetermineBackgroundColor(nsPresContext* aPresContext,
   450                            nsStyleContext* aStyleContext,
   451                            nsIFrame* aFrame,
   452                            bool& aDrawBackgroundImage,
   453                            bool& aDrawBackgroundColor);
   455   static nsRect
   456   ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
   457                                    nsIFrame* aForFrame,
   458                                    const nsRect& aBorderArea,
   459                                    const nsStyleBackground& aBackground,
   460                                    const nsStyleBackground::Layer& aLayer,
   461                                    nsIFrame** aAttachedToFrame);
   463   static nsBackgroundLayerState
   464   PrepareBackgroundLayer(nsPresContext* aPresContext,
   465                          nsIFrame* aForFrame,
   466                          uint32_t aFlags,
   467                          const nsRect& aBorderArea,
   468                          const nsRect& aBGClipRect,
   469                          const nsStyleBackground& aBackground,
   470                          const nsStyleBackground::Layer& aLayer);
   472   /**
   473    * Render the background for an element using css rendering rules
   474    * for backgrounds.
   475    */
   476   enum {
   477     /**
   478      * When this flag is passed, the element's nsDisplayBorder will be
   479      * painted immediately on top of this background.
   480      */
   481     PAINTBG_WILL_PAINT_BORDER = 0x01,
   482     /**
   483      * When this flag is passed, images are synchronously decoded.
   484      */
   485     PAINTBG_SYNC_DECODE_IMAGES = 0x02,
   486     /**
   487      * When this flag is passed, painting will go to the screen so we can
   488      * take advantage of the fact that it will be clipped to the viewport.
   489      */
   490     PAINTBG_TO_WINDOW = 0x04
   491   };
   492   static void PaintBackground(nsPresContext* aPresContext,
   493                               nsRenderingContext& aRenderingContext,
   494                               nsIFrame* aForFrame,
   495                               const nsRect& aDirtyRect,
   496                               const nsRect& aBorderArea,
   497                               uint32_t aFlags,
   498                               nsRect* aBGClipRect = nullptr,
   499                               int32_t aLayer = -1);
   501   static void PaintBackgroundColor(nsPresContext* aPresContext,
   502                                    nsRenderingContext& aRenderingContext,
   503                                    nsIFrame* aForFrame,
   504                                    const nsRect& aDirtyRect,
   505                                    const nsRect& aBorderArea,
   506                                    uint32_t aFlags);
   508   /**
   509    * Same as |PaintBackground|, except using the provided style structs.
   510    * This short-circuits the code that ensures that the root element's
   511    * background is drawn on the canvas.
   512    * The aLayer parameter allows you to paint a single layer of the background.
   513    * The default value for aLayer, -1, means that all layers will be painted.
   514    * The background color will only be painted if the back-most layer is also
   515    * being painted.
   516    */
   517   static void PaintBackgroundWithSC(nsPresContext* aPresContext,
   518                                     nsRenderingContext& aRenderingContext,
   519                                     nsIFrame* aForFrame,
   520                                     const nsRect& aDirtyRect,
   521                                     const nsRect& aBorderArea,
   522                                     nsStyleContext *aStyleContext,
   523                                     const nsStyleBorder& aBorder,
   524                                     uint32_t aFlags,
   525                                     nsRect* aBGClipRect = nullptr,
   526                                     int32_t aLayer = -1);
   528   static void PaintBackgroundColorWithSC(nsPresContext* aPresContext,
   529                                          nsRenderingContext& aRenderingContext,
   530                                          nsIFrame* aForFrame,
   531                                          const nsRect& aDirtyRect,
   532                                          const nsRect& aBorderArea,
   533                                          nsStyleContext *aStyleContext,
   534                                          const nsStyleBorder& aBorder,
   535                                          uint32_t aFlags);
   536   /**
   537    * Returns the rectangle covered by the given background layer image, taking
   538    * into account background positioning, sizing, and repetition, but not
   539    * clipping.
   540    */
   541   static nsRect GetBackgroundLayerRect(nsPresContext* aPresContext,
   542                                        nsIFrame* aForFrame,
   543                                        const nsRect& aBorderArea,
   544                                        const nsRect& aClipRect,
   545                                        const nsStyleBackground& aBackground,
   546                                        const nsStyleBackground::Layer& aLayer,
   547                                        uint32_t aFlags);
   549   /**
   550    * Checks if image in layer aLayer of aBackground is currently decoded.
   551    */
   552   static bool IsBackgroundImageDecodedForStyleContextAndLayer(
   553     const nsStyleBackground *aBackground, uint32_t aLayer);
   555   /**
   556    * Checks if all images that are part of the background for aFrame are
   557    * currently decoded.
   558    */
   559   static bool AreAllBackgroundImagesDecodedForFrame(nsIFrame* aFrame);
   561   /**
   562    * Called when we start creating a display list. The frame tree will not
   563    * change until a matching EndFrameTreeLocked is called.
   564    */
   565   static void BeginFrameTreesLocked();
   566   /**
   567    * Called when we've finished using a display list. When all
   568    * BeginFrameTreeLocked calls have been balanced by an EndFrameTreeLocked,
   569    * the frame tree may start changing again.
   570    */
   571   static void EndFrameTreesLocked();
   573   // Draw a border segment in the table collapsing border model without
   574   // beveling corners
   575   static void DrawTableBorderSegment(nsRenderingContext& aContext,
   576                                      uint8_t              aBorderStyle,  
   577                                      nscolor              aBorderColor,
   578                                      const nsStyleBackground* aBGColor,
   579                                      const nsRect&        aBorderRect,
   580                                      int32_t              aAppUnitsPerCSSPixel,
   581                                      uint8_t              aStartBevelSide = 0,
   582                                      nscoord              aStartBevelOffset = 0,
   583                                      uint8_t              aEndBevelSide = 0,
   584                                      nscoord              aEndBevelOffset = 0);
   586   /**
   587    * Function for painting the decoration lines for the text.
   588    * NOTE: aPt, aLineSize, aAscent and aOffset are non-rounded device pixels,
   589    *       not app units.
   590    *   input:
   591    *     @param aFrame            the frame which needs the decoration line
   592    *     @param aGfxContext
   593    *     @param aDirtyRect        no need to paint outside this rect
   594    *     @param aColor            the color of the decoration line
   595    *     @param aPt               the top/left edge of the text
   596    *     @param aXInFrame         the distance between aPt.x and left edge of
   597    *                              aFrame.  If the decoration line is for shadow,
   598    *                              set the distance between the left edge of
   599    *                              the aFrame and the position of the text as
   600    *                              positioned without offset of the shadow.
   601    *     @param aLineSize         the width and the height of the decoration
   602    *                              line
   603    *     @param aAscent           the ascent of the text
   604    *     @param aOffset           the offset of the decoration line from
   605    *                              the baseline of the text (if the value is
   606    *                              positive, the line is lifted up)
   607    *     @param aDecoration       which line will be painted. The value can be
   608    *                              NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
   609    *                              NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
   610    *                              NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
   611    *     @param aStyle            the style of the decoration line such as
   612    *                              NS_STYLE_TEXT_DECORATION_STYLE_*.
   613    *     @param aDescentLimit     If aDescentLimit is zero or larger and the
   614    *                              underline overflows from the descent space,
   615    *                              the underline should be lifted up as far as
   616    *                              possible.  Note that this does not mean the
   617    *                              underline never overflows from this
   618    *                              limitation.  Because if the underline is
   619    *                              positioned to the baseline or upper, it causes
   620    *                              unreadability.  Note that if this is zero
   621    *                              or larger, the underline rect may be shrunken
   622    *                              if it's possible.  Therefore, this value is
   623    *                              used for strikeout line and overline too.
   624    */
   625   static void PaintDecorationLine(nsIFrame* aFrame,
   626                                   gfxContext* aGfxContext,
   627                                   const gfxRect& aDirtyRect,
   628                                   const nscolor aColor,
   629                                   const gfxPoint& aPt,
   630                                   const gfxFloat aXInFrame,
   631                                   const gfxSize& aLineSize,
   632                                   const gfxFloat aAscent,
   633                                   const gfxFloat aOffset,
   634                                   const uint8_t aDecoration,
   635                                   const uint8_t aStyle,
   636                                   const gfxFloat aDescentLimit = -1.0);
   638   /**
   639    * Adds a path corresponding to the outline of the decoration line to
   640    * the specified context.  Arguments have the same meaning as for
   641    * PaintDecorationLine.  Currently this only works for solid
   642    * decorations; for other decoration styles, an empty path is added
   643    * to the context.
   644    */
   645   static void DecorationLineToPath(nsIFrame* aFrame,
   646                                    gfxContext* aGfxContext,
   647                                    const gfxRect& aDirtyRect,
   648                                    const nscolor aColor,
   649                                    const gfxPoint& aPt,
   650                                    const gfxFloat aXInFrame,
   651                                    const gfxSize& aLineSize,
   652                                    const gfxFloat aAscent,
   653                                    const gfxFloat aOffset,
   654                                    const uint8_t aDecoration,
   655                                    const uint8_t aStyle,
   656                                    const gfxFloat aDescentLimit = -1.0);
   658   /**
   659    * Function for getting the decoration line rect for the text.
   660    * NOTE: aLineSize, aAscent and aOffset are non-rounded device pixels,
   661    *       not app units.
   662    *   input:
   663    *     @param aPresContext
   664    *     @param aLineSize         the width and the height of the decoration
   665    *                              line
   666    *     @param aAscent           the ascent of the text
   667    *     @param aOffset           the offset of the decoration line from
   668    *                              the baseline of the text (if the value is
   669    *                              positive, the line is lifted up)
   670    *     @param aDecoration       which line will be painted. The value can be
   671    *                              NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
   672    *                              NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
   673    *                              NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
   674    *     @param aStyle            the style of the decoration line such as
   675    *                              NS_STYLE_TEXT_DECORATION_STYLE_*.
   676    *     @param aDescentLimit     If aDescentLimit is zero or larger and the
   677    *                              underline overflows from the descent space,
   678    *                              the underline should be lifted up as far as
   679    *                              possible.  Note that this does not mean the
   680    *                              underline never overflows from this
   681    *                              limitation.  Because if the underline is
   682    *                              positioned to the baseline or upper, it causes
   683    *                              unreadability.  Note that if this is zero
   684    *                              or larger, the underline rect may be shrunken
   685    *                              if it's possible.  Therefore, this value is
   686    *                              used for strikeout line and overline too.
   687    *   output:
   688    *     @return                  the decoration line rect for the input,
   689    *                              the each values are app units.
   690    */
   691   static nsRect GetTextDecorationRect(nsPresContext* aPresContext,
   692                                       const gfxSize& aLineSize,
   693                                       const gfxFloat aAscent,
   694                                       const gfxFloat aOffset,
   695                                       const uint8_t aDecoration,
   696                                       const uint8_t aStyle,
   697                                       const gfxFloat aDescentLimit = -1.0);
   699   static gfxContext::GraphicsOperator GetGFXBlendMode(uint8_t mBlendMode) {
   700     switch (mBlendMode) {
   701       case NS_STYLE_BLEND_NORMAL:      return gfxContext::OPERATOR_OVER;
   702       case NS_STYLE_BLEND_MULTIPLY:    return gfxContext::OPERATOR_MULTIPLY;
   703       case NS_STYLE_BLEND_SCREEN:      return gfxContext::OPERATOR_SCREEN;
   704       case NS_STYLE_BLEND_OVERLAY:     return gfxContext::OPERATOR_OVERLAY;
   705       case NS_STYLE_BLEND_DARKEN:      return gfxContext::OPERATOR_DARKEN;
   706       case NS_STYLE_BLEND_LIGHTEN:     return gfxContext::OPERATOR_LIGHTEN;
   707       case NS_STYLE_BLEND_COLOR_DODGE: return gfxContext::OPERATOR_COLOR_DODGE;
   708       case NS_STYLE_BLEND_COLOR_BURN:  return gfxContext::OPERATOR_COLOR_BURN;
   709       case NS_STYLE_BLEND_HARD_LIGHT:  return gfxContext::OPERATOR_HARD_LIGHT;
   710       case NS_STYLE_BLEND_SOFT_LIGHT:  return gfxContext::OPERATOR_SOFT_LIGHT;
   711       case NS_STYLE_BLEND_DIFFERENCE:  return gfxContext::OPERATOR_DIFFERENCE;
   712       case NS_STYLE_BLEND_EXCLUSION:   return gfxContext::OPERATOR_EXCLUSION;
   713       case NS_STYLE_BLEND_HUE:         return gfxContext::OPERATOR_HUE;
   714       case NS_STYLE_BLEND_SATURATION:  return gfxContext::OPERATOR_SATURATION;
   715       case NS_STYLE_BLEND_COLOR:       return gfxContext::OPERATOR_COLOR;
   716       case NS_STYLE_BLEND_LUMINOSITY:  return gfxContext::OPERATOR_LUMINOSITY;
   717       default:                         MOZ_ASSERT(false); return gfxContext::OPERATOR_OVER;
   718     }
   720     return gfxContext::OPERATOR_OVER;
   721   }
   723 protected:
   724   static gfxRect GetTextDecorationRectInternal(const gfxPoint& aPt,
   725                                                const gfxSize& aLineSize,
   726                                                const gfxFloat aAscent,
   727                                                const gfxFloat aOffset,
   728                                                const uint8_t aDecoration,
   729                                                const uint8_t aStyle,
   730                                                const gfxFloat aDscentLimit);
   732   /**
   733    * Returns inflated rect for painting a decoration line.
   734    * Complex style decoration lines should be painted from leftmost of nearest
   735    * ancestor block box because that makes better look of connection of lines
   736    * for different nodes.  ExpandPaintingRectForDecorationLine() returns
   737    * a rect for actual painting rect for the clipped rect.
   738    *
   739    * input:
   740    *     @param aFrame            the frame which needs the decoration line.
   741    *     @param aStyle            the style of the complex decoration line
   742    *                              NS_STYLE_TEXT_DECORATION_STYLE_DOTTED or
   743    *                              NS_STYLE_TEXT_DECORATION_STYLE_DASHED or
   744    *                              NS_STYLE_TEXT_DECORATION_STYLE_WAVY.
   745    *     @param aClippedRect      the clipped rect for the decoration line.
   746    *                              in other words, visible area of the line.
   747    *     @param aXInFrame         the distance between left edge of aFrame and
   748    *                              aClippedRect.pos.x.
   749    *     @param aCycleLength      the width of one cycle of the line style.
   750    */
   751   static gfxRect ExpandPaintingRectForDecorationLine(
   752                    nsIFrame* aFrame,
   753                    const uint8_t aStyle,
   754                    const gfxRect &aClippedRect,
   755                    const gfxFloat aXInFrame,
   756                    const gfxFloat aCycleLength);
   757 };
   759 /*
   760  * nsContextBoxBlur
   761  * Creates an 8-bit alpha channel context for callers to draw in, blurs the
   762  * contents of that context and applies it as a 1-color mask on a
   763  * different existing context. Uses gfxAlphaBoxBlur as its back end.
   764  *
   765  * You must call Init() first to create a suitable temporary surface to draw
   766  * on.  You must then draw any desired content onto the given context, then
   767  * call DoPaint() to apply the blurred content as a single-color mask. You
   768  * can only call Init() once, so objects cannot be reused.
   769  *
   770  * This is very useful for creating drop shadows or silhouettes.
   771  */
   772 class nsContextBoxBlur {
   773 public:
   774   enum {
   775     FORCE_MASK = 0x01
   776   };
   777   /**
   778    * Prepares a gfxContext to draw on. Do not call this twice; if you want
   779    * to get the gfxContext again use GetContext().
   780    *
   781    * @param aRect                The coordinates of the surface to create.
   782    *                             All coordinates must be in app units.
   783    *                             This must not include the blur radius, pass
   784    *                             it as the second parameter and everything
   785    *                             is taken care of.
   786    *
   787    * @param aBlurRadius          The blur radius in app units.
   788    *
   789    * @param aAppUnitsPerDevPixel The number of app units in a device pixel,
   790    *                             for conversion.  Most of the time you'll
   791    *                             pass this from the current PresContext if
   792    *                             available.
   793    *
   794    * @param aDestinationCtx      The graphics context to apply the blurred
   795    *                             mask to when you call DoPaint(). Make sure
   796    *                             it is not destroyed before you call
   797    *                             DoPaint(). To set the color of the
   798    *                             resulting blurred graphic mask, you must
   799    *                             set the color on this context before
   800    *                             calling Init().
   801    *
   802    * @param aDirtyRect           The absolute dirty rect in app units. Used to
   803    *                             optimize the temporary surface size and speed up blur.
   804    *
   805    * @param aSkipRect            An area in device pixels (NOT app units!) to avoid
   806    *                             blurring over, to prevent unnecessary work.
   807    *                             
   808    * @param aFlags               FORCE_MASK to ensure that the content drawn to the
   809    *                             returned gfxContext is used as a mask, and not
   810    *                             drawn directly to aDestinationCtx.
   811    *
   812    * @return            A blank 8-bit alpha-channel-only graphics context to
   813    *                    draw on, or null on error. Must not be freed. The
   814    *                    context has a device offset applied to it given by
   815    *                    aRect. This means you can use coordinates as if it
   816    *                    were at the desired position at aRect and you don't
   817    *                    need to worry about translating any coordinates to
   818    *                    draw on this temporary surface.
   819    *
   820    * If aBlurRadius is 0, the returned context is aDestinationCtx and
   821    * DoPaint() does nothing, because no blurring is required. Therefore, you
   822    * should prepare the destination context as if you were going to draw
   823    * directly on it instead of any temporary surface created in this class.
   824    */
   825   gfxContext* Init(const nsRect& aRect, nscoord aSpreadRadius,
   826                    nscoord aBlurRadius,
   827                    int32_t aAppUnitsPerDevPixel, gfxContext* aDestinationCtx,
   828                    const nsRect& aDirtyRect, const gfxRect* aSkipRect,
   829                    uint32_t aFlags = 0);
   831   /**
   832    * Does the actual blurring and mask applying. Users of this object *must*
   833    * have called Init() first, then have drawn whatever they want to be
   834    * blurred onto the internal gfxContext before calling this.
   835    */
   836   void DoPaint();
   838   /**
   839    * Gets the internal gfxContext at any time. Must not be freed. Avoid
   840    * calling this before calling Init() since the context would not be
   841    * constructed at that point.
   842    */
   843   gfxContext* GetContext();
   846   /**
   847    * Get the margin associated with the given blur radius, i.e., the
   848    * additional area that might be painted as a result of it.  (The
   849    * margin for a spread radius is itself, on all sides.)
   850    */
   851   static nsMargin GetBlurRadiusMargin(nscoord aBlurRadius,
   852                                       int32_t aAppUnitsPerDevPixel);
   854   /**
   855    * Blurs a coloured rectangle onto aDestinationCtx. This is equivalent
   856    * to calling Init(), drawing a rectangle onto the returned surface
   857    * and then calling DoPaint, but may let us optimize better in the
   858    * backend.
   859    *
   860    * @param aDestinationCtx      The destination to blur to.
   861    * @param aRect                The rectangle to blur in app units.
   862    * @param aAppUnitsPerDevPixel The number of app units in a device pixel,
   863    *                             for conversion.  Most of the time you'll
   864    *                             pass this from the current PresContext if
   865    *                             available.
   866    * @param aCornerRadii         Corner radii for aRect, if it is a rounded
   867    *                             rectangle.
   868    * @param aBlurRadius          The blur radius in app units.
   869    * @param aShadowColor         The color to draw the blurred shadow.
   870    * @param aDirtyRect           The absolute dirty rect in app units. Used to
   871    *                             optimize the temporary surface size and speed up blur.
   872    * @param aSkipRect            An area in device pixels (NOT app units!) to avoid
   873    *                             blurring over, to prevent unnecessary work.
   874    */
   875   static void BlurRectangle(gfxContext* aDestinationCtx,
   876                             const nsRect& aRect,
   877                             int32_t aAppUnitsPerDevPixel,
   878                             gfxCornerSizes* aCornerRadii,
   879                             nscoord aBlurRadius,
   880                             const gfxRGBA& aShadowColor,
   881                             const nsRect& aDirtyRect,
   882                             const gfxRect& aSkipRect);
   884 protected:
   885   gfxAlphaBoxBlur blur;
   886   nsRefPtr<gfxContext> mContext;
   887   gfxContext* mDestinationCtx;
   889   /* This is true if the blur already has it's content transformed
   890    * by mDestinationCtx's transform */
   891   bool mPreTransformed;
   893 };
   895 #endif /* nsCSSRendering_h___ */

mercurial