Example #1
0
float
nsSVGUtils::ObjectSpace(const gfxRect &aRect, const nsSVGLength2 *aLength)
{
  float fraction, axis;

  switch (aLength->GetCtxType()) {
  case X:
    axis = aRect.Width();
    break;
  case Y:
    axis = aRect.Height();
    break;
  case XY:
    axis = float(ComputeNormalizedHypotenuse(aRect.Width(), aRect.Height()));
    break;
  default:
    NS_NOTREACHED("unexpected ctx type");
    axis = 0.0f;
    break;
  }

  if (aLength->IsPercentage()) {
    fraction = aLength->GetAnimValInSpecifiedUnits() / 100;
  } else {
    fraction = aLength->GetAnimValue(static_cast<nsSVGSVGElement*>
                                                (nsnull));
  }

  return fraction * axis;
}
Example #2
0
nsresult
NS_NewSVGRect(mozilla::dom::SVGRect** result, const gfxRect& rect)
{
  return NS_NewSVGRect(result,
                       rect.X(), rect.Y(),
                       rect.Width(), rect.Height());
}
Example #3
0
gfxRect gfx3DMatrix::ProjectRectBounds(const gfxRect& aRect) const
{
  gfxPoint points[4];

  points[0] = ProjectPoint(aRect.TopLeft());
  points[1] = ProjectPoint(gfxPoint(aRect.X() + aRect.Width(), aRect.Y()));
  points[2] = ProjectPoint(gfxPoint(aRect.X(), aRect.Y() + aRect.Height()));
  points[3] = ProjectPoint(gfxPoint(aRect.X() + aRect.Width(),
                                    aRect.Y() + aRect.Height()));

  gfxFloat min_x, max_x;
  gfxFloat min_y, max_y;

  min_x = max_x = points[0].x;
  min_y = max_y = points[0].y;

  for (int i=1; i<4; i++) {
    min_x = min(points[i].x, min_x);
    max_x = max(points[i].x, max_x);
    min_y = min(points[i].y, min_y);
    max_y = max(points[i].y, max_y);
  }

  return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
}
Example #4
0
nsresult
NS_NewSVGRect(nsIDOMSVGRect** result, const gfxRect& rect)
{
  return NS_NewSVGRect(result,
                       rect.X(), rect.Y(),
                       rect.Width(), rect.Height());
}
Example #5
0
// clipping
void
gfxContext::Clip(const gfxRect& rect)
{
    cairo_new_path(mCairo);
    cairo_rectangle(mCairo, rect.X(), rect.Y(), rect.Width(), rect.Height());
    cairo_clip(mCairo);
}
Example #6
0
imgFrame::SurfaceWithFormat
imgFrame::SurfaceForDrawing(bool               aDoPadding,
                            bool               aDoPartialDecode,
                            bool               aDoTile,
                            const nsIntMargin& aPadding,
                            gfxMatrix&         aUserSpaceToImageSpace,
                            gfxRect&           aFill,
                            gfxRect&           aSubimage,
                            gfxRect&           aSourceRect,
                            gfxRect&           aImageRect)
{
  gfxIntSize size(PRInt32(aImageRect.Width()), PRInt32(aImageRect.Height()));
  if (!aDoPadding && !aDoPartialDecode) {
    NS_ASSERTION(!mSinglePixel, "This should already have been handled");
    return SurfaceWithFormat(new gfxSurfaceDrawable(ThebesSurface(), size), mFormat);
  }

  gfxRect available = gfxRect(mDecoded.x, mDecoded.y, mDecoded.width, mDecoded.height);

  if (aDoTile || mSinglePixel) {
    // Create a temporary surface.
    // Give this surface an alpha channel because there are
    // transparent pixels in the padding or undecoded area
    gfxImageSurface::gfxImageFormat format = gfxASurface::ImageFormatARGB32;
    nsRefPtr<gfxASurface> surface =
      gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, gfxImageSurface::ContentFromFormat(format));
    if (!surface || surface->CairoStatus())
      return SurfaceWithFormat();

    // Fill 'available' with whatever we've got
    gfxContext tmpCtx(surface);
    tmpCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
    if (mSinglePixel) {
      tmpCtx.SetDeviceColor(mSinglePixelColor);
    } else {
      tmpCtx.SetSource(ThebesSurface(), gfxPoint(aPadding.left, aPadding.top));
    }
    tmpCtx.Rectangle(available);
    tmpCtx.Fill();
    return SurfaceWithFormat(new gfxSurfaceDrawable(surface, size), format);
  }

  // Not tiling, and we have a surface, so we can account for
  // padding and/or a partial decode just by twiddling parameters.
  // First, update our user-space fill rect.
  aSourceRect = aSourceRect.Intersect(available);
  gfxMatrix imageSpaceToUserSpace = aUserSpaceToImageSpace;
  imageSpaceToUserSpace.Invert();
  aFill = imageSpaceToUserSpace.Transform(aSourceRect);

  aSubimage = aSubimage.Intersect(available) - gfxPoint(aPadding.left, aPadding.top);
  aUserSpaceToImageSpace.Multiply(gfxMatrix().Translate(-gfxPoint(aPadding.left, aPadding.top)));
  aSourceRect = aSourceRect - gfxPoint(aPadding.left, aPadding.top);
  aImageRect = gfxRect(0, 0, mSize.width, mSize.height);

  gfxIntSize availableSize(mDecoded.width, mDecoded.height);
  return SurfaceWithFormat(new gfxSurfaceDrawable(ThebesSurface(),
                                                  availableSize),
                           mFormat);
}
void
gfxFontMissingGlyphs::DrawMissingGlyph(gfxContext *aContext, const gfxRect& aRect,
                                       uint32_t aChar)
{
    aContext->Save();

    gfxRGBA currentColor;
    if (!aContext->GetDeviceColor(currentColor)) {
        // We're currently drawing with some kind of pattern... Just draw
        // the missing-glyph data in black.
        currentColor = gfxRGBA(0,0,0,1);
    }

    // Stroke a rectangle so that the stroke's left edge is inset one pixel
    // from the left edge of the glyph box and the stroke's right edge
    // is inset one pixel from the right edge of the glyph box.
    gfxFloat halfBorderWidth = BOX_BORDER_WIDTH/2.0;
    gfxFloat borderLeft = aRect.X() + BOX_HORIZONTAL_INSET + halfBorderWidth;
    gfxFloat borderRight = aRect.XMost() - BOX_HORIZONTAL_INSET - halfBorderWidth;
    gfxRect borderStrokeRect(borderLeft, aRect.Y() + halfBorderWidth,
                             borderRight - borderLeft, aRect.Height() - 2*halfBorderWidth);
    if (!borderStrokeRect.IsEmpty()) {
        aContext->SetLineWidth(BOX_BORDER_WIDTH);
        aContext->SetDash(gfxContext::gfxLineSolid);
        aContext->SetLineCap(gfxContext::LINE_CAP_SQUARE);
        aContext->SetLineJoin(gfxContext::LINE_JOIN_MITER);
        gfxRGBA color = currentColor;
        color.a *= BOX_BORDER_OPACITY;
        aContext->SetDeviceColor(color);
        aContext->NewPath();
        aContext->Rectangle(borderStrokeRect);

#ifdef MOZ_GFX_OPTIMIZE_MOBILE
        aContext->Fill();
#else
        aContext->Stroke();
#endif
    }

#ifndef MOZ_GFX_OPTIMIZE_MOBILE
    gfxPoint center(aRect.X() + aRect.Width()/2,
                    aRect.Y() + aRect.Height()/2);
    gfxFloat halfGap = HEX_CHAR_GAP/2.0;
    gfxFloat top = -(MINIFONT_HEIGHT + halfGap);
    if (aChar < 0x10000) {
        if (aRect.Width() >= 2*MINIFONT_WIDTH + HEX_CHAR_GAP &&
            aRect.Height() >= 2*MINIFONT_HEIGHT + HEX_CHAR_GAP) {
            // Draw 4 digits for BMP
            aContext->SetDeviceColor(currentColor);
            gfxFloat left = -(MINIFONT_WIDTH + halfGap);
            DrawHexChar(aContext,
                        center + gfxPoint(left, top), (aChar >> 12) & 0xF);
            DrawHexChar(aContext,
                        center + gfxPoint(halfGap, top), (aChar >> 8) & 0xF);
            DrawHexChar(aContext,
                        center + gfxPoint(left, halfGap), (aChar >> 4) & 0xF);
            DrawHexChar(aContext,
                        center + gfxPoint(halfGap, halfGap), aChar & 0xF);
        }
    } else {
Example #8
0
void
gfxASurface::MarkDirty(const gfxRect& r)
{
    cairo_surface_mark_dirty_rectangle(mSurface,
                                       (int) r.X(), (int) r.Y(),
                                       (int) r.Width(), (int) r.Height());
}
Example #9
0
nsRect
nsSVGUtils::ToAppPixelRect(nsPresContext *aPresContext, const gfxRect& rect)
{
  return nsRect(aPresContext->DevPixelsToAppUnits(NSToIntFloor(rect.X())),
                aPresContext->DevPixelsToAppUnits(NSToIntFloor(rect.Y())),
                aPresContext->DevPixelsToAppUnits(NSToIntCeil(rect.XMost()) - NSToIntFloor(rect.X())),
                aPresContext->DevPixelsToAppUnits(NSToIntCeil(rect.YMost()) - NSToIntFloor(rect.Y())));
}
Example #10
0
void
gfxASurface::MarkDirty(const gfxRect& r)
{
    if (!mSurfaceValid)
        return;
    cairo_surface_mark_dirty_rectangle(mSurface,
                                       (int) r.X(), (int) r.Y(),
                                       (int) r.Width(), (int) r.Height());
    gfxPlatform::ClearSourceSurfaceForSurface(this);
}
Example #11
0
gfxMatrix
nsSVGPatternFrame::ConstructCTM(const gfxRect &callerBBox,
                                const gfxMatrix &callerCTM,
                                nsIFrame *aTarget)
{
  gfxMatrix tCTM;
  nsSVGSVGElement *ctx = nsnull;
  nsIContent* targetContent = aTarget->GetContent();

  // The objectBoundingBox conversion must be handled in the CTM:
  if (GetEnumValue(nsSVGPatternElement::PATTERNCONTENTUNITS) ==
      nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
    tCTM.Scale(callerBBox.Width(), callerBBox.Height());
  } else {
    if (targetContent->IsSVG()) {
      ctx = static_cast<nsSVGElement*>(targetContent)->GetCtx();
    }
    float scale = nsSVGUtils::MaxExpansion(callerCTM);
    tCTM.Scale(scale, scale);
  }

  const nsSVGViewBoxRect viewBox = GetViewBox().GetAnimValue();

  if (viewBox.height <= 0.0f && viewBox.width <= 0.0f) {
    return tCTM;
  }

  float viewportWidth, viewportHeight;
  if (targetContent->IsSVG()) {
    // If we're dealing with an SVG target only retrieve the context once.
    // Calling the nsIFrame* variant of GetAnimValue would look it up on
    // every call.
    viewportWidth =
      GetLengthValue(nsSVGPatternElement::WIDTH)->GetAnimValue(ctx);
    viewportHeight =
      GetLengthValue(nsSVGPatternElement::HEIGHT)->GetAnimValue(ctx);
  } else {
    // No SVG target, call the nsIFrame* variant of GetAnimValue.
    viewportWidth =
      GetLengthValue(nsSVGPatternElement::WIDTH)->GetAnimValue(aTarget);
    viewportHeight =
      GetLengthValue(nsSVGPatternElement::HEIGHT)->GetAnimValue(aTarget);
  }
  gfxMatrix tm = nsSVGUtils::GetViewBoxTransform(
    static_cast<nsSVGPatternElement*>(mContent),
    viewportWidth, viewportHeight,
    viewBox.x, viewBox.y,
    viewBox.width, viewBox.height,
    GetPreserveAspectRatio());

  return tm * tCTM;
}
Example #12
0
gfxRect
gfxRect::Union(const gfxRect& aRect) const
{
    if (IsEmpty())
        return aRect;
    if (aRect.IsEmpty())
        return *this;

    gfxFloat x = PR_MIN(aRect.X(), X());
    gfxFloat xmost = PR_MAX(aRect.XMost(), XMost());
    gfxFloat y = PR_MIN(aRect.Y(), Y());
    gfxFloat ymost = PR_MAX(aRect.YMost(), YMost());
    return gfxRect(x, y, xmost - x, ymost - y);
}
Example #13
0
gfx3DMatrix
Layer::SnapTransform(const gfx3DMatrix& aTransform,
                     const gfxRect& aSnapRect,
                     gfxMatrix* aResidualTransform)
{
  if (aResidualTransform) {
    *aResidualTransform = gfxMatrix();
  }

  gfxMatrix matrix2D;
  gfx3DMatrix result;
  if (mManager->IsSnappingEffectiveTransforms() &&
      aTransform.Is2D(&matrix2D) &&
      matrix2D.HasNonIntegerTranslation() &&
      !matrix2D.IsSingular() &&
      !matrix2D.HasNonAxisAlignedTransform()) {
    gfxMatrix snappedMatrix;
    gfxPoint topLeft = matrix2D.Transform(aSnapRect.TopLeft());
    topLeft.Round();
    // first compute scale factors that scale aSnapRect to the snapped rect
    if (aSnapRect.IsEmpty()) {
      snappedMatrix.xx = matrix2D.xx;
      snappedMatrix.yy = matrix2D.yy;
    } else {
      gfxPoint bottomRight = matrix2D.Transform(aSnapRect.BottomRight());
      bottomRight.Round();
      snappedMatrix.xx = (bottomRight.x - topLeft.x)/aSnapRect.Width();
      snappedMatrix.yy = (bottomRight.y - topLeft.y)/aSnapRect.Height();
    }
    // compute translation factors that will move aSnapRect to the snapped rect
    // given those scale factors
    snappedMatrix.x0 = topLeft.x - aSnapRect.pos.x*snappedMatrix.xx;
    snappedMatrix.y0 = topLeft.y - aSnapRect.pos.y*snappedMatrix.yy;
    result = gfx3DMatrix::From2D(snappedMatrix);
    if (aResidualTransform && !snappedMatrix.IsSingular()) {
      // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
      // (i.e., appying snappedMatrix after aResidualTransform gives the
      // ideal transform.
      gfxMatrix snappedMatrixInverse = snappedMatrix;
      snappedMatrixInverse.Invert();
      *aResidualTransform = matrix2D * snappedMatrixInverse;
    }
  } else {
    result = aTransform;
  }
  return result;
}
Example #14
0
gfxQuad 
gfx3DMatrix::TransformRect(const gfxRect& aRect) const
{
  gfxPoint points[4];

  points[0] = Transform(aRect.TopLeft());
  points[1] = Transform(gfxPoint(aRect.X() + aRect.Width(), aRect.Y()));
  points[2] = Transform(gfxPoint(aRect.X() + aRect.Width(),
                                 aRect.Y() + aRect.Height()));
  points[3] = Transform(gfxPoint(aRect.X(), aRect.Y() + aRect.Height()));
  
  // Could this ever result in lines that intersect? I don't think so.
  return gfxQuad(points[0], points[1], points[2], points[3]);
}
Example #15
0
gfxRect
nsSVGUtils::GetRelativeRect(PRUint16 aUnits, const nsSVGLength2 *aXYWH,
                            const gfxRect &aBBox, nsIFrame *aFrame)
{
  float x, y, width, height;
  if (aUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
    x = aBBox.X() + ObjectSpace(aBBox, &aXYWH[0]);
    y = aBBox.Y() + ObjectSpace(aBBox, &aXYWH[1]);
    width = ObjectSpace(aBBox, &aXYWH[2]);
    height = ObjectSpace(aBBox, &aXYWH[3]);
  } else {
    x = nsSVGUtils::UserSpace(aFrame, &aXYWH[0]);
    y = nsSVGUtils::UserSpace(aFrame, &aXYWH[1]);
    width = nsSVGUtils::UserSpace(aFrame, &aXYWH[2]);
    height = nsSVGUtils::UserSpace(aFrame, &aXYWH[3]);
  }
  return gfxRect(x, y, width, height);
}
Example #16
0
gfxRect
gfxRect::Intersect(const gfxRect& aRect) const
{
    gfxRect result(0,0,0,0);

    gfxFloat x = PR_MAX(aRect.X(), X());
    gfxFloat xmost = PR_MIN(aRect.XMost(), XMost());
    if (x >= xmost)
        return result;

    gfxFloat y = PR_MAX(aRect.Y(), Y());
    gfxFloat ymost = PR_MIN(aRect.YMost(), YMost());
    if (y >= ymost)
        return result;

    result = gfxRect(x, y, xmost - x, ymost - y);
    return result;
}
Example #17
0
// XXX snapToPixels is only valid when snapping for filled
// rectangles and for even-width stroked rectangles.
// For odd-width stroked rectangles, we need to offset x/y by
// 0.5...
void
gfxContext::Rectangle(const gfxRect& rect, bool snapToPixels)
{
    if (snapToPixels) {
        gfxRect snappedRect(rect);

        if (UserToDevicePixelSnapped(snappedRect, PR_TRUE))
        {
            cairo_matrix_t mat;
            cairo_get_matrix(mCairo, &mat);
            cairo_identity_matrix(mCairo);
            Rectangle(snappedRect);
            cairo_set_matrix(mCairo, &mat);

            return;
        }
    }

    cairo_rectangle(mCairo, rect.X(), rect.Y(), rect.Width(), rect.Height());
}
Example #18
0
void
gfxASurface::SetOpaqueRect(const gfxRect& aRect)
{
    if (aRect.IsEmpty()) {
        mOpaqueRect = nullptr;
    } else if (!!mOpaqueRect) {
        *mOpaqueRect = aRect;
    } else {
        mOpaqueRect = MakeUnique<gfxRect>(aRect);
    }
}
Example #19
0
gfx3DMatrix
Layer::SnapTransform(const gfx3DMatrix& aTransform,
                     const gfxRect& aSnapRect,
                     gfxMatrix* aResidualTransform)
{
  if (aResidualTransform) {
    *aResidualTransform = gfxMatrix();
  }

  gfxMatrix matrix2D;
  gfx3DMatrix result;
  if (!(mContentFlags & CONTENT_DISABLE_TRANSFORM_SNAPPING) &&
      mManager->IsSnappingEffectiveTransforms() &&
      aTransform.Is2D(&matrix2D) &&
      gfxSize(1.0, 1.0) <= aSnapRect.Size() &&
      matrix2D.PreservesAxisAlignedRectangles()) {
    gfxPoint transformedTopLeft = matrix2D.Transform(aSnapRect.TopLeft());
    transformedTopLeft.Round();
    gfxPoint transformedTopRight = matrix2D.Transform(aSnapRect.TopRight());
    transformedTopRight.Round();
    gfxPoint transformedBottomRight = matrix2D.Transform(aSnapRect.BottomRight());
    transformedBottomRight.Round();

    gfxMatrix snappedMatrix = gfxUtils::TransformRectToRect(aSnapRect,
      transformedTopLeft, transformedTopRight, transformedBottomRight);

    result = gfx3DMatrix::From2D(snappedMatrix);
    if (aResidualTransform && !snappedMatrix.IsSingular()) {
      // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
      // (i.e., appying snappedMatrix after aResidualTransform gives the
      // ideal transform.
      gfxMatrix snappedMatrixInverse = snappedMatrix;
      snappedMatrixInverse.Invert();
      *aResidualTransform = matrix2D * snappedMatrixInverse;
    }
  } else {
    result = aTransform;
  }
  return result;
}
Example #20
0
bool imgFrame::Draw(gfxContext *aContext, GraphicsFilter aFilter,
                    const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill,
                    const nsIntMargin &aPadding, const nsIntRect &aSubimage,
                    uint32_t aImageFlags)
{
  PROFILER_LABEL("image", "imgFrame::Draw");
  NS_ASSERTION(!aFill.IsEmpty(), "zero dest size --- fix caller");
  NS_ASSERTION(!aSubimage.IsEmpty(), "zero source size --- fix caller");
  NS_ASSERTION(!mPalettedImageData, "Directly drawing a paletted image!");

  bool doPadding = aPadding != nsIntMargin(0,0,0,0);
  bool doPartialDecode = !ImageComplete();

  if (mSinglePixel && !doPadding && !doPartialDecode) {
    DoSingleColorFastPath(aContext, mSinglePixelColor, aFill);
    return true;
  }

  gfxMatrix userSpaceToImageSpace = aUserSpaceToImageSpace;
  gfxRect sourceRect = userSpaceToImageSpace.TransformBounds(aFill);
  gfxRect imageRect(0, 0, mSize.width + aPadding.LeftRight(),
                    mSize.height + aPadding.TopBottom());
  gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height);
  gfxRect fill = aFill;

  NS_ASSERTION(!sourceRect.Intersect(subimage).IsEmpty(),
               "We must be allowed to sample *some* source pixels!");

  nsRefPtr<gfxASurface> surf;
  if (!mSinglePixel) {
    surf = ThebesSurface();
    if (!surf)
      return false;
  }

  bool doTile = !imageRect.Contains(sourceRect) &&
                !(aImageFlags & imgIContainer::FLAG_CLAMP);
  SurfaceWithFormat surfaceResult =
    SurfaceForDrawing(doPadding, doPartialDecode, doTile, aPadding,
                      userSpaceToImageSpace, fill, subimage, sourceRect,
                      imageRect, surf);

  if (surfaceResult.IsValid()) {
    gfxUtils::DrawPixelSnapped(aContext, surfaceResult.mDrawable,
                               userSpaceToImageSpace,
                               subimage, sourceRect, imageRect, fill,
                               surfaceResult.mFormat, aFilter, aImageFlags);
  }
  return true;
}
// Given the matrix for the pattern element's own transform, this returns a
// combined matrix including the transforms applicable to its target.
static Matrix
GetPatternMatrix(uint16_t aPatternUnits,
                 const Matrix &patternTransform,
                 const gfxRect &bbox,
                 const gfxRect &callerBBox,
                 const Matrix &callerCTM)
{
  // We really want the pattern matrix to handle translations
  gfxFloat minx = bbox.X();
  gfxFloat miny = bbox.Y();

  if (aPatternUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
    minx += callerBBox.X();
    miny += callerBBox.Y();
  }

  float scale = 1.0f / MaxExpansion(callerCTM);
  Matrix patternMatrix = patternTransform;
  patternMatrix.PreScale(scale, scale);
  patternMatrix.PreTranslate(minx, miny);

  return patternMatrix;
}
// Given the matrix for the pattern element's own transform, this returns a
// combined matrix including the transforms applicable to its target.
static gfxMatrix
GetPatternMatrix(uint16_t aPatternUnits,
                 const gfxMatrix &patternTransform,
                 const gfxRect &bbox,
                 const gfxRect &callerBBox,
                 const gfxMatrix &callerCTM)
{
  // We really want the pattern matrix to handle translations
  gfxFloat minx = bbox.X();
  gfxFloat miny = bbox.Y();

  if (aPatternUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
    minx += callerBBox.X();
    miny += callerBBox.Y();
  }

  float scale = 1.0f / nsSVGUtils::MaxExpansion(callerCTM);
  gfxMatrix patternMatrix = patternTransform;
  patternMatrix.Scale(scale, scale);
  patternMatrix.Translate(gfxPoint(minx, miny));

  return patternMatrix;
}
// Given the matrix for the pattern element's own transform, this returns a
// combined matrix including the transforms applicable to its target.
gfxMatrix
nsSVGPatternFrame::GetPatternMatrix(const gfxMatrix &patternTransform,
                                    const gfxRect &bbox,
                                    const gfxRect &callerBBox,
                                    const gfxMatrix &callerCTM)
{
  // We really want the pattern matrix to handle translations
  gfxFloat minx = bbox.X();
  gfxFloat miny = bbox.Y();

  PRUint16 type = GetEnumValue(nsSVGPatternElement::PATTERNUNITS);
  if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
    minx += callerBBox.X();
    miny += callerBBox.Y();
  }

  float scale = 1.0f / nsSVGUtils::MaxExpansion(callerCTM);
  gfxMatrix patternMatrix = patternTransform;
  patternMatrix.Scale(scale, scale);
  patternMatrix.Translate(gfxPoint(minx, miny));

  return patternMatrix;
}
Example #24
0
gfxRect
gfxContext::UserToDevice(const gfxRect& rect) const
{
    double xmin = rect.X(), ymin = rect.Y(), xmax = rect.XMost(), ymax = rect.YMost();

    double x[3], y[3];
    x[0] = xmin;  y[0] = ymax;
    x[1] = xmax;  y[1] = ymax;
    x[2] = xmax;  y[2] = ymin;

    cairo_user_to_device(mCairo, &xmin, &ymin);
    xmax = xmin;
    ymax = ymin;
    for (int i = 0; i < 3; i++) {
        cairo_user_to_device(mCairo, &x[i], &y[i]);
        xmin = NS_MIN(xmin, x[i]);
        xmax = NS_MAX(xmax, x[i]);
        ymin = NS_MIN(ymin, y[i]);
        ymax = NS_MAX(ymax, y[i]);
    }

    return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin);
}
Example #25
0
Matrix4x4
Layer::SnapTransform(const Matrix4x4& aTransform,
                     const gfxRect& aSnapRect,
                     Matrix* aResidualTransform)
{
  if (aResidualTransform) {
    *aResidualTransform = Matrix();
  }

  Matrix matrix2D;
  Matrix4x4 result;
  if (mManager->IsSnappingEffectiveTransforms() &&
      aTransform.Is2D(&matrix2D) &&
      gfx::Size(1.0, 1.0) <= ToSize(aSnapRect.Size()) &&
      matrix2D.PreservesAxisAlignedRectangles()) {
    IntPoint transformedTopLeft = RoundedToInt(matrix2D * ToPoint(aSnapRect.TopLeft()));
    IntPoint transformedTopRight = RoundedToInt(matrix2D * ToPoint(aSnapRect.TopRight()));
    IntPoint transformedBottomRight = RoundedToInt(matrix2D * ToPoint(aSnapRect.BottomRight()));

    Matrix snappedMatrix = gfxUtils::TransformRectToRect(aSnapRect,
      transformedTopLeft, transformedTopRight, transformedBottomRight);

    result = Matrix4x4::From2D(snappedMatrix);
    if (aResidualTransform && !snappedMatrix.IsSingular()) {
      // set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
      // (i.e., appying snappedMatrix after aResidualTransform gives the
      // ideal transform.
      Matrix snappedMatrixInverse = snappedMatrix;
      snappedMatrixInverse.Invert();
      *aResidualTransform = matrix2D * snappedMatrixInverse;
    }
  } else {
    result = aTransform;
  }
  return result;
}
gfxRect
gfxMatrix::TransformBounds(const gfxRect& rect) const
{
    /* Code taken from cairo-matrix.c, _cairo_matrix_transform_bounding_box isn't public */
    int i;
    double quad_x[4], quad_y[4];
    double min_x, max_x;
    double min_y, max_y;

    quad_x[0] = rect.X();
    quad_y[0] = rect.Y();
    cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[0], &quad_y[0]);

    quad_x[1] = rect.XMost();
    quad_y[1] = rect.Y();
    cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[1], &quad_y[1]);

    quad_x[2] = rect.X();
    quad_y[2] = rect.YMost();
    cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[2], &quad_y[2]);

    quad_x[3] = rect.XMost();
    quad_y[3] = rect.YMost();
    cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[3], &quad_y[3]);

    min_x = max_x = quad_x[0];
    min_y = max_y = quad_y[0];

    for (i = 1; i < 4; i++) {
        if (quad_x[i] < min_x)
            min_x = quad_x[i];
        if (quad_x[i] > max_x)
            max_x = quad_x[i];

        if (quad_y[i] < min_y)
            min_y = quad_y[i];
        if (quad_y[i] > max_y)
            max_y = quad_y[i];
    }

    return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
}
Example #27
0
// Return the largest rectangle that fits in aRect and has the
// same aspect ratio as aRatio, centered at the center of aRect
static gfxRect
CorrectForAspectRatio(const gfxRect& aRect, const nsIntSize& aRatio)
{
  NS_ASSERTION(aRatio.width > 0 && aRatio.height > 0 && !aRect.IsEmpty(),
               "Nothing to draw");
  // Choose scale factor that scales aRatio to just fit into aRect
  gfxFloat scale =
    std::min(aRect.Width()/aRatio.width, aRect.Height()/aRatio.height);
  gfxSize scaledRatio(scale*aRatio.width, scale*aRatio.height);
  gfxPoint topLeft((aRect.Width() - scaledRatio.width)/2,
                   (aRect.Height() - scaledRatio.height)/2);
  return gfxRect(aRect.TopLeft() + topLeft, scaledRatio);
}
already_AddRefed<gfxContext>
gfxCachedTempSurface::Get(gfxASurface::gfxContentType aContentType,
                          const gfxRect& aRect,
                          gfxASurface* aSimilarTo)
{
  if (mSurface) {
    /* Verify the current buffer is valid for this purpose */
    if (mSize.width < aRect.width || mSize.height < aRect.height
        || mSurface->GetContentType() != aContentType) {
      mSurface = nsnull;
    } else {
      NS_ASSERTION(mType == aSimilarTo->GetType(),
                   "Unexpected surface type change");
    }
  }

  bool cleared = false;
  if (!mSurface) {
    mSize = gfxIntSize(PRInt32(ceil(aRect.width)), PRInt32(ceil(aRect.height)));
    mSurface = aSimilarTo->CreateSimilarSurface(aContentType, mSize);
    if (!mSurface)
      return nsnull;

    cleared = PR_TRUE;
#ifdef DEBUG
    mType = aSimilarTo->GetType();
#endif
  }
  mSurface->SetDeviceOffset(-aRect.TopLeft());

  nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
  ctx->Rectangle(aRect);
  ctx->Clip();
  if (!cleared && aContentType != gfxASurface::CONTENT_COLOR) {
    ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
    ctx->Paint();
    ctx->SetOperator(gfxContext::OPERATOR_OVER);
  }

  CachedSurfaceExpirationTracker::MarkSurfaceUsed(this);

  return ctx.forget();
}
Example #29
0
void imgFrame::Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter,
                    const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill,
                    const nsIntMargin &aPadding, const nsIntRect &aSubimage)
{
  NS_ASSERTION(!aFill.IsEmpty(), "zero dest size --- fix caller");
  NS_ASSERTION(!aSubimage.IsEmpty(), "zero source size --- fix caller");
  NS_ASSERTION(!mPalettedImageData, "Directly drawing a paletted image!");

  bool doPadding = aPadding != nsIntMargin(0,0,0,0);
  bool doPartialDecode = !ImageComplete();

  if (mSinglePixel && !doPadding && !doPartialDecode) {
    DoSingleColorFastPath(aContext, mSinglePixelColor, aFill);
    return;
  }

  gfxMatrix userSpaceToImageSpace = aUserSpaceToImageSpace;
  gfxRect sourceRect = userSpaceToImageSpace.Transform(aFill);
  gfxRect imageRect(0, 0, mSize.width + aPadding.LeftRight(),
                    mSize.height + aPadding.TopBottom());
  gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height);
  gfxRect fill = aFill;

  NS_ASSERTION(!sourceRect.Intersect(subimage).IsEmpty(),
               "We must be allowed to sample *some* source pixels!");

  bool doTile = !imageRect.Contains(sourceRect);
  SurfaceWithFormat surfaceResult =
    SurfaceForDrawing(doPadding, doPartialDecode, doTile, aPadding,
                      userSpaceToImageSpace, fill, subimage, sourceRect,
                      imageRect);

  if (surfaceResult.IsValid()) {
    gfxUtils::DrawPixelSnapped(aContext, surfaceResult.mDrawable,
                               userSpaceToImageSpace,
                               subimage, sourceRect, imageRect, fill,
                               surfaceResult.mFormat, aFilter);
  }
}
Example #30
0
bool
gfxContext::UserToDevicePixelSnapped(gfxRect& rect, bool ignoreScale) const
{
    if (GetFlags() & FLAG_DISABLE_SNAPPING)
        return PR_FALSE;

    // if we're not at 1.0 scale, don't snap, unless we're
    // ignoring the scale.  If we're not -just- a scale,
    // never snap.
    const gfxFloat epsilon = 0.0000001;
#define WITHIN_E(a,b) (fabs((a)-(b)) < epsilon)
    cairo_matrix_t mat;
    cairo_get_matrix(mCairo, &mat);
    if (!ignoreScale &&
        (!WITHIN_E(mat.xx,1.0) || !WITHIN_E(mat.yy,1.0) ||
         !WITHIN_E(mat.xy,0.0) || !WITHIN_E(mat.yx,0.0)))
        return PR_FALSE;
#undef WITHIN_E

    gfxPoint p1 = UserToDevice(rect.TopLeft());
    gfxPoint p2 = UserToDevice(rect.TopRight());
    gfxPoint p3 = UserToDevice(rect.BottomRight());

    // Check that the rectangle is axis-aligned. For an axis-aligned rectangle,
    // two opposite corners define the entire rectangle. So check if
    // the axis-aligned rectangle with opposite corners p1 and p3
    // define an axis-aligned rectangle whose other corners are p2 and p4.
    // We actually only need to check one of p2 and p4, since an affine
    // transform maps parallelograms to parallelograms.
    if (p2 == gfxPoint(p1.x, p3.y) || p2 == gfxPoint(p3.x, p1.y)) {
        p1.Round();
        p3.Round();

        rect.MoveTo(gfxPoint(NS_MIN(p1.x, p3.x), NS_MIN(p1.y, p3.y)));
        rect.SizeTo(gfxSize(NS_MAX(p1.x, p3.x) - rect.X(),
                            NS_MAX(p1.y, p3.y) - rect.Y()));
        return PR_TRUE;
    }

    return PR_FALSE;
}