nsWindow::nsWindow() { if (!sScreenInitialized) { // Watching screen on/off state by using a pthread // which implicitly calls exit() when the main thread ends if (pthread_create(&sFramebufferWatchThread, NULL, frameBufferWatcher, NULL)) { NS_RUNTIMEABORT("Failed to create framebufferWatcherThread, aborting..."); } nsIntSize screenSize; bool gotFB = Framebuffer::GetSize(&screenSize); if (!gotFB) { NS_RUNTIMEABORT("Failed to get size from framebuffer, aborting..."); } gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize); char propValue[PROPERTY_VALUE_MAX]; property_get("ro.sf.hwrotation", propValue, "0"); sPhysicalScreenRotation = atoi(propValue) / 90; // Unlike nsScreenGonk::SetRotation(), only support 0 and 180 as there // are no known screens that are mounted at 90 or 270 at the moment. switch (sPhysicalScreenRotation) { case nsIScreen::ROTATION_0_DEG: break; case nsIScreen::ROTATION_180_DEG: sRotationMatrix.Translate(gfxPoint(gScreenBounds.width, gScreenBounds.height)); sRotationMatrix.Rotate(M_PI); break; default: MOZ_NOT_REACHED("Unknown rotation"); break; } sVirtualBounds = gScreenBounds; sScreenInitialized = true; nsAppShell::NotifyScreenInitialized(); // This is a hack to force initialization of the compositor // resources, if we're going to use omtc. // // NB: GetPlatform() will create the gfxPlatform, which wants // to know the color depth, which asks our native window. // This has to happen after other init has finished. gfxPlatform::GetPlatform(); sUsingOMTC = ShouldUseOffMainThreadCompositing(); property_get("ro.display.colorfill", propValue, "0"); sUsingHwc = Preferences::GetBool("layers.composer2d.enabled", atoi(propValue) == 1); if (sUsingOMTC) { sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1), gfxASurface::ImageFormatRGB24); } } }
void LayerManagerOGL::SetWorldTransform(const gfxMatrix& aMatrix) { NS_ASSERTION(aMatrix.PreservesAxisAlignedRectangles(), "SetWorldTransform only accepts matrices that satisfy PreservesAxisAlignedRectangles"); NS_ASSERTION(!aMatrix.HasNonIntegerScale(), "SetWorldTransform only accepts matrices with integer scale"); mWorldMatrix = aMatrix; }
/* static */ bool HwcUtils::PrepareLayerRects(nsIntRect aVisible, const gfxMatrix& aTransform, nsIntRect aClip, nsIntRect aBufferRect, hwc_rect_t* aSourceCrop, hwc_rect_t* aVisibleRegionScreen) { gfxRect visibleRect(aVisible); gfxRect clip(aClip); gfxRect visibleRectScreen = aTransform.TransformBounds(visibleRect); // |clip| is guaranteed to be integer visibleRectScreen.IntersectRect(visibleRectScreen, clip); if (visibleRectScreen.IsEmpty()) { LOGD("Skip layer"); return false; } gfxMatrix inverse(aTransform); inverse.Invert(); gfxRect crop = inverse.TransformBounds(visibleRectScreen); //clip to buffer size crop.IntersectRect(crop, aBufferRect); crop.Round(); if (crop.IsEmpty()) { LOGD("Skip layer"); return false; } //propagate buffer clipping back to visible rect visibleRectScreen = aTransform.TransformBounds(crop); visibleRectScreen.Round(); // Map from layer space to buffer space crop -= aBufferRect.TopLeft(); aSourceCrop->left = crop.x; aSourceCrop->top = crop.y; aSourceCrop->right = crop.x + crop.width; aSourceCrop->bottom = crop.y + crop.height; aVisibleRegionScreen->left = visibleRectScreen.x; aVisibleRegionScreen->top = visibleRectScreen.y; aVisibleRegionScreen->right = visibleRectScreen.x + visibleRectScreen.width; aVisibleRegionScreen->bottom = visibleRectScreen.y + visibleRectScreen.height; return true; }
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; } if (!PrepareLayerList(aRoot, mScreenRect, gfxMatrix(), aGLWorldTransform)) { LOGD("Render aborted. Nothing was drawn to the screen"); return false; } if (mHwc->set(mHwc, mDpy, mSur, mList)) { LOGE("Hardware device failed to render"); return false; } LOGD("Frame rendered"); return true; }
/* static */ bool HwcUtils::CalculateClipRect(const gfxMatrix& aTransform, const nsIntRect* aLayerClip, nsIntRect aParentClip, nsIntRect* aRenderClip) { *aRenderClip = aParentClip; if (!aLayerClip) { return true; } if (aLayerClip->IsEmpty()) { return false; } nsIntRect clip = *aLayerClip; gfxRect r(clip); gfxRect trClip = aTransform.TransformBounds(r); trClip.Round(); gfxUtils::GfxRectToIntRect(trClip, &clip); aRenderClip->IntersectRect(*aRenderClip, clip); return true; }
/* static */ bool HwcUtils::PrepareVisibleRegion(const nsIntRegion& aVisible, const gfxMatrix& aTransform, nsIntRect aClip, nsIntRect aBufferRect, RectVector* aVisibleRegionScreen) { nsIntRegionRectIterator rect(aVisible); bool isVisible = false; while (const nsIntRect* visibleRect = rect.Next()) { hwc_rect_t visibleRectScreen; gfxRect screenRect; screenRect.IntersectRect(gfxRect(*visibleRect), aBufferRect); screenRect = aTransform.TransformBounds(screenRect); screenRect.IntersectRect(screenRect, aClip); screenRect.Round(); if (screenRect.IsEmpty()) { continue; } visibleRectScreen.left = screenRect.x; visibleRectScreen.top = screenRect.y; visibleRectScreen.right = screenRect.XMost(); visibleRectScreen.bottom = screenRect.YMost(); aVisibleRegionScreen->push_back(visibleRectScreen); isVisible = true; } return isVisible; }
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); }
gfxMatrix nsSVGGraphicElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix, TransformTypes aWhich) const { NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(), "Skipping eUserSpaceToParent transforms makes no sense"); gfxMatrix result(aMatrix); if (aWhich == eChildToUserSpace) { // We don't have anything to prepend. // eChildToUserSpace is not the common case, which is why we return // 'result' to benefit from NRVO rather than returning aMatrix before // creating 'result'. return result; } NS_ABORT_IF_FALSE(aWhich == eAllTransforms || aWhich == eUserSpaceToParent, "Unknown TransformTypes"); // animateMotion's resulting transform is supposed to apply *on top of* // any transformations from the |transform| attribute. So since we're // PRE-multiplying, we need to apply the animateMotion transform *first*. if (mAnimateMotionTransform) { result.PreMultiply(*mAnimateMotionTransform); } if (mTransforms) { result.PreMultiply(mTransforms->GetAnimValue().GetConsolidationMatrix()); } return result; }
bool gfxSurfaceDrawable::Draw(gfxContext* aContext, const gfxRect& aFillRect, bool aRepeat, const GraphicsFilter& aFilter, const gfxMatrix& aTransform) { nsRefPtr<gfxPattern> pattern = new gfxPattern(mSurface); if (aRepeat) { pattern->SetExtend(gfxPattern::EXTEND_REPEAT); pattern->SetFilter(aFilter); } else { 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 = GraphicsFilter::FILTER_FAST; } nsRefPtr<gfxASurface> currentTarget = aContext->CurrentSurface(); gfxMatrix deviceSpaceToImageSpace = DeviceToImageTransform(aContext, aTransform); PreparePatternForUntiledDrawing(pattern, deviceSpaceToImageSpace, currentTarget, filter); } pattern->SetMatrix(gfxMatrix(aTransform).Multiply(mTransform)); aContext->NewPath(); aContext->SetPattern(pattern); aContext->Rectangle(aFillRect); aContext->Fill(); return true; }
/** * Returns the app unit canvas bounds of a userspace rect. * * @param aToCanvas Transform from userspace to canvas device space. */ static nsRect ToCanvasBounds(const gfxRect &aUserspaceRect, const gfxMatrix &aToCanvas, const nsPresContext *presContext) { return nsLayoutUtils::RoundGfxRectToAppRect( aToCanvas.TransformBounds(aUserspaceRect), presContext->AppUnitsPerDevPixel()); }
/* [noscript] void draw(in gfxContext aContext, * in gfxGraphicsFilter aFilter, * [const] in gfxMatrix aUserSpaceToImageSpace, * [const] in gfxRect aFill, * [const] in nsIntRect aSubimage, * [const] in nsIntSize aViewportSize, * in PRUint32 aFlags); */ NS_IMETHODIMP VectorImage::Draw(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, const gfxRect& aFill, const nsIntRect& aSubimage, const nsIntSize& aViewportSize, PRUint32 aFlags) { NS_ENSURE_ARG_POINTER(aContext); if (mError || !mIsFullyLoaded) return NS_ERROR_FAILURE; if (mIsDrawing) { NS_WARNING("Refusing to make re-entrant call to VectorImage::Draw"); return NS_ERROR_FAILURE; } mIsDrawing = true; if (aViewportSize != mLastRenderedSize) { mSVGDocumentWrapper->UpdateViewportBounds(aViewportSize); mLastRenderedSize = aViewportSize; } mSVGDocumentWrapper->FlushImageTransformInvalidation(); nsIntSize imageSize = mHaveRestrictedRegion ? mRestrictedRegion.Size() : aViewportSize; // XXXdholbert Do we need to convert image size from // CSS pixels to dev pixels here? (is gfxCallbackDrawable's 2nd arg in dev // pixels?) gfxIntSize imageSizeGfx(imageSize.width, imageSize.height); // Based on imgFrame::Draw gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill); gfxRect imageRect(0, 0, imageSize.width, imageSize.height); gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height); nsRefPtr<gfxDrawingCallback> cb = new SVGDrawingCallback(mSVGDocumentWrapper, mHaveRestrictedRegion ? mRestrictedRegion : nsIntRect(nsIntPoint(0, 0), aViewportSize), aFlags); nsRefPtr<gfxDrawable> drawable = new gfxCallbackDrawable(cb, imageSizeGfx); gfxUtils::DrawPixelSnapped(aContext, drawable, aUserSpaceToImageSpace, subimage, sourceRect, imageRect, aFill, gfxASurface::ImageFormatARGB32, aFilter); mIsDrawing = false; return NS_OK; }
// EXTEND_PAD won't help us here; we have to create a temporary surface to hold // the subimage of pixels we're allowed to sample. static already_AddRefed<gfxDrawable> CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable, gfxContext* aContext, const gfxMatrix& aUserSpaceToImageSpace, const gfxRect& aSourceRect, const gfxRect& aSubimage, const gfxImageFormat aFormat) { PROFILER_LABEL("gfxUtils", "CreateSamplingRestricedDrawable"); gfxRect userSpaceClipExtents = aContext->GetClipExtents(); // This isn't optimal --- if aContext has a rotation then GetClipExtents // will have to do a bounding-box computation, and TransformBounds might // too, so we could get a better result if we computed image space clip // extents in one go --- but it doesn't really matter and this is easier // to understand. gfxRect imageSpaceClipExtents = aUserSpaceToImageSpace.TransformBounds(userSpaceClipExtents); // Inflate by one pixel because bilinear filtering will sample at most // one pixel beyond the computed image pixel coordinate. imageSpaceClipExtents.Inflate(1.0); gfxRect needed = imageSpaceClipExtents.Intersect(aSourceRect); needed = needed.Intersect(aSubimage); needed.RoundOut(); // if 'needed' is empty, nothing will be drawn since aFill // must be entirely outside the clip region, so it doesn't // matter what we do here, but we should avoid trying to // create a zero-size surface. if (needed.IsEmpty()) return nullptr; nsRefPtr<gfxDrawable> drawable; gfxIntSize size(int32_t(needed.Width()), int32_t(needed.Height())); nsRefPtr<gfxImageSurface> image = aDrawable->GetAsImageSurface(); if (image && gfxRect(0, 0, image->GetSize().width, image->GetSize().height).Contains(needed)) { nsRefPtr<gfxASurface> temp = image->GetSubimage(needed); drawable = new gfxSurfaceDrawable(temp, size, gfxMatrix().Translate(-needed.TopLeft())); } else { mozilla::RefPtr<mozilla::gfx::DrawTarget> target = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(ToIntSize(size), ImageFormatToSurfaceFormat(aFormat)); if (!target) { return nullptr; } nsRefPtr<gfxContext> tmpCtx = new gfxContext(target); tmpCtx->SetOperator(OptimalFillOperator()); aDrawable->Draw(tmpCtx, needed - needed.TopLeft(), true, GraphicsFilter::FILTER_FAST, gfxMatrix().Translate(needed.TopLeft())); drawable = new gfxSurfaceDrawable(target, size, gfxMatrix().Translate(-needed.TopLeft())); } return drawable.forget(); }
SVGBBox nsSVGForeignObjectFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace, PRUint32 aFlags) { nsSVGForeignObjectElement *content = static_cast<nsSVGForeignObjectElement*>(mContent); float x, y, w, h; content->GetAnimatedLengthValues(&x, &y, &w, &h, nsnull); if (w < 0.0f) w = 0.0f; if (h < 0.0f) h = 0.0f; if (aToBBoxUserspace.IsSingular()) { // XXX ReportToConsole return SVGBBox(); } return aToBBoxUserspace.TransformBounds(gfxRect(0.0, 0.0, w, h)); }
gfxRect nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace) { if (aToBBoxUserspace.IsSingular()) { // XXX ReportToConsole return gfxRect(0.0, 0.0, 0.0, 0.0); } gfxContext context(nsSVGUtils::GetThebesComputationalSurface()); GeneratePath(&context, &aToBBoxUserspace); context.IdentityMatrix(); return context.GetUserPathExtent(); }
gfxRect nsSVGForeignObjectFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace) { NS_ASSERTION(!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), "Should not be calling this on a non-display child"); nsSVGForeignObjectElement *content = static_cast<nsSVGForeignObjectElement*>(mContent); float x, y, w, h; content->GetAnimatedLengthValues(&x, &y, &w, &h, nsnull); if (w < 0.0f) w = 0.0f; if (h < 0.0f) h = 0.0f; if (aToBBoxUserspace.IsSingular()) { // XXX ReportToConsole return gfxRect(0.0, 0.0, 0.0, 0.0); } return aToBBoxUserspace.TransformBounds(gfxRect(0.0, 0.0, w, h)); }
void nsSVGUtils::SetClipRect(gfxContext *aContext, const gfxMatrix &aCTM, const gfxRect &aRect) { if (aCTM.IsSingular()) return; gfxMatrix oldMatrix = aContext->CurrentMatrix(); aContext->Multiply(aCTM); aContext->Clip(aRect); aContext->SetMatrix(oldMatrix); }
bool gfxSurfaceDrawable::Draw(gfxContext* aContext, const gfxRect& aFillRect, bool aRepeat, const GraphicsFilter& aFilter, const gfxMatrix& aTransform) { nsRefPtr<gfxPattern> pattern; if (mDrawTarget) { if (aContext->IsCairo()) { nsRefPtr<gfxASurface> source = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget); pattern = new gfxPattern(source); } else { RefPtr<SourceSurface> source = mDrawTarget->Snapshot(); pattern = new gfxPattern(source, Matrix()); } } else if (mSourceSurface) { pattern = new gfxPattern(mSourceSurface, Matrix()); } else { pattern = new gfxPattern(mSurface); } if (aRepeat) { pattern->SetExtend(gfxPattern::EXTEND_REPEAT); pattern->SetFilter(aFilter); } else { 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 = GraphicsFilter::FILTER_FAST; } nsRefPtr<gfxASurface> currentTarget = aContext->CurrentSurface(); gfxMatrix deviceSpaceToImageSpace = DeviceToImageTransform(aContext, aTransform); PreparePatternForUntiledDrawing(pattern, deviceSpaceToImageSpace, currentTarget, filter); } pattern->SetMatrix(gfxMatrix(aTransform).Multiply(mTransform)); aContext->NewPath(); aContext->SetPattern(pattern); aContext->Rectangle(aFillRect); aContext->Fill(); // clear the pattern so that the snapshot is released before the // drawable is destroyed aContext->SetDeviceColor(gfxRGBA(0.0, 0.0, 0.0, 0.0)); return true; }
// EXTEND_PAD won't help us here; we have to create a temporary surface to hold // the subimage of pixels we're allowed to sample. static already_AddRefed<gfxDrawable> CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable, gfxContext* aContext, const gfxMatrix& aUserSpaceToImageSpace, const gfxRect& aSourceRect, const gfxRect& aSubimage, const gfxImageSurface::gfxImageFormat aFormat) { SAMPLE_LABEL("gfxUtils", "CreateSamplingRestricedDrawable"); gfxRect userSpaceClipExtents = aContext->GetClipExtents(); // This isn't optimal --- if aContext has a rotation then GetClipExtents // will have to do a bounding-box computation, and TransformBounds might // too, so we could get a better result if we computed image space clip // extents in one go --- but it doesn't really matter and this is easier // to understand. gfxRect imageSpaceClipExtents = aUserSpaceToImageSpace.TransformBounds(userSpaceClipExtents); // Inflate by one pixel because bilinear filtering will sample at most // one pixel beyond the computed image pixel coordinate. imageSpaceClipExtents.Inflate(1.0); gfxRect needed = imageSpaceClipExtents.Intersect(aSourceRect); needed = needed.Intersect(aSubimage); needed.RoundOut(); // if 'needed' is empty, nothing will be drawn since aFill // must be entirely outside the clip region, so it doesn't // matter what we do here, but we should avoid trying to // create a zero-size surface. if (needed.IsEmpty()) return nullptr; gfxIntSize size(PRInt32(needed.Width()), PRInt32(needed.Height())); nsRefPtr<gfxASurface> temp = gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, gfxASurface::ContentFromFormat(aFormat)); if (!temp || temp->CairoStatus()) return nullptr; nsRefPtr<gfxContext> tmpCtx = new gfxContext(temp); tmpCtx->SetOperator(OptimalFillOperator()); aDrawable->Draw(tmpCtx, needed - needed.TopLeft(), true, gfxPattern::FILTER_FAST, gfxMatrix().Translate(needed.TopLeft())); nsRefPtr<gfxPattern> resultPattern = new gfxPattern(temp); if (!resultPattern) return nullptr; nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(temp, size, gfxMatrix().Translate(-needed.TopLeft())); return drawable.forget(); }
void nsSVGUtils::CompositeSurfaceMatrix(gfxContext *aContext, gfxASurface *aSurface, const gfxMatrix &aCTM, float aOpacity) { if (aCTM.IsSingular()) return; aContext->Save(); aContext->Multiply(aCTM); aContext->SetSource(aSurface); aContext->Paint(aOpacity); aContext->Restore(); }
NS_IMETHODIMP ClippedImage::Draw(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, const gfxRect& aFill, const nsIntRect& aSubimage, const nsIntSize& aViewportSize, const SVGImageContext* aSVGContext, uint32_t aWhichFrame, uint32_t aFlags) { if (!ShouldClip()) { return InnerImage()->Draw(aContext, aFilter, aUserSpaceToImageSpace, aFill, aSubimage, aViewportSize, aSVGContext, aWhichFrame, aFlags); } // Check for tiling. If we need to tile then we need to create a // gfxCallbackDrawable to handle drawing for us. gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill); if (MustCreateSurface(aContext, aUserSpaceToImageSpace, sourceRect, aSubimage, aFlags)) { // Create a temporary surface containing a single tile of this image. // GetFrame will call DrawSingleTile internally. nsRefPtr<gfxASurface> surface; GetFrameInternal(aViewportSize, aSVGContext, aWhichFrame, aFlags, getter_AddRefs(surface)); NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); // Create a drawable from that surface. nsRefPtr<gfxSurfaceDrawable> drawable = new gfxSurfaceDrawable(surface, gfxIntSize(mClip.width, mClip.height)); // Draw. gfxRect imageRect(0, 0, mClip.width, mClip.height); gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height); gfxUtils::DrawPixelSnapped(aContext, drawable, aUserSpaceToImageSpace, subimage, sourceRect, imageRect, aFill, gfxASurface::ImageFormatARGB32, aFilter); return NS_OK; } // Determine the appropriate subimage for the inner image. nsIntRect innerSubimage(aSubimage); innerSubimage.MoveBy(mClip.x, mClip.y); innerSubimage.Intersect(mClip); return DrawSingleTile(aContext, aFilter, aUserSpaceToImageSpace, aFill, innerSubimage, aViewportSize, aSVGContext, aWhichFrame, aFlags); }
PRBool nsSVGUtils::HitTestRect(const gfxMatrix &aMatrix, float aRX, float aRY, float aRWidth, float aRHeight, float aX, float aY) { if (aMatrix.IsSingular()) { return PR_FALSE; } gfxContext ctx(gfxPlatform::GetPlatform()->ScreenReferenceSurface()); ctx.SetMatrix(aMatrix); ctx.NewPath(); ctx.Rectangle(gfxRect(aRX, aRY, aRWidth, aRHeight)); ctx.IdentityMatrix(); return ctx.PointInFill(gfxPoint(aX, aY)); }
void nsSVGUtils::CompositePatternMatrix(gfxContext *aContext, gfxPattern *aPattern, const gfxMatrix &aCTM, float aWidth, float aHeight, float aOpacity) { if (aCTM.IsSingular()) return; aContext->Save(); SetClipRect(aContext, aCTM, gfxRect(0, 0, aWidth, aHeight)); aContext->Multiply(aCTM); aContext->SetPattern(aPattern); aContext->Paint(aOpacity); aContext->Restore(); }
static bool AccumulateLayerTransforms2D(Layer* aLayer, Layer* aAncestor, gfxMatrix& aMatrix) { // Accumulate the transforms between this layer and the subtree root layer. for (Layer* l = aLayer; l && l != aAncestor; l = l->GetParent()) { gfxMatrix l2D; if (!GetBaseTransform2D(l, &l2D)) { return false; } aMatrix.Multiply(l2D); } return true; }
static nsIntRect MapDeviceRectToFilterSpace(const gfxMatrix& aMatrix, const gfxIntSize& aFilterSize, const nsIntRect* aDeviceRect) { nsIntRect rect(0, 0, aFilterSize.width, aFilterSize.height); if (aDeviceRect) { gfxRect r = aMatrix.TransformBounds(gfxRect(aDeviceRect->x, aDeviceRect->y, aDeviceRect->width, aDeviceRect->height)); r.RoundOut(); nsIntRect intRect; if (gfxUtils::GfxRectToIntRect(r, &intRect)) { rect = intRect; } } return rect; }
nsresult ClippedImage::DrawSingleTile(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, const gfxRect& aFill, const nsIntRect& aSubimage, const nsIntSize& aViewportSize, const SVGImageContext* aSVGContext, uint32_t aWhichFrame, uint32_t aFlags) { MOZ_ASSERT(!MustCreateSurface(aContext, aUserSpaceToImageSpace, aUserSpaceToImageSpace.Transform(aFill), aSubimage - nsIntPoint(mClip.x, mClip.y), aFlags), "DrawSingleTile shouldn't need to create a surface"); // Make the viewport reflect the original image's size. nsIntSize viewportSize(aViewportSize); int32_t imgWidth, imgHeight; if (NS_SUCCEEDED(InnerImage()->GetWidth(&imgWidth)) && NS_SUCCEEDED(InnerImage()->GetHeight(&imgHeight))) { viewportSize = nsIntSize(imgWidth, imgHeight); } else { MOZ_ASSERT(false, "If ShouldClip() led us to draw then we should never get here"); } // Add a translation to the transform to reflect the clipping region. gfxMatrix transform(aUserSpaceToImageSpace); transform.Multiply(gfxMatrix().Translate(gfxPoint(mClip.x, mClip.y))); // "Clamp the source rectangle" to the clipping region's width and height. // Really, this means modifying the transform to get the results we want. gfxRect sourceRect = transform.Transform(aFill); if (sourceRect.width > mClip.width || sourceRect.height > mClip.height) { gfxMatrix clampSource; clampSource.Translate(gfxPoint(sourceRect.x, sourceRect.y)); clampSource.Scale(ClampFactor(sourceRect.width, mClip.width), ClampFactor(sourceRect.height, mClip.height)); clampSource.Translate(gfxPoint(-sourceRect.x, -sourceRect.y)); transform.Multiply(clampSource); } return InnerImage()->Draw(aContext, aFilter, transform, aFill, aSubimage, viewportSize, aSVGContext, aWhichFrame, aFlags); }
NS_IMETHODIMP nsScreenGonk::SetRotation(PRUint32 aRotation) { if (!(ROTATION_0_DEG <= aRotation && aRotation <= ROTATION_270_DEG)) return NS_ERROR_ILLEGAL_VALUE; if (sScreenRotation == aRotation) return NS_OK; sScreenRotation = aRotation; sRotationMatrix.Reset(); switch ((aRotation + sPhysicalScreenRotation) % (360 / 90)) { case nsIScreen::ROTATION_0_DEG: sVirtualBounds = gScreenBounds; break; case nsIScreen::ROTATION_90_DEG: sRotationMatrix.Translate(gfxPoint(gScreenBounds.width, 0)); sRotationMatrix.Rotate(M_PI / 2); sVirtualBounds = nsIntRect(0, 0, gScreenBounds.height, gScreenBounds.width); break; case nsIScreen::ROTATION_180_DEG: sRotationMatrix.Translate(gfxPoint(gScreenBounds.width, gScreenBounds.height)); sRotationMatrix.Rotate(M_PI); sVirtualBounds = gScreenBounds; break; case nsIScreen::ROTATION_270_DEG: sRotationMatrix.Translate(gfxPoint(0, gScreenBounds.height)); sRotationMatrix.Rotate(M_PI * 3 / 2); sVirtualBounds = nsIntRect(0, 0, gScreenBounds.height, gScreenBounds.width); break; default: MOZ_NOT_REACHED("Unknown rotation"); break; } for (unsigned int i = 0; i < sTopWindows.Length(); i++) sTopWindows[i]->Resize(sVirtualBounds.width, sVirtualBounds.height, !i); nsAppShell::NotifyScreenRotation(); return NS_OK; }
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; }
NS_IMETHODIMP DynamicImage::Draw(gfxContext* aContext, GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, const gfxRect& aFill, const nsIntRect& aSubimage, const nsIntSize& aViewportSize, const SVGImageContext* aSVGContext, uint32_t aWhichFrame, uint32_t aFlags) { gfxIntSize drawableSize(mDrawable->Size()); gfxRect imageRect(0, 0, drawableSize.width, drawableSize.height); gfxRect sourceRect = aUserSpaceToImageSpace.TransformBounds(aFill); gfxUtils::DrawPixelSnapped(aContext, mDrawable, aUserSpaceToImageSpace, aSubimage, sourceRect, imageRect, aFill, SurfaceFormat::B8G8R8A8, aFilter, aFlags); return NS_OK; }
/** * Converts an nsRect that is relative to a filtered frame's origin (i.e. the * top-left corner of its border box) into filter space. * Returns the entire filter region (a rect the width/height of aFilterRes) if * aFrameRect is null, or if the result is too large to be stored in an * nsIntRect. */ static nsIntRect MapFrameRectToFilterSpace(const nsRect* aRect, int32_t aAppUnitsPerCSSPx, const gfxMatrix& aFrameSpaceInCSSPxToFilterSpace, const gfxIntSize& aFilterRes) { nsIntRect rect(0, 0, aFilterRes.width, aFilterRes.height); if (aRect) { if (aRect->IsEmpty()) { return nsIntRect(); } gfxRect rectInCSSPx = nsLayoutUtils::RectToGfxRect(*aRect, aAppUnitsPerCSSPx); gfxRect rectInFilterSpace = aFrameSpaceInCSSPxToFilterSpace.TransformBounds(rectInCSSPx); rectInFilterSpace.RoundOut(); nsIntRect intRect; if (gfxUtils::GfxRectToIntRect(rectInFilterSpace, &intRect)) { rect = intRect; } } return rect; }
/* 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; }