Bug 1310165 - Add a GetReferenceDrawTarget overload to PrintTargetCG to return a PDF CGContext backed DrawTarget. r=mstange, a=jcristau
authorJonathan Watt <jwatt@jwatt.org>
Thu, 17 Nov 2016 16:25:19 +0000
changeset 352613 684cee0b8da4a84513de5e06b123d22f3eb0368d
parent 352612 2e61912b522799a315b45da0f648f76ad4874287
child 352614 7b584df373c7e3cf06dd4a74db3357e06ecfd00b
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange, jcristau
bugs1310165
milestone52.0a2
Bug 1310165 - Add a GetReferenceDrawTarget overload to PrintTargetCG to return a PDF CGContext backed DrawTarget. r=mstange, a=jcristau
gfx/thebes/PrintTargetCG.cpp
gfx/thebes/PrintTargetCG.h
--- a/gfx/thebes/PrintTargetCG.cpp
+++ b/gfx/thebes/PrintTargetCG.cpp
@@ -62,10 +62,59 @@ PrintTargetCG::CreateOrNull(CGContextRef
   }
 
   // The new object takes ownership of our surface reference.
   RefPtr<PrintTargetCG> target = new PrintTargetCG(surface, aSize);
 
   return target.forget();
 }
 
+static size_t
+PutBytesNull(void* info, const void* buffer, size_t count)
+{
+  return count;
+}
+
+already_AddRefed<DrawTarget>
+PrintTargetCG::GetReferenceDrawTarget(DrawEventRecorder* aRecorder)
+{
+  if (!mRefDT) {
+    const IntSize size(1, 1);
+
+    CGDataConsumerCallbacks callbacks = {PutBytesNull, nullptr};
+    CGDataConsumerRef consumer = CGDataConsumerCreate(nullptr, &callbacks);
+    CGContextRef pdfContext = CGPDFContextCreate(consumer, nullptr, nullptr);
+    CGDataConsumerRelease(consumer);
+
+    cairo_surface_t* similar =
+      cairo_quartz_surface_create_for_cg_context(
+        pdfContext, size.width, size.height);
+
+    CGContextRelease(pdfContext);
+
+    if (cairo_surface_status(similar)) {
+      return nullptr;
+    }
+
+    RefPtr<DrawTarget> dt =
+      Factory::CreateDrawTargetForCairoSurface(similar, size);
+
+    // The DT addrefs the surface, so we need drop our own reference to it:
+    cairo_surface_destroy(similar);
+
+    if (!dt || !dt->IsValid()) {
+      return nullptr;
+    }
+
+    if (aRecorder) {
+      dt = CreateRecordingDrawTarget(aRecorder, dt);
+      if (!dt || !dt->IsValid()) {
+        return nullptr;
+      }
+    }
+
+    mRefDT = dt.forget();
+  }
+  return do_AddRef(mRefDT);
+}
+
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/thebes/PrintTargetCG.h
+++ b/gfx/thebes/PrintTargetCG.h
@@ -23,16 +23,19 @@ class PrintTargetCG final : public Print
 {
 public:
   static already_AddRefed<PrintTargetCG>
   CreateOrNull(const IntSize& aSize, gfxImageFormat aFormat);
 
   static already_AddRefed<PrintTargetCG>
   CreateOrNull(CGContextRef aContext, const IntSize& aSize);
 
+  virtual already_AddRefed<DrawTarget>
+  GetReferenceDrawTarget(DrawEventRecorder* aRecorder) final;
+
 private:
   PrintTargetCG(cairo_surface_t* aCairoSurface,
                 const IntSize& aSize);
 };
 
 } // namespace gfx
 } // namespace mozilla