DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (409f3966645a)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef nsCSSRenderingGradients_h__
#define nsCSSRenderingGradients_h__

#include "nsLayoutUtils.h"
#include "nsStyleStruct.h"
#include "Units.h"
#include "mozilla/Maybe.h"
#include "mozilla/gfx/2D.h"

namespace mozilla {

namespace layers {
class StackingContextHelper;
} // namespace layers

namespace wr {
class DisplayListBuilder;
} // namespace wr

// A resolved color stop, with a specific position along the gradient line and
// a color.
struct ColorStop
{
  ColorStop()
    : mPosition(0)
    , mIsMidpoint(false)
  {
  }
  ColorStop(double aPosition, bool aIsMidPoint, const gfx::Color& aColor)
    : mPosition(aPosition)
    , mIsMidpoint(aIsMidPoint)
    , mColor(aColor)
  {
  }
  double mPosition; // along the gradient line; 0=start, 1=end
  bool mIsMidpoint;
  gfx::Color mColor;
};

class nsCSSGradientRenderer final
{
public:
  /**
   * Prepare a nsCSSGradientRenderer for a gradient for an element.
   * aIntrinsicSize - the size of the source gradient.
   */
  static nsCSSGradientRenderer Create(nsPresContext* aPresContext,
                                      ComputedStyle* aComputedStyle,
                                      nsStyleGradient* aGradient,
                                      const nsSize& aIntrinsiceSize);

  /**
   * Draw the gradient to aContext
   * aDest - where the first tile of gradient is
   * aFill - the area to be filled with tiles of aDest
   * aSrc - the area of the gradient that will fill aDest
   * aRepeatSize - the distance from the origin of a tile
   *               to the next origin of a tile
   * aDirtyRect - pixels outside of this area may be skipped
   */
  void Paint(gfxContext& aContext,
             const nsRect& aDest,
             const nsRect& aFill,
             const nsSize& aRepeatSize,
             const mozilla::CSSIntRect& aSrc,
             const nsRect& aDirtyRect,
             float aOpacity = 1.0);

  /**
   * Collect the gradient parameters
   */
  void BuildWebRenderParameters(float aOpacity,
                                wr::ExtendMode& aMode,
                                nsTArray<wr::GradientStop>& aStops,
                                LayoutDevicePoint& aLineStart,
                                LayoutDevicePoint& aLineEnd,
                                LayoutDeviceSize& aGradientRadius);

  /**
   * Build display items for the gradient
   * aLayer - the layer to make this display item relative to
   * aDest - where the first tile of gradient is
   * aFill - the area to be filled with tiles of aDest
   * aRepeatSize - the distance from the origin of a tile
   *               to the next origin of a tile
   * aSrc - the area of the gradient that will fill aDest
   */
  void BuildWebRenderDisplayItems(wr::DisplayListBuilder& aBuilder,
                                  const layers::StackingContextHelper& aSc,
                                  const nsRect& aDest,
                                  const nsRect& aFill,
                                  const nsSize& aRepeatSize,
                                  const mozilla::CSSIntRect& aSrc,
                                  bool aIsBackfaceVisible,
                                  float aOpacity = 1.0);

private:
  nsCSSGradientRenderer()
    : mPresContext(nullptr)
    , mGradient(nullptr)
    , mRadiusX(0.0)
    , mRadiusY(0.0)
  {
  }

  /**
   * Attempts to paint the tiles for a gradient by painting it once to an
   * offscreen surface and then painting that offscreen surface with
   * ExtendMode::Repeat to cover all tiles.
   *
   * Returns false if the optimization wasn't able to be used, in which case
   * a fallback should be used.
   */
  bool TryPaintTilesWithExtendMode(gfxContext& aContext,
                                   gfxPattern* aGradientPattern,
                                   nscoord aXStart,
                                   nscoord aYStart,
                                   const gfxRect& aDirtyAreaToFill,
                                   const nsRect& aDest,
                                   const nsSize& aRepeatSize,
                                   bool aForceRepeatToCoverTiles);

  nsPresContext* mPresContext;
  nsStyleGradient* mGradient;
  nsTArray<ColorStop> mStops;
  gfxPoint mLineStart, mLineEnd;
  double mRadiusX, mRadiusY;
};

} // namespace mozilla

#endif /* nsCSSRenderingGradients_h__ */