gfxMatrix SVGMarkerElement::GetMarkerTransform(float aStrokeWidth, float aX, float aY, float aAutoAngle) { gfxFloat scale = mEnumAttributes[MARKERUNITS].GetAnimValue() == SVG_MARKERUNITS_STROKEWIDTH ? aStrokeWidth : 1.0; gfxFloat angle = mOrientType.GetAnimValue() == SVG_MARKER_ORIENT_AUTO ? aAutoAngle : mAngleAttributes[ORIENT].GetAnimValue() * M_PI / 180.0; return gfxMatrix(cos(angle) * scale, sin(angle) * scale, -sin(angle) * scale, cos(angle) * scale, aX, aY); }
NS_IMETHODIMP nsSVGPathGeometryFrame::UpdateCoveredRegion() { gfxRect extent = GetBBoxContribution(gfxMatrix(), nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIgnoreFillIfNone | nsSVGUtils::eBBoxIncludeStroke | nsSVGUtils::eBBoxIgnoreStrokeIfNone | nsSVGUtils::eBBoxIncludeMarkers); mRect = nsLayoutUtils::RoundGfxRectToAppRect(extent, PresContext()->AppUnitsPerCSSPixel()); // See bug 614732 comment 32. mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG( mRect, GetCanvasTM(), PresContext()); return NS_OK; }
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; }
gfx3DMatrix nsSVGForeignObjectFrame::GetTransformMatrix(nsIFrame* aAncestor, nsIFrame **aOutAncestor) { NS_PRECONDITION(aOutAncestor, "We need an ancestor to write to!"); /* Set the ancestor to be the outer frame. */ *aOutAncestor = nsSVGUtils::GetOuterSVGFrame(this); NS_ASSERTION(*aOutAncestor, "How did we end up without an outer frame?"); if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) { return gfx3DMatrix::From2D(gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); } /* Return the matrix back to the root, factoring in the x and y offsets. */ return gfx3DMatrix::From2D(GetCanvasTMForChildren()); }
gfxMatrix nsSVGMarkerElement::GetMarkerTransform(float aStrokeWidth, float aX, float aY, float aAngle) { float scale = 1.0; if (mEnumAttributes[MARKERUNITS].GetAnimValue() == SVG_MARKERUNITS_STROKEWIDTH) scale = aStrokeWidth; if (mOrientType.GetAnimValue() != SVG_MARKER_ORIENT_AUTO) { aAngle = mAngleAttributes[ORIENT].GetAnimValue(); } return gfxMatrix(cos(aAngle) * scale, sin(aAngle) * scale, -sin(aAngle) * scale, cos(aAngle) * scale, aX, aY); }
static already_AddRefed<gfxDrawable> DrawableFromPaintServer(nsIFrame* aFrame, nsIFrame* aTarget, const nsSize& aPaintServerSize, const gfxIntSize& aRenderSize) { // aPaintServerSize is the size that would be filled when using // background-repeat:no-repeat and background-size:auto. For normal background // images, this would be the intrinsic size of the image; for gradients and // patterns this would be the whole target frame fill area. // aRenderSize is what we will be actually filling after accounting for // background-size. if (aFrame->IsFrameOfType(nsIFrame::eSVGPaintServer)) { // aFrame is either a pattern or a gradient. These fill the whole target // frame by default, so aPaintServerSize is the whole target background fill // area. nsSVGPaintServerFrame* server = static_cast<nsSVGPaintServerFrame*>(aFrame); gfxRect overrideBounds(0, 0, aPaintServerSize.width, aPaintServerSize.height); overrideBounds.ScaleInverse(aFrame->PresContext()->AppUnitsPerDevPixel()); nsRefPtr<gfxPattern> pattern = server->GetPaintServerPattern(aTarget, 1.0, &overrideBounds); // pattern is now set up to fill aPaintServerSize. But we want it to // fill aRenderSize, so we need to add a scaling transform. // We couldn't just have set overrideBounds to aRenderSize - it would have // worked for gradients, but for patterns it would result in a different // pattern size. gfxFloat scaleX = overrideBounds.Width() / aRenderSize.width; gfxFloat scaleY = overrideBounds.Height() / aRenderSize.height; gfxMatrix scaleMatrix = gfxMatrix().Scale(scaleX, scaleY); pattern->SetMatrix(scaleMatrix.Multiply(pattern->GetMatrix())); nsRefPtr<gfxDrawable> drawable = new gfxPatternDrawable(pattern, aRenderSize); return drawable.forget(); } // We don't want to paint into a surface as long as we don't need to, so we // set up a drawing callback. nsRefPtr<gfxDrawingCallback> cb = new PaintFrameCallback(aFrame, aTarget, aPaintServerSize, aRenderSize); nsRefPtr<gfxDrawable> drawable = new gfxCallbackDrawable(cb, aRenderSize); return drawable.forget(); }
/* GetThebesMatrix converts the stored matrix in a few steps. */ gfxMatrix nsStyleTransformMatrix::GetThebesMatrix(const nsRect& aBounds, float aScale) const { /* Compute the graphics matrix. We take the stored main elements, along with * the delta, and add in the matrices: * * | 0 0 dx1| * | 0 0 dx2| * width * | 0 0 0| * * | 0 0 dy1| * | 0 0 dy2| * height * | 0 0 0| */ return gfxMatrix(mMain[0], mMain[1], mMain[2], mMain[3], NSAppUnitsToFloatPixels(GetXTranslation(aBounds), aScale), NSAppUnitsToFloatPixels(GetYTranslation(aBounds), aScale)); }
gfxMatrix nsSVGGradientFrame::GetGradientTransform(nsSVGGeometryFrame *aSource) { gfxMatrix bboxMatrix; PRUint16 gradientUnits = GetGradientUnits(); nsIAtom *callerType = aSource->GetType(); if (gradientUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) { // If this gradient is applied to text, our caller // will be the glyph, which is not a container, so we // need to get the parent if (callerType == nsGkAtoms::svgGlyphFrame) mSourceContent = static_cast<nsSVGElement*> (aSource->GetContent()->GetParent()); else mSourceContent = static_cast<nsSVGElement*>(aSource->GetContent()); NS_ASSERTION(mSourceContent, "Can't get content for gradient"); } else { NS_ASSERTION(gradientUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, "Unknown gradientUnits type"); // objectBoundingBox is the default anyway nsIFrame *frame = (callerType == nsGkAtoms::svgGlyphFrame) ? aSource->GetParent() : aSource; gfxRect bbox = nsSVGUtils::GetBBox(frame); bboxMatrix = gfxMatrix(bbox.Width(), 0, 0, bbox.Height(), bbox.X(), bbox.Y()); } nsSVGGradientElement *element = GetGradientWithAttr(nsGkAtoms::gradientTransform, mContent); nsCOMPtr<nsIDOMSVGTransformList> trans; element->mGradientTransform->GetAnimVal(getter_AddRefs(trans)); nsCOMPtr<nsIDOMSVGMatrix> gradientTransform = nsSVGTransformList::GetConsolidationMatrix(trans); if (!gradientTransform) return bboxMatrix; return bboxMatrix.PreMultiply(nsSVGUtils::ConvertSVGMatrixToThebes(gradientTransform)); }
bool HwcComposer2D::TryRender(Layer* aRoot, const gfxMatrix& aGLWorldTransform) { if (!aGLWorldTransform.PreservesAxisAlignedRectangles()) { LOGD("Render aborted. World transform has non-square angle rotation"); return false; } MOZ_ASSERT(Initialized()); if (mList) { mList->numHwLayers = 0; mHwcLayerMap.Clear(); } if (mPrepared) { Reset(); } // XXX: The clear() below means all rect vectors will be have to be // reallocated. We may want to avoid this if possible mVisibleRegions.clear(); MOZ_ASSERT(mHwcLayerMap.IsEmpty()); if (!PrepareLayerList(aRoot, mScreenRect, gfxMatrix(), aGLWorldTransform)) { LOGD("Render aborted. Nothing was drawn to the screen"); return false; } if (!TryHwComposition()) { LOGD("H/W Composition failed"); return false; } LOGD("Frame rendered"); return true; }
void nsRenderingContext::DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1) { gfxPoint p0 = gfxPoint(FROM_TWIPS(aX0), FROM_TWIPS(aY0)); gfxPoint p1 = gfxPoint(FROM_TWIPS(aX1), FROM_TWIPS(aY1)); // we can't draw thick lines with gfx, so we always assume we want // pixel-aligned lines if the rendering context is at 1.0 scale gfxMatrix savedMatrix = mThebes->CurrentMatrix(); if (!savedMatrix.HasNonTranslation()) { p0 = mThebes->UserToDevice(p0); p1 = mThebes->UserToDevice(p1); p0.Round(); p1.Round(); mThebes->SetMatrix(gfxMatrix()); mThebes->NewPath(); // snap straight lines if (p0.x == p1.x) { mThebes->Line(p0 + gfxPoint(0.5, 0), p1 + gfxPoint(0.5, 0)); } else if (p0.y == p1.y) { mThebes->Line(p0 + gfxPoint(0, 0.5), p1 + gfxPoint(0, 0.5)); } else { mThebes->Line(p0, p1); } mThebes->Stroke(); mThebes->SetMatrix(savedMatrix); } else { mThebes->NewPath(); mThebes->Line(p0, p1); mThebes->Stroke(); } }
gfxMatrix nsSVGMarkerFrame::GetCanvasTM(PRUint32 aFor) { NS_ASSERTION(mMarkedFrame, "null nsSVGPathGeometry frame"); if (mInUse2) { // We're going to be bailing drawing the marker, so return an identity. return gfxMatrix(); } nsSVGMarkerElement *content = static_cast<nsSVGMarkerElement*>(mContent); mInUse2 = true; gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(aFor); mInUse2 = false; gfxMatrix markerTM = content->GetMarkerTransform(mStrokeWidth, mX, mY, mAutoAngle); gfxMatrix viewBoxTM = content->GetViewBoxTransform(); return viewBoxTM * markerTM * markedTM; }
void SVGMotionSMILAnimationFunction:: RebuildPathAndVerticesFromMpathElem(nsSVGMpathElement* aMpathElem) { mPathSourceType = ePathSourceType_Mpath; // Use the path that's the target of our chosen <mpath> child. nsSVGPathElement* pathElem = aMpathElem->GetReferencedPath(); if (pathElem) { const SVGPathData &path = pathElem->GetAnimPathSegList()->GetAnimValue(); // Path data must contain of at least one path segment (if the path data // doesn't begin with a valid "M", then it's invalid). if (path.Length()) { bool ok = path.GetDistancesFromOriginToEndsOfVisibleSegments(&mPathVertices); if (ok && mPathVertices.Length()) { mPath = pathElem->GetFlattenedPath(gfxMatrix()); } } } }
PRBool gfxSurfaceDrawable::Draw(gfxContext* aContext, const gfxRect& aFillRect, PRBool aRepeat, const gfxPattern::GraphicsFilter& aFilter, const gfxMatrix& aTransform) { nsRefPtr<gfxPattern> pattern = new gfxPattern(mSurface); if (aRepeat) { pattern->SetExtend(gfxPattern::EXTEND_REPEAT); pattern->SetFilter(aFilter); } else { gfxPattern::GraphicsFilter filter = aFilter; if (aContext->CurrentMatrix().HasOnlyIntegerTranslation() && aTransform.HasOnlyIntegerTranslation()) { // If we only have integer translation, no special filtering needs to // happen and we explicitly use FILTER_FAST. This is fast for some // backends. filter = gfxPattern::FILTER_FAST; } nsRefPtr<gfxASurface> currentTarget = aContext->CurrentSurface(); gfxMatrix deviceSpaceToImageSpace = DeviceToImageTransform(aContext, aTransform); PreparePatternForUntiledDrawing(pattern, deviceSpaceToImageSpace, currentTarget, filter); } #ifdef MOZ_GFX_OPTIMIZE_MOBILE if (!mozilla::supports_neon()) { pattern->SetFilter(gfxPattern::FILTER_FAST); } #endif pattern->SetMatrix(gfxMatrix(aTransform).Multiply(mTransform)); aContext->NewPath(); aContext->SetPattern(pattern); aContext->Rectangle(aFillRect); aContext->Fill(); return PR_TRUE; }
nsSVGTransform SVGTransformSMILData::ToSVGTransform() const { nsSVGTransform result; switch (mTransformType) { case SVG_TRANSFORM_MATRIX: result.SetMatrix(gfxMatrix(mParams[0], mParams[1], mParams[2], mParams[3], mParams[4], mParams[5])); break; case SVG_TRANSFORM_TRANSLATE: result.SetTranslate(mParams[0], mParams[1]); break; case SVG_TRANSFORM_SCALE: result.SetScale(mParams[0], mParams[1]); break; case SVG_TRANSFORM_ROTATE: result.SetRotate(mParams[0], mParams[1], mParams[2]); break; case SVG_TRANSFORM_SKEWX: result.SetSkewX(mParams[0]); break; case SVG_TRANSFORM_SKEWY: result.SetSkewY(mParams[0]); break; default: NS_NOTREACHED("Unexpected transform type"); break; } return result; }
/* virtual */ gfxMatrix SVGUseElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix, TransformTypes aWhich) const { NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(), "Skipping eUserSpaceToParent transforms makes no sense"); // 'transform' attribute: gfxMatrix fromUserSpace = SVGUseElementBase::PrependLocalTransformsTo(aMatrix, aWhich); if (aWhich == eUserSpaceToParent) { return fromUserSpace; } // our 'x' and 'y' attributes: float x, y; const_cast<SVGUseElement*>(this)->GetAnimatedLengthValues(&x, &y, nullptr); gfxMatrix toUserSpace = gfxMatrix().Translate(gfxPoint(x, y)); if (aWhich == eChildToUserSpace) { return toUserSpace; } NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes"); return toUserSpace * fromUserSpace; }
already_AddRefed<nsISVGPoint> SVGPathElement::GetPointAtLength(float distance, ErrorResult& rv) { nsRefPtr<gfxFlattenedPath> flat = GetFlattenedPath(gfxMatrix()); if (!flat) { rv.Throw(NS_ERROR_FAILURE); return nullptr; } float totalLength = flat->GetLength(); if (mPathLength.IsExplicitlySet()) { float pathLength = mPathLength.GetAnimValue(); if (pathLength <= 0) { rv.Throw(NS_ERROR_FAILURE); return nullptr; } distance *= totalLength / pathLength; } distance = std::max(0.f, distance); distance = std::min(totalLength, distance); nsCOMPtr<nsISVGPoint> point = new DOMSVGPoint(flat->FindPoint(gfxPoint(distance, 0))); return point.forget(); }
void nsRenderingContext::SetClip(const nsIntRegion& aRegion) { // Region is in device coords, no transformation. This should // only be called when there is no transform in place, when we we // just start painting a widget. The region is set by the platform // paint routine. Therefore, there is no option to intersect with // an existing clip. gfxMatrix mat = mThebes->CurrentMatrix(); mThebes->SetMatrix(gfxMatrix()); mThebes->ResetClip(); mThebes->NewPath(); nsIntRegionRectIterator iter(aRegion); const nsIntRect* rect; while ((rect = iter.Next())) { mThebes->Rectangle(gfxRect(rect->x, rect->y, rect->width, rect->height), true); } mThebes->Clip(); mThebes->SetMatrix(mat); }
already_AddRefed<SVGMatrix> SVGMatrix::ScaleNonUniform(float scaleFactorX, float scaleFactorY) { RefPtr<SVGMatrix> matrix = new SVGMatrix( gfxMatrix(GetMatrix()).PreScale(scaleFactorX, scaleFactorY)); return matrix.forget(); }
void RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1, bool flip_y /* = false */) { if (vertexCoords.IsEmpty() && x0 == 0.0f && y0 == 0.0f && x1 == 1.0f && y1 == 1.0f) { mIsSimpleQuad = true; if (flip_y) { mTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty0 - ty1, tx0, ty1)); } else { mTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty1 - ty0, tx0, ty0)); } } else if (mIsSimpleQuad) { mIsSimpleQuad = false; mTextureTransform = gfx3DMatrix(); } vert_coord v; v.x = x0; v.y = y0; vertexCoords.AppendElement(v); v.x = x1; v.y = y0; vertexCoords.AppendElement(v); v.x = x0; v.y = y1; vertexCoords.AppendElement(v); v.x = x0; v.y = y1; vertexCoords.AppendElement(v); v.x = x1; v.y = y0; vertexCoords.AppendElement(v); v.x = x1; v.y = y1; vertexCoords.AppendElement(v); if (flip_y) { tex_coord t; t.u = tx0; t.v = ty1; texCoords.AppendElement(t); t.u = tx1; t.v = ty1; texCoords.AppendElement(t); t.u = tx0; t.v = ty0; texCoords.AppendElement(t); t.u = tx0; t.v = ty0; texCoords.AppendElement(t); t.u = tx1; t.v = ty1; texCoords.AppendElement(t); t.u = tx1; t.v = ty0; texCoords.AppendElement(t); } else { tex_coord t; t.u = tx0; t.v = ty0; texCoords.AppendElement(t); t.u = tx1; t.v = ty0; texCoords.AppendElement(t); t.u = tx0; t.v = ty1; texCoords.AppendElement(t); t.u = tx0; t.v = ty1; texCoords.AppendElement(t); t.u = tx1; t.v = ty0; texCoords.AppendElement(t); t.u = tx1; t.v = ty1; texCoords.AppendElement(t); } }
already_AddRefed<SVGMatrix> SVGMatrix::FlipY() { const gfxMatrix& mx = GetMatrix(); RefPtr<SVGMatrix> matrix = new SVGMatrix( gfxMatrix(mx._11, mx._12, -mx._21, -mx._22, mx._31, mx._32)); return matrix.forget(); }
already_AddRefed<SVGMatrix> SVGMatrix::Rotate(float angle) { RefPtr<SVGMatrix> matrix = new SVGMatrix(gfxMatrix(GetMatrix()).PreRotate(angle * radPerDegree)); return matrix.forget(); }
gfxMatrix gfxContext::CurrentMatrix() const { cairo_matrix_t mat; cairo_get_matrix(mCairo, &mat); return gfxMatrix(mat); }
already_AddRefed<gfxPattern> nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *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 nullptr; } AutoMaskReferencer maskRef(this); nsSVGMaskElement *mask = static_cast<nsSVGMaskElement*>(mContent); uint16_t 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); gfxContext *gfx = aContext->ThebesContext(); // Get the clip extents in device space: gfx->Save(); nsSVGUtils::SetClipRect(gfx, aMatrix, maskArea); gfx->IdentityMatrix(); gfxRect clipExtents = gfx->GetClipExtents(); clipExtents.RoundOut(); gfx->Restore(); bool 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 nullptr; if (resultOverflows) return nullptr; nsRefPtr<gfxImageSurface> image = new gfxImageSurface(surfaceSize, gfxASurface::ImageFormatARGB32); if (!image || image->CairoStatus()) return nullptr; // We would like to use gfxImageSurface::SetDeviceOffset() to position // 'image'. However, we need to set the same matrix on the temporary context // and pattern that we create below as is currently set on 'gfx'. // Unfortunately, any device offset set by SetDeviceOffset() is affected by // the transform passed to the SetMatrix() calls, so to avoid that we account // for the device offset in the transform rather than use SetDeviceOffset(). gfxMatrix matrix = gfx->CurrentMatrix() * gfxMatrix().Translate(-clipExtents.TopLeft()); nsRenderingContext tmpCtx; tmpCtx.Init(this->PresContext()->DeviceContext(), image); tmpCtx.ThebesContext()->SetMatrix(matrix); mMaskParent = aParent; if (mMaskParentMatrix) { *mMaskParentMatrix = aMatrix; } else { mMaskParentMatrix = new gfxMatrix(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::TRANSFORM_CHANGED); } nsSVGUtils::PaintFrameWithEffects(&tmpCtx, nullptr, kid); } uint8_t *data = image->Data(); int32_t stride = image->Stride(); nsIntRect rect(0, 0, surfaceSize.width, surfaceSize.height); nsSVGUtils::UnPremultiplyImageDataAlpha(data, stride, rect); if (GetStyleSVG()->mColorInterpolation == NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) { nsSVGUtils::ConvertImageDataToLinearRGB(data, stride, rect); } for (int32_t y = 0; y < surfaceSize.height; y++) for (int32_t x = 0; x < surfaceSize.width; x++) { uint8_t *pixel = data + stride * y + 4 * x; /* linearRGB -> intensity */ uint8_t alpha = static_cast<uint8_t> ((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); retval->SetMatrix(matrix); NS_IF_ADDREF(retval); return retval; }
already_AddRefed<SVGMatrix> SVGMatrix::Translate(float x, float y) { RefPtr<SVGMatrix> matrix = new SVGMatrix(gfxMatrix(GetMatrix()).PreTranslate(gfxPoint(x, y))); return matrix.forget(); }