Back to index

lightning-sunbird  0.9+nobinonly
Functions
nsSVGCairoGradient.cpp File Reference
#include <math.h>
#include "nsCOMPtr.h"
#include "nsIDOMSVGMatrix.h"
#include "nsIDOMSVGGradientElement.h"
#include "nsISVGPathGeometrySource.h"
#include "nsSVGCairoGradient.h"

Go to the source code of this file.

Functions

static cairo_matrix_t SVGToMatrix (nsIDOMSVGMatrix *ctm)
static void CairoSetStops (cairo_pattern_t *aPattern, nsISVGGradient *aGrad, float aOpacity)
static cairo_pattern_t * CairoLinearGradient (cairo_t *ctx, nsISVGGradient *aGrad)
static cairo_pattern_t * CairoRadialGradient (cairo_t *ctx, nsISVGGradient *aGrad)
cairo_pattern_t * CairoGradient (cairo_t *ctx, nsISVGGradient *aGrad, nsISVGGeometrySource *aSource, float aOpacity)

Function Documentation

cairo_pattern_t* CairoGradient ( cairo_t *  ctx,
nsISVGGradient aGrad,
nsISVGGeometrySource aSource,
float  aOpacity 
)

Definition at line 151 of file nsSVGCairoGradient.cpp.

{
  NS_ASSERTION(aGrad, "Called CairoGradient without a gradient!");
  if (!aGrad)
    return nsnull;

  // Get the transform list (if there is one)
  nsCOMPtr<nsIDOMSVGMatrix> svgMatrix;
  aGrad->GetGradientTransform(getter_AddRefs(svgMatrix), aSource);
  NS_ASSERTION(svgMatrix, "CairoGradient: GetGradientTransform returns null");

  cairo_matrix_t patternMatrix = SVGToMatrix(svgMatrix);
  if (cairo_matrix_invert(&patternMatrix)) {
    return nsnull;
  }

  cairo_pattern_t *gradient;

  // Linear or Radial?
  PRUint32 type;
  aGrad->GetGradientType(&type);
  if (type == nsISVGGradient::SVG_LINEAR_GRADIENT)
    gradient = CairoLinearGradient(ctx, aGrad);
  else if (type == nsISVGGradient::SVG_RADIAL_GRADIENT)
    gradient = CairoRadialGradient(ctx, aGrad);
  else 
    return nsnull; // Shouldn't happen

  PRUint16 aSpread;
  aGrad->GetSpreadMethod(&aSpread);
  // We don't call cairo_pattern_set_extend for SVG_SPREADMETHOD_PAD because
  // pad is cairo's default, and the explicit argument used for pad changed
  // from CAIRO_EXTEND_NONE to CAIRO_EXTEND_PAD between cairo 1.0 and 1.2. See
  // bug 358930.
  if (aSpread == nsIDOMSVGGradientElement::SVG_SPREADMETHOD_REFLECT)
    cairo_pattern_set_extend(gradient, CAIRO_EXTEND_REFLECT);
  else if (aSpread == nsIDOMSVGGradientElement::SVG_SPREADMETHOD_REPEAT)
    cairo_pattern_set_extend(gradient, CAIRO_EXTEND_REPEAT);
  
  cairo_pattern_set_matrix(gradient, &patternMatrix);

  CairoSetStops(gradient, aGrad, aOpacity);

  return gradient;
}

Here is the call graph for this function:

static cairo_pattern_t* CairoLinearGradient ( cairo_t *  ctx,
nsISVGGradient aGrad 
) [static]

Definition at line 96 of file nsSVGCairoGradient.cpp.

{
  float fX1, fY1, fX2, fY2;
    
  nsCOMPtr<nsISVGLinearGradient>aLgrad = do_QueryInterface(aGrad);
  NS_ASSERTION(aLgrad, "error gradient did not provide a Linear Gradient interface");
  
  aLgrad->GetX1(&fX1);
  aLgrad->GetX2(&fX2);
  aLgrad->GetY1(&fY1);
  aLgrad->GetY2(&fY2);
  
  return cairo_pattern_create_linear(fX1, fY1, fX2, fY2);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static cairo_pattern_t* CairoRadialGradient ( cairo_t *  ctx,
nsISVGGradient aGrad 
) [static]

Definition at line 113 of file nsSVGCairoGradient.cpp.

{
  float fCx, fCy, fR, fFx, fFy;

  // Get the Radial Gradient interface
  nsCOMPtr<nsISVGRadialGradient>aRgrad = do_QueryInterface(aGrad);
  NS_ASSERTION(aRgrad, "error gradient did not provide a Linear Gradient interface");

  aRgrad->GetCx(&fCx);
  aRgrad->GetCy(&fCy);
  aRgrad->GetR(&fR);
  aRgrad->GetFx(&fFx);
  aRgrad->GetFy(&fFy);

  if (fFx != fCx || fFy != fCy) {
    // The focal point (fFx and fFy) must be clamped to be *inside* - not on -
    // the circumference of the gradient or we'll get rendering anomalies. We
    // calculate the distance from the focal point to the gradient center and
    // make sure it is *less* than the gradient radius. 0.999 is used as the
    // factor of the radius because it's close enough to 1 that we won't get a
    // fringe at the edge of the gradient if we clamp, but not so close to 1
    // that rounding error will give us the same results as using fR itself.
    double dMax = 0.999 * fR;
    float dx = fFx - fCx;
    float dy = fFy - fCy;
    double d = sqrt((dx * dx) + (dy * dy));
    if (d > dMax) {
      double angle = atan2(dy, dx);
      fFx = (float)(dMax * cos(angle)) + fCx;
      fFy = (float)(dMax * sin(angle)) + fCy;
    }
  }

  return cairo_pattern_create_radial(fFx, fFy, 0, fCx, fCy, fR);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void CairoSetStops ( cairo_pattern_t *  aPattern,
nsISVGGradient aGrad,
float  aOpacity 
) [static]

Definition at line 66 of file nsSVGCairoGradient.cpp.

{
  PRUint32 nStops;
  float lastOffset = 0.0f;

  aGrad->GetStopCount(&nStops);
  for (PRUint32 i = 0; i < nStops; i++) {
    nscolor rgba;
    float offset;
    float opacity;

    aGrad->GetStopOffset(i, &offset);
    aGrad->GetStopColor(i, &rgba);
    aGrad->GetStopOpacity(i, &opacity);

    if (offset < lastOffset)
      offset = lastOffset;
    else
      lastOffset = offset;

    cairo_pattern_add_color_stop_rgba(aPattern, offset,
                                      NS_GET_R(rgba)/255.0,
                                      NS_GET_G(rgba)/255.0,
                                      NS_GET_B(rgba)/255.0,
                                      opacity * aOpacity);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static cairo_matrix_t SVGToMatrix ( nsIDOMSVGMatrix ctm) [static]

Definition at line 51 of file nsSVGCairoGradient.cpp.

{
  float A, B, C, D, E, F;
  ctm->GetA(&A);
  ctm->GetB(&B);
  ctm->GetC(&C);
  ctm->GetD(&D);
  ctm->GetE(&E);
  ctm->GetF(&F);
  cairo_matrix_t matrix = { A, B, C, D, E, F };
  return matrix;
}

Here is the call graph for this function:

Here is the caller graph for this function: