void gfxContext::PushGroupAndCopyBackground(gfxContentType content) { IntRect clipExtents; if (mDT->GetFormat() != SurfaceFormat::B8G8R8X8) { gfxRect clipRect = GetRoundOutDeviceClipExtents(this); clipExtents = IntRect(clipRect.x, clipRect.y, clipRect.width, clipRect.height); } if ((mDT->GetFormat() == SurfaceFormat::B8G8R8X8 || mDT->GetOpaqueRect().Contains(clipExtents)) && !mDT->GetUserData(&sDontUseAsSourceKey)) { DrawTarget *oldDT = mDT; RefPtr<SourceSurface> source = mDT->Snapshot(); Point oldDeviceOffset = CurrentState().deviceOffset; PushNewDT(gfxContentType::COLOR); if (oldDT == mDT) { // Creating new DT failed. return; } Point offset = CurrentState().deviceOffset - oldDeviceOffset; Rect surfRect(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height)); Rect sourceRect = surfRect + offset; mDT->SetTransform(Matrix()); // XXX: It's really sad that we have to do this (for performance). // Once DrawTarget gets a PushLayer API we can implement this within // DrawTargetTiled. if (source->GetType() == SurfaceType::TILED) { SnapshotTiled *sourceTiled = static_cast<SnapshotTiled*>(source.get()); for (uint32_t i = 0; i < sourceTiled->mSnapshots.size(); i++) { Rect tileSourceRect = sourceRect.Intersect(Rect(sourceTiled->mOrigins[i].x, sourceTiled->mOrigins[i].y, sourceTiled->mSnapshots[i]->GetSize().width, sourceTiled->mSnapshots[i]->GetSize().height)); if (tileSourceRect.IsEmpty()) { continue; } Rect tileDestRect = tileSourceRect - offset; tileSourceRect -= sourceTiled->mOrigins[i]; mDT->DrawSurface(sourceTiled->mSnapshots[i], tileDestRect, tileSourceRect); } } else { mDT->DrawSurface(source, surfRect, sourceRect); } mDT->SetOpaqueRect(oldDT->GetOpaqueRect()); PushClipsToDT(mDT); mDT->SetTransform(GetDTTransform()); return; } PushGroup(content); }