コード例 #1
0
ファイル: nsSVGPatternFrame.cpp プロジェクト: ahadzi/celtx
nsresult
nsSVGPatternFrame::ConstructCTM(nsIDOMSVGMatrix **aCTM,
                                nsIDOMSVGRect *callerBBox,
                                nsIDOMSVGMatrix *callerCTM)
{
  nsCOMPtr<nsIDOMSVGMatrix> tCTM, tempTM;

  // Begin by handling the objectBoundingBox conversion since
  // this must be handled in the CTM
  PRUint16 type = GetPatternContentUnits();

  if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
    // Use the bounding box
    float width, height;
    callerBBox->GetWidth(&width);
    callerBBox->GetHeight(&height);
    NS_NewSVGMatrix(getter_AddRefs(tCTM), width, 0.0f, 0.0f, 
                    height, 0.0f, 0.0f);
  } else {
    float scale = nsSVGUtils::MaxExpansion(callerCTM);
    NS_NewSVGMatrix(getter_AddRefs(tCTM), scale, 0, 0, scale, 0, 0);
  }

  // Do we have a viewbox?
  nsCOMPtr<nsIDOMSVGRect> viewRect;
  GetViewBox(getter_AddRefs(viewRect));

  // See if we really have something
  float viewBoxX, viewBoxY, viewBoxHeight, viewBoxWidth;
  viewRect->GetX(&viewBoxX);
  viewRect->GetY(&viewBoxY);
  viewRect->GetHeight(&viewBoxHeight);
  viewRect->GetWidth(&viewBoxWidth);
  if (viewBoxHeight > 0.0f && viewBoxWidth > 0.0f) {

    float viewportWidth = GetLengthValue(GetWidth());
    float viewportHeight = GetLengthValue(GetHeight());
    float refX = GetLengthValue(GetX());
    float refY = GetLengthValue(GetY());

    nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> par;
    GetPreserveAspectRatio(getter_AddRefs(par));

    tempTM = nsSVGUtils::GetViewBoxTransform(viewportWidth, viewportHeight,
                                             viewBoxX + refX, viewBoxY + refY,
                                             viewBoxWidth, viewBoxHeight,
                                             par,
                                             PR_TRUE);

  } else {
    // No viewBox, construct from the (modified) parent matrix
    NS_NewSVGMatrix(getter_AddRefs(tempTM));
  }
  tCTM->Multiply(tempTM, aCTM);
  return NS_OK;
}
コード例 #2
0
gfxMatrix
nsSVGMarkerElement::GetViewBoxTransform()
{
  if (!mViewBoxToViewportTransform) {
    float viewportWidth =
      mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx);
    float viewportHeight = 
      mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx);
   
    const nsSVGViewBoxRect& viewbox = mViewBox.GetAnimValue(); 

    if (viewbox.width <= 0.0f || viewbox.height <= 0.0f) {
      return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // invalid - don't paint element
    }

    float refX = mLengthAttributes[REFX].GetAnimValue(mCoordCtx);
    float refY = mLengthAttributes[REFY].GetAnimValue(mCoordCtx);

    gfxMatrix viewBoxTM =
      nsSVGUtils::GetViewBoxTransform(this,
                                      viewportWidth, viewportHeight,
                                      viewbox.x, viewbox.y,
                                      viewbox.width, viewbox.height,
                                      mPreserveAspectRatio);

    gfxPoint ref = viewBoxTM.Transform(gfxPoint(refX, refY));

    gfxMatrix TM = viewBoxTM * gfxMatrix().Translate(gfxPoint(-ref.x, -ref.y));

    mViewBoxToViewportTransform = NS_NewSVGMatrix(TM);
  }

  return nsSVGUtils::ConvertSVGMatrixToThebes(mViewBoxToViewportTransform);
}
コード例 #3
0
gfxMatrix
nsSVGInnerSVGFrame::GetCanvasTM()
{
  if (!mCanvasTM) {
    NS_ASSERTION(mParent, "null parent");

    nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
    nsSVGSVGElement *content = static_cast<nsSVGSVGElement*>(mContent);

    gfxMatrix tm = content->PrependLocalTransformTo(parent->GetCanvasTM());

    mCanvasTM = NS_NewSVGMatrix(tm);
  }
  return nsSVGUtils::ConvertSVGMatrixToThebes(mCanvasTM);
}
コード例 #4
0
nsresult
nsSVGTransformSMILAttr::GetSVGTransformFromSMILValue(
    const nsSVGSMILTransform& aSMILTransform,
    nsIDOMSVGTransform* aSVGTransform)
{
  switch (aSMILTransform.mTransformType)
  {
    case nsSVGSMILTransform::TRANSFORM_TRANSLATE:
      return aSVGTransform->SetTranslate(aSMILTransform.mParams[0],
                                         aSMILTransform.mParams[1]);

    case nsSVGSMILTransform::TRANSFORM_SCALE:
      return aSVGTransform->SetScale(aSMILTransform.mParams[0],
                                   aSMILTransform.mParams[1]);

    case nsSVGSMILTransform::TRANSFORM_ROTATE:
      return aSVGTransform->SetRotate(aSMILTransform.mParams[0],
                                      aSMILTransform.mParams[1],
                                      aSMILTransform.mParams[2]);

    case nsSVGSMILTransform::TRANSFORM_SKEWX:
      return aSVGTransform->SetSkewX(aSMILTransform.mParams[0]);

    case nsSVGSMILTransform::TRANSFORM_SKEWY:
      return aSVGTransform->SetSkewY(aSMILTransform.mParams[0]);

    case nsSVGSMILTransform::TRANSFORM_MATRIX:
    {
      nsCOMPtr<nsIDOMSVGMatrix> svgMatrix;
      nsresult rv =
        NS_NewSVGMatrix(getter_AddRefs(svgMatrix),
                        aSMILTransform.mParams[0],
                        aSMILTransform.mParams[1],
                        aSMILTransform.mParams[2],
                        aSMILTransform.mParams[3],
                        aSMILTransform.mParams[4],
                        aSMILTransform.mParams[5]);
      NS_ENSURE_SUCCESS(rv, rv);
      NS_ABORT_IF_FALSE(svgMatrix,
                        "NS_NewSVGMatrix succeeded, so it should have "
                        "given us a non-null result");
      return aSVGTransform->SetMatrix(svgMatrix);
    }
    default:
      NS_WARNING("Unexpected transform type");
      return NS_ERROR_FAILURE;
  }
}
コード例 #5
0
ファイル: nsSVGPatternFrame.cpp プロジェクト: ahadzi/celtx
// If our GetCanvasTM is getting called, we
// need to return *our current* transformation
// matrix, which depends on our units parameters
// and X, Y, Width, and Height
already_AddRefed<nsIDOMSVGMatrix> 
nsSVGPatternFrame::GetCanvasTM()
{
  nsIDOMSVGMatrix *rCTM;
  
  if (mCTM) {
    rCTM = mCTM;
    NS_IF_ADDREF(rCTM);
  } else {
    // Do we know our rendering parent?
    if (mSource) {
      // Yes, use it!
      mSource->GetCanvasTM(&rCTM);
    } else {
      // No, return an identity
      // We get here when geometry in the <pattern> container is updated
      NS_NewSVGMatrix(&rCTM);
    }
  }
  return rCTM;  
}
コード例 #6
0
already_AddRefed<nsIDOMSVGMatrix>
nsSVGTransformList::GetConsolidationMatrix(nsIDOMSVGTransformList *transforms)
{
  PRUint32 count;
  transforms->GetNumberOfItems(&count);

  if (!count)
    return nsnull;

  nsCOMPtr<nsIDOMSVGTransform> transform;
  nsCOMPtr<nsIDOMSVGMatrix> conmatrix;

  // single transform common case - shortcut
  if (count == 1) {
    transforms->GetItem(0, getter_AddRefs(transform));
    transform->GetMatrix(getter_AddRefs(conmatrix));
  } else {
    nsresult rv = NS_NewSVGMatrix(getter_AddRefs(conmatrix));
    NS_ENSURE_SUCCESS(rv, nsnull);
    
    nsCOMPtr<nsIDOMSVGMatrix> temp1, temp2;
    
    for (PRUint32 i = 0; i < count; ++i) {
      transforms->GetItem(i, getter_AddRefs(transform));
      transform->GetMatrix(getter_AddRefs(temp1));
      conmatrix->Multiply(temp1, getter_AddRefs(temp2));
      if (!temp2)
        return nsnull;
      conmatrix = temp2;
    }
  }

  nsIDOMSVGMatrix *_retval = nsnull;
  conmatrix.swap(_retval);
  return _retval;
}
コード例 #7
0
already_AddRefed<gfxPattern>
nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
                                 nsIFrame* aParent,
                                 const gfxMatrix &aMatrix,
                                 float aOpacity)
{
  // If the flag is set when we get here, it means this mask frame
  // has already been used painting the current mask, and the document
  // has a mask reference loop.
  if (mInUse) {
    NS_WARNING("Mask loop detected!");
    return nsnull;
  }
  AutoMaskReferencer maskRef(this);

  nsSVGMaskElement *mask = static_cast<nsSVGMaskElement*>(mContent);

  PRUint16 units =
    mask->mEnumAttributes[nsSVGMaskElement::MASKUNITS].GetAnimValue();
  gfxRect bbox;
  if (units == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
    bbox = nsSVGUtils::GetBBox(aParent);
  }

  gfxRect maskArea = nsSVGUtils::GetRelativeRect(units,
    &mask->mLengthAttributes[nsSVGMaskElement::X], bbox, aParent);
  maskArea.RoundOut();

  gfxContext *gfx = aContext->GetGfxContext();

  gfx->Save();
  nsSVGUtils::SetClipRect(gfx, aMatrix, maskArea);
  gfxRect clipExtents = gfx->GetClipExtents();
  gfx->Restore();

#ifdef DEBUG_tor
  fprintf(stderr, "clip extent: %f,%f %fx%f\n",
          clipExtents.X(), clipExtents.Y(),
          clipExtents.Width(), clipExtents.Height());
#endif

  PRBool resultOverflows;
  gfxIntSize surfaceSize =
    nsSVGUtils::ConvertToSurfaceSize(gfxSize(clipExtents.Width(),
                                             clipExtents.Height()),
                                     &resultOverflows);

  // 0 disables mask, < 0 is an error
  if (surfaceSize.width <= 0 || surfaceSize.height <= 0)
    return nsnull;

  if (resultOverflows)
    return nsnull;

  nsRefPtr<gfxImageSurface> image =
    new gfxImageSurface(surfaceSize, gfxASurface::ImageFormatARGB32);
  if (!image || image->CairoStatus())
    return nsnull;
  image->SetDeviceOffset(-clipExtents.TopLeft());

  nsSVGRenderState tmpState(image);

  mMaskParent = aParent;
  mMaskParentMatrix = NS_NewSVGMatrix(aMatrix);

  for (nsIFrame* kid = mFrames.FirstChild(); kid;
       kid = kid->GetNextSibling()) {
    // The CTM of each frame referencing us can be different
    nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
    if (SVGFrame) {
      SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
                                 nsISVGChildFrame::TRANSFORM_CHANGED);
    }
    nsSVGUtils::PaintFrameWithEffects(&tmpState, nsnull, kid);
  }

  PRUint8 *data   = image->Data();
  PRInt32  stride = image->Stride();

  nsIntRect rect(0, 0, surfaceSize.width, surfaceSize.height);
  nsSVGUtils::UnPremultiplyImageDataAlpha(data, stride, rect);
  nsSVGUtils::ConvertImageDataToLinearRGB(data, stride, rect);

  for (PRInt32 y = 0; y < surfaceSize.height; y++)
    for (PRInt32 x = 0; x < surfaceSize.width; x++) {
      PRUint8 *pixel = data + stride * y + 4 * x;

      /* linearRGB -> intensity */
      PRUint8 alpha =
        static_cast<PRUint8>
                   ((pixel[GFX_ARGB32_OFFSET_R] * 0.2125 +
                        pixel[GFX_ARGB32_OFFSET_G] * 0.7154 +
                        pixel[GFX_ARGB32_OFFSET_B] * 0.0721) *
                       (pixel[GFX_ARGB32_OFFSET_A] / 255.0) * aOpacity);

      memset(pixel, alpha, 4);
    }

  gfxPattern *retval = new gfxPattern(image);
  NS_IF_ADDREF(retval);
  return retval;
}
コード例 #8
0
ファイル: nsSVGPatternFrame.cpp プロジェクト: ahadzi/celtx
nsresult
nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
                                gfxMatrix* patternMatrix,
                                nsSVGGeometryFrame *aSource,
                                float aGraphicOpacity)
{
  /*
   * General approach:
   *    Set the content geometry stuff
   *    Calculate our bbox (using x,y,width,height & patternUnits & 
   *                        patternTransform)
   *    Create the surface
   *    Calculate the content transformation matrix
   *    Get our children (we may need to get them from another Pattern)
   *    Call SVGPaint on all of our children
   *    Return
   */
  *surface = nsnull;

  // Get our child
  nsIFrame *firstKid;
  if (NS_FAILED(GetPatternFirstChild(&firstKid)))
    return NS_ERROR_FAILURE; // Either no kids or a bad reference

  /*
   * Get the content geometry information.  This is a little tricky --
   * our parent is probably a <defs>, but we are rendering in the context
   * of some geometry source.  Our content geometry information needs to
   * come from our rendering parent as opposed to our content parent.  We
   * get that information from aSource, which is passed to us from the
   * backend renderer.
   *
   * There are three "geometries" that we need:
   *   1) The bounding box for the pattern.  We use this to get the
   *      width and height for the surface, and as the return to
   *      GetBBox.
   *   2) The transformation matrix for the pattern.  This is not *quite*
   *      the same as the canvas transformation matrix that we will
   *      provide to our rendering children since we "fudge" it a little
   *      to get the renderer to handle the translations correctly for us.
   *   3) The CTM that we return to our children who make up the pattern.
   */

  // Get all of the information we need from our "caller" -- i.e.
  // the geometry that is being rendered with a pattern
  nsSVGElement *callerContent;
  nsCOMPtr<nsIDOMSVGRect> callerBBox;
  nsCOMPtr<nsIDOMSVGMatrix> callerCTM;
  if (NS_FAILED(GetCallerGeometry(getter_AddRefs(callerCTM),
                                  getter_AddRefs(callerBBox),
                                  &callerContent, aSource)))
    return NS_ERROR_FAILURE;

  // Construct the CTM that we will provide to our children when we
  // render them into the tile.
  if (NS_FAILED(ConstructCTM(getter_AddRefs(mCTM), callerBBox, callerCTM)))
    return NS_ERROR_FAILURE;

  // Get the bounding box of the pattern.  This will be used to determine
  // the size of the surface, and will also be used to define the bounding
  // box for the pattern tile.
  nsCOMPtr<nsIDOMSVGRect> bbox;
  if (NS_FAILED(GetPatternRect(getter_AddRefs(bbox),
                               callerBBox, callerCTM,
                               callerContent)))
    return NS_ERROR_FAILURE;

  // Get the transformation matrix that we will hand to the renderer's pattern
  // routine.
  *patternMatrix = GetPatternMatrix(bbox, callerBBox, callerCTM);

#ifdef DEBUG_scooter
  printRect("Geometry Rect: ", callerBBox);
  printRect("Pattern Rect: ", bbox);
  printCTM("Pattern TM ", *patternMatrix);
  printCTM("Child TM ", mCTM);
#endif

  // Now that we have all of the necessary geometries, we can
  // create our surface.
  float patternWidth, patternHeight;
  bbox->GetWidth(&patternWidth);
  bbox->GetHeight(&patternHeight);

  PRBool resultOverflows;
  gfxIntSize surfaceSize =
    nsSVGUtils::ConvertToSurfaceSize(gfxSize(patternWidth, patternHeight),
                                     &resultOverflows);

  // 0 disables rendering, < 0 is an error
  if (surfaceSize.width <= 0 || surfaceSize.height <= 0)
    return NS_ERROR_FAILURE;

  if (resultOverflows) {
    // scale down drawing to new pattern surface size
    nsCOMPtr<nsIDOMSVGMatrix> tempTM, aCTM;
    NS_NewSVGMatrix(getter_AddRefs(tempTM),
                    surfaceSize.width / patternWidth, 0.0f,
                    0.0f, surfaceSize.height / patternHeight,
                    0.0f, 0.0f);
    mCTM->Multiply(tempTM, getter_AddRefs(aCTM));
    aCTM.swap(mCTM);

    // and magnify pattern to compensate
    patternMatrix->Scale(patternWidth / surfaceSize.width,
                         patternHeight / surfaceSize.height);
  }

#ifdef DEBUG_scooter
  printf("Creating %dX%d surface\n", int(surfaceSize.width), int(surfaceSize.height));
#endif

  nsRefPtr<gfxASurface> tmpSurface =
    gfxPlatform::GetPlatform()->CreateOffscreenSurface(surfaceSize,
                                                       gfxASurface::ImageFormatARGB32);
  if (!tmpSurface || tmpSurface->CairoStatus())
    return NS_ERROR_FAILURE;

  gfxContext tmpContext(tmpSurface);
  nsSVGRenderState tmpState(&tmpContext);

  // Fill with transparent black
  tmpContext.SetOperator(gfxContext::OPERATOR_CLEAR);
  tmpContext.Paint();
  tmpContext.SetOperator(gfxContext::OPERATOR_OVER);

  if (aGraphicOpacity != 1.0f) {
    tmpContext.Save();
    tmpContext.PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
  }

  // OK, now render -- note that we use "firstKid", which
  // we got at the beginning because it takes care of the
  // referenced pattern situation for us

  // Set our geometrical parent
  mSource = aSource;

  for (nsIFrame* kid = firstKid; kid;
       kid = kid->GetNextSibling()) {
    nsSVGUtils::PaintChildWithEffects(&tmpState, nsnull, kid);
  }
  mSource = nsnull;

  if (aGraphicOpacity != 1.0f) {
    tmpContext.PopGroupToSource();
    tmpContext.Paint(aGraphicOpacity);
    tmpContext.Restore();
  }

  // caller now owns the surface
  tmpSurface.swap(*surface);
  return NS_OK;
}
コード例 #9
0
nsresult nsSVGTransform::Init()
{
  nsresult rv = NS_NewSVGMatrix(getter_AddRefs(mMatrix));
  NS_ADD_SVGVALUE_OBSERVER(mMatrix);
  return rv;
}