bool PaintFrameCallback::operator()(gfxContext* aContext, const gfxRect& aFillRect, const gfxPattern::GraphicsFilter& aFilter, const gfxMatrix& aTransform) { if (mFrame->GetStateBits() & NS_FRAME_DRAWING_AS_PAINTSERVER) return false; mFrame->AddStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER); nsRenderingContext context; context.Init(mFrame->PresContext()->DeviceContext(), aContext); aContext->Save(); // Clip to aFillRect so that we don't paint outside. aContext->NewPath(); aContext->Rectangle(aFillRect); aContext->Clip(); gfxMatrix savedMatrix(aContext->CurrentMatrix()); aContext->Multiply(gfxMatrix(aTransform).Invert()); // nsLayoutUtils::PaintFrame will anchor its painting at mFrame. But we want // to have it anchored at the top left corner of the bounding box of all of // mFrame's continuations. So we add a translation transform. nsRect bbox = nsSVGIntegrationUtils::GetNonSVGUserSpace(mFrame); PRInt32 appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); gfxPoint offset = gfxPoint(bbox.x, bbox.y) / appUnitsPerDevPixel; aContext->Multiply(gfxMatrix().Translate(-offset)); gfxSize paintServerSize = gfxSize(mPaintServerSize.width, mPaintServerSize.height) / mFrame->PresContext()->AppUnitsPerDevPixel(); // nsLayoutUtils::PaintFrame wants to render with paintServerSize, but we // want it to render with mRenderSize, so we need to set up a scale transform. gfxFloat scaleX = mRenderSize.width / paintServerSize.width; gfxFloat scaleY = mRenderSize.height / paintServerSize.height; gfxMatrix scaleMatrix = gfxMatrix().Scale(scaleX, scaleY); aContext->Multiply(scaleMatrix); // Draw. nsRect dirty(bbox.x, bbox.y, mPaintServerSize.width, mPaintServerSize.height); nsLayoutUtils::PaintFrame(&context, mFrame, dirty, NS_RGBA(0, 0, 0, 0), nsLayoutUtils::PAINT_IN_TRANSFORM | nsLayoutUtils::PAINT_ALL_CONTINUATIONS); aContext->SetMatrix(savedMatrix); aContext->Restore(); mFrame->RemoveStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER); return true; }
bool PaintFrameCallback::operator()(gfxContext* aContext, const gfxRect& aFillRect, const Filter& aFilter, const gfxMatrix& aTransform) { if (mFrame->GetStateBits() & NS_FRAME_DRAWING_AS_PAINTSERVER) return false; mFrame->AddStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER); aContext->Save(); // Clip to aFillRect so that we don't paint outside. aContext->NewPath(); aContext->Rectangle(aFillRect); aContext->Clip(); gfxMatrix invmatrix = aTransform; if (!invmatrix.Invert()) { return false; } aContext->Multiply(invmatrix); // nsLayoutUtils::PaintFrame will anchor its painting at mFrame. But we want // to have it anchored at the top left corner of the bounding box of all of // mFrame's continuations. So we add a translation transform. int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); nsPoint offset = GetOffsetToBoundingBox(mFrame); gfxPoint devPxOffset = gfxPoint(offset.x, offset.y) / appUnitsPerDevPixel; aContext->Multiply(gfxMatrix::Translation(devPxOffset)); gfxSize paintServerSize = gfxSize(mPaintServerSize.width, mPaintServerSize.height) / mFrame->PresContext()->AppUnitsPerDevPixel(); // nsLayoutUtils::PaintFrame wants to render with paintServerSize, but we // want it to render with mRenderSize, so we need to set up a scale transform. gfxFloat scaleX = mRenderSize.width / paintServerSize.width; gfxFloat scaleY = mRenderSize.height / paintServerSize.height; aContext->Multiply(gfxMatrix::Scaling(scaleX, scaleY)); // Draw. nsRect dirty(-offset.x, -offset.y, mPaintServerSize.width, mPaintServerSize.height); uint32_t flags = nsLayoutUtils::PAINT_IN_TRANSFORM; if (mFlags & nsSVGIntegrationUtils::FLAG_SYNC_DECODE_IMAGES) { flags |= nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES; } nsRenderingContext context(aContext); nsLayoutUtils::PaintFrame(&context, mFrame, dirty, NS_RGBA(0, 0, 0, 0), flags); nsIFrame* currentFrame = mFrame; while ((currentFrame = currentFrame->GetNextContinuation()) != nullptr) { offset = currentFrame->GetOffsetToCrossDoc(mFrame); devPxOffset = gfxPoint(offset.x, offset.y) / appUnitsPerDevPixel; aContext->Save(); aContext->Multiply(gfxMatrix::Scaling(1/scaleX, 1/scaleY)); aContext->Multiply(gfxMatrix::Translation(devPxOffset)); aContext->Multiply(gfxMatrix::Scaling(scaleX, scaleY)); nsLayoutUtils::PaintFrame(&context, currentFrame, dirty - offset, NS_RGBA(0, 0, 0, 0), flags); aContext->Restore(); } aContext->Restore(); mFrame->RemoveStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER); return true; }