Bug 1280324, part 1 - Add functionality to the PrintTarget sub-classes to return reference DrawTargets. r=edwin
authorJonathan Watt <jwatt@jwatt.org>
Thu, 27 Oct 2016 19:24:12 +0100
changeset 431554 bcb5f7b49427929996c0b8425cb9220f0c07e7bc
parent 431553 4a6cd6dff941517c15ce49226f74e438f83983e8
child 431555 620893e272d615af3192524b9ca959890f9a2c24
push id34062
push usercykesiopka.bmo@gmail.com
push dateSun, 30 Oct 2016 05:36:21 +0000
reviewersedwin
bugs1280324
milestone52.0a1
Bug 1280324, part 1 - Add functionality to the PrintTarget sub-classes to return reference DrawTargets. r=edwin
gfx/thebes/PrintTarget.cpp
gfx/thebes/PrintTarget.h
gfx/thebes/PrintTargetThebes.cpp
gfx/thebes/PrintTargetThebes.h
--- a/gfx/thebes/PrintTarget.cpp
+++ b/gfx/thebes/PrintTarget.cpp
@@ -71,16 +71,46 @@ PrintTarget::MakeDrawTarget(const IntSiz
       return nullptr;
     }
   }
 
   return dt.forget();
 }
 
 already_AddRefed<DrawTarget>
+PrintTarget::GetReferenceDrawTarget()
+{
+  if (!mRefDT) {
+    IntSize size(1, 1);
+
+    cairo_surface_t* surface =
+      cairo_surface_create_similar(mCairoSurface,
+                                   cairo_surface_get_content(mCairoSurface),
+                                   size.width, size.height);
+
+    if (cairo_surface_status(surface)) {
+      return nullptr;
+    }
+
+    RefPtr<DrawTarget> dt =
+      Factory::CreateDrawTargetForCairoSurface(surface, size);
+
+    // The DT addrefs the surface, so we need drop our own reference to it:
+    cairo_surface_destroy(surface);
+
+    if (!dt || !dt->IsValid()) {
+      return nullptr;
+    }
+
+    mRefDT = dt.forget();
+  }
+  return do_AddRef(mRefDT);
+}
+
+already_AddRefed<DrawTarget>
 PrintTarget::CreateRecordingDrawTarget(DrawEventRecorder* aRecorder,
                                        DrawTarget* aDrawTarget)
 {
   MOZ_ASSERT(aRecorder);
   MOZ_ASSERT(aDrawTarget);
 
   RefPtr<DrawTarget> dt;
 
--- a/gfx/thebes/PrintTarget.h
+++ b/gfx/thebes/PrintTarget.h
@@ -106,29 +106,38 @@ public:
    *
    * TODO: Consider adding a SetDPI method that calls
    * cairo_surface_set_fallback_resolution.
    */
   virtual already_AddRefed<DrawTarget>
   MakeDrawTarget(const IntSize& aSize,
                  DrawEventRecorder* aRecorder = nullptr);
 
+  /**
+   * Returns a reference DrawTarget. Unlike MakeDrawTarget, this method is not
+   * restricted to being called between BeginPage()/EndPage() calls, and the
+   * returned DrawTarget it is still valid to use after EndPage() has been
+   * called.
+   */
+  virtual already_AddRefed<DrawTarget> GetReferenceDrawTarget();
+
 protected:
 
   // Only created via subclass's constructors
   explicit PrintTarget(cairo_surface_t* aCairoSurface, const IntSize& aSize);
 
   // Protected because we're refcounted
   virtual ~PrintTarget();
 
   already_AddRefed<DrawTarget>
   CreateRecordingDrawTarget(DrawEventRecorder* aRecorder,
                             DrawTarget* aDrawTarget);
 
   cairo_surface_t* mCairoSurface;
+  RefPtr<DrawTarget> mRefDT; // reference DT
   IntSize mSize;
   bool mIsFinished;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_PRINTTARGET_H */
--- a/gfx/thebes/PrintTargetThebes.cpp
+++ b/gfx/thebes/PrintTargetThebes.cpp
@@ -47,16 +47,30 @@ PrintTargetThebes::MakeDrawTarget(const 
     if (!dt || !dt->IsValid()) {
       return nullptr;
     }
   }
 
   return dt.forget();
 }
 
+already_AddRefed<DrawTarget>
+PrintTargetThebes::GetReferenceDrawTarget()
+{
+  if (!mRefDT) {
+    RefPtr<gfx::DrawTarget> dt =
+      gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mGfxSurface, mSize);
+    if (!dt || !dt->IsValid()) {
+      return nullptr;
+    }
+    mRefDT = dt->CreateSimilarDrawTarget(IntSize(1,1), dt->GetFormat());
+  }
+  return do_AddRef(mRefDT);
+}
+
 nsresult
 PrintTargetThebes::BeginPrinting(const nsAString& aTitle,
                                  const nsAString& aPrintToFileName)
 {
   return mGfxSurface->BeginPrinting(aTitle, aPrintToFileName);
 }
 
 nsresult
--- a/gfx/thebes/PrintTargetThebes.h
+++ b/gfx/thebes/PrintTargetThebes.h
@@ -36,16 +36,18 @@ public:
   virtual nsresult BeginPage() override;
   virtual nsresult EndPage() override;
   virtual void Finish() override;
 
   virtual already_AddRefed<DrawTarget>
   MakeDrawTarget(const IntSize& aSize,
                  DrawEventRecorder* aRecorder = nullptr) override;
 
+  virtual already_AddRefed<DrawTarget> GetReferenceDrawTarget() final;
+
 private:
 
   // Only created via CreateOrNull
   explicit PrintTargetThebes(gfxASurface* aSurface);
 
   RefPtr<gfxASurface> mGfxSurface;
 };