Bug 1156742 Part 13: Create a Moz2D PrintTranslator. r=bas
authorBob Owen <bobowencode@gmail.com>
Tue, 05 Jan 2016 10:08:57 +0000
changeset 278501 6c13b972933639299aceef19b6541e9412ef9242
parent 278500 57d758c8ac22c640e955fba23b6802582169f78f
child 278502 f17ecf3189bd4a25e806a71ed4ae2be40e82440f
push id29852
push userkwierso@gmail.com
push dateWed, 06 Jan 2016 00:03:27 +0000
treeherdermozilla-central@dd6d447fc6e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas
bugs1156742
milestone46.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1156742 Part 13: Create a Moz2D PrintTranslator. r=bas A better solution to the ScaledFonts issue comes in Part 24.
gfx/2d/DrawEventRecorder.cpp
gfx/2d/RecordedEvent.h
gfx/2d/moz.build
layout/printing/PrintTranslator.cpp
layout/printing/PrintTranslator.h
layout/printing/moz.build
--- a/gfx/2d/DrawEventRecorder.cpp
+++ b/gfx/2d/DrawEventRecorder.cpp
@@ -7,18 +7,16 @@
 #include "PathRecording.h"
 #include "RecordingTypes.h"
 
 namespace mozilla {
 namespace gfx {
 
 using namespace std;
 
-const uint32_t kMagicInt = 0xc001feed;
-
 DrawEventRecorderPrivate::DrawEventRecorderPrivate(std::ostream *aStream)
   : mOutputStream(aStream)
 {
 }
 
 void
 DrawEventRecorderPrivate::WriteHeader()
 {
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -13,16 +13,18 @@
 #include <vector>
 
 namespace mozilla {
 namespace gfx {
 
 struct PathOp;
 class PathRecording;
 
+const uint32_t kMagicInt = 0xc001feed;
+
 // A change in major revision means a change in event binary format, causing
 // loss of backwards compatibility. Old streams will not work in a player
 // using a newer major revision. And new streams will not work in a player
 // using an older major revision.
 const uint16_t kMajorRevision = 3;
 // A change in minor revision means additions of new events. New streams will
 // not play in older players.
 const uint16_t kMinorRevision = 2;
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -35,16 +35,17 @@ EXPORTS.mozilla.gfx += [
     'Matrix.h',
     'MatrixFwd.h',
     'NumericTools.h',
     'PathHelpers.h',
     'PatternHelpers.h',
     'Point.h',
     'Quaternion.h',
     'RecordedEvent.h',
+    'RecordingTypes.h',
     'Rect.h',
     'Scale.h',
     'ScaleFactor.h',
     'ScaleFactors2D.h',
     'SourceSurfaceCairo.h',
     'SourceSurfaceRawData.h',
     'StackArray.h',
     'Tools.h',
new file mode 100644
--- /dev/null
+++ b/layout/printing/PrintTranslator.cpp
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "PrintTranslator.h"
+
+#include "gfxContext.h"
+#include "nsDeviceContext.h"
+#include "mozilla/gfx/RecordedEvent.h"
+#include "mozilla/gfx/RecordingTypes.h"
+#include "mozilla/UniquePtr.h"
+
+using namespace mozilla::gfx;
+
+namespace mozilla {
+namespace layout {
+
+PrintTranslator::PrintTranslator(nsDeviceContext* aDeviceContext)
+  : mDeviceContext(aDeviceContext)
+{
+  RefPtr<gfxContext> context = mDeviceContext->CreateRenderingContext();
+  mBaseDT = context->GetDrawTarget();
+}
+
+bool
+PrintTranslator::TranslateRecording(std::istream& aRecording)
+{
+  uint32_t magicInt;
+  ReadElement(aRecording, magicInt);
+  if (magicInt != mozilla::gfx::kMagicInt) {
+    return false;
+  }
+
+  uint16_t majorRevision;
+  ReadElement(aRecording, majorRevision);
+  if (majorRevision != kMajorRevision) {
+    return false;
+  }
+
+  uint16_t minorRevision;
+  ReadElement(aRecording, minorRevision);
+  if (minorRevision > kMinorRevision) {
+    return false;
+  }
+
+  int32_t eventType;
+  ReadElement(aRecording, eventType);
+  while (aRecording.good()) {
+    UniquePtr<RecordedEvent> recordedEvent(
+      RecordedEvent::LoadEventFromStream(aRecording,
+      static_cast<RecordedEvent::EventType>(eventType)));
+
+    // Make sure that the whole event was read from the stream successfully.
+    if (!aRecording.good()) {
+      return false;
+    }
+
+    recordedEvent->PlayEvent(this);
+    ReadElement(aRecording, eventType);
+  }
+
+  return true;
+}
+
+already_AddRefed<DrawTarget>
+PrintTranslator::CreateDrawTarget(ReferencePtr aRefPtr,
+                                  const gfx::IntSize &aSize,
+                                  gfx::SurfaceFormat aFormat)
+{
+  RefPtr<gfxContext> context = mDeviceContext->CreateRenderingContext();
+  if (!context) {
+    NS_WARNING("Failed to create rendering context for print.");
+    return nullptr;
+  }
+
+  RefPtr<DrawTarget> drawTarget = context->GetDrawTarget();
+  AddDrawTarget(aRefPtr, drawTarget);
+  return drawTarget.forget();
+}
+
+FontType
+PrintTranslator::GetDesiredFontType()
+{
+  switch (mBaseDT->GetBackendType()) {
+    case BackendType::DIRECT2D:
+      return FontType::DWRITE;
+    case BackendType::CAIRO:
+      return FontType::CAIRO;
+    case BackendType::SKIA:
+      return FontType::SKIA;
+    case BackendType::COREGRAPHICS:
+    case BackendType::COREGRAPHICS_ACCELERATED:
+      return FontType::COREGRAPHICS;
+    default:
+      return FontType::CAIRO;
+  }
+}
+
+} // namespace layout
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/printing/PrintTranslator.h
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layout_PrintTranslator_h
+#define mozilla_layout_PrintTranslator_h
+
+#include <istream>
+
+#include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/Filters.h"
+#include "mozilla/gfx/RecordedEvent.h"
+#include "mozilla/unused.h"
+#include "nsRefPtrHashtable.h"
+
+class nsDeviceContext;
+
+namespace mozilla {
+namespace layout {
+
+using gfx::Translator;
+using gfx::ReferencePtr;
+using gfx::DrawTarget;
+using gfx::Path;
+using gfx::SourceSurface;
+using gfx::FilterNode;
+using gfx::GradientStops;
+using gfx::ScaledFont;
+
+class PrintTranslator final : public Translator
+{
+public:
+  explicit PrintTranslator(nsDeviceContext* aDeviceContext);
+
+  bool TranslateRecording(std::istream& aRecording);
+
+  DrawTarget* LookupDrawTarget(ReferencePtr aRefPtr) final
+  {
+    return mDrawTargets.GetWeak(aRefPtr);
+  }
+
+  Path* LookupPath(ReferencePtr aRefPtr) final
+  {
+    return mPaths.GetWeak(aRefPtr);
+  }
+
+  SourceSurface* LookupSourceSurface(ReferencePtr aRefPtr) final
+  {
+    return mSourceSurfaces.GetWeak(aRefPtr);
+  }
+
+  FilterNode* LookupFilterNode(ReferencePtr aRefPtr) final
+  {
+    return mFilterNodes.GetWeak(aRefPtr);
+  }
+
+  GradientStops* LookupGradientStops(ReferencePtr aRefPtr) final
+  {
+    return mGradientStops.GetWeak(aRefPtr);
+  }
+
+  ScaledFont* LookupScaledFont(ReferencePtr aRefPtr) final
+  {
+    return mScaledFonts.GetWeak(aRefPtr);
+  }
+
+  void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) final
+  {
+    mDrawTargets.Put(aRefPtr, aDT);
+  }
+
+  void AddPath(ReferencePtr aRefPtr, Path *aPath) final
+  {
+    mPaths.Put(aRefPtr, aPath);
+  }
+
+  void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface *aSurface) final
+  {
+    mSourceSurfaces.Put(aRefPtr, aSurface);
+  }
+
+  void AddFilterNode(ReferencePtr aRefPtr, FilterNode *aFilter) final
+  {
+    mFilterNodes.Put(aRefPtr, aFilter);
+  }
+
+  void AddGradientStops(ReferencePtr aRefPtr, GradientStops *aStops) final
+  {
+    mGradientStops.Put(aRefPtr, aStops);
+  }
+
+  void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) final
+  {
+    mScaledFonts.Put(aRefPtr, aScaledFont);
+    Unused << mSavedScaledFonts.PutEntry(aScaledFont);
+  }
+
+  void RemoveDrawTarget(ReferencePtr aRefPtr) final
+  {
+    mDrawTargets.Remove(aRefPtr);
+  }
+
+  void RemovePath(ReferencePtr aRefPtr) final
+  {
+    mPaths.Remove(aRefPtr);
+  }
+
+  void RemoveSourceSurface(ReferencePtr aRefPtr) final
+  {
+    mSourceSurfaces.Remove(aRefPtr);
+  }
+
+  void RemoveFilterNode(ReferencePtr aRefPtr) final
+  {
+    mFilterNodes.Remove(aRefPtr);
+  }
+
+  void RemoveGradientStops(ReferencePtr aRefPtr) final
+  {
+    mGradientStops.Remove(aRefPtr);
+  }
+
+  void RemoveScaledFont(ReferencePtr aRefPtr) final
+  {
+    mScaledFonts.Remove(aRefPtr);
+  }
+
+  void ClearSavedFonts() { mSavedScaledFonts.Clear(); }
+
+  already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
+                                                const gfx::IntSize &aSize,
+                                                gfx::SurfaceFormat aFormat) final;
+
+  mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
+
+  mozilla::gfx::FontType GetDesiredFontType() final;
+
+private:
+  RefPtr<nsDeviceContext> mDeviceContext;
+  RefPtr<DrawTarget> mBaseDT;
+
+  nsRefPtrHashtable<nsPtrHashKey<void>, DrawTarget> mDrawTargets;
+  nsRefPtrHashtable<nsPtrHashKey<void>, Path> mPaths;
+  nsRefPtrHashtable<nsPtrHashKey<void>, SourceSurface> mSourceSurfaces;
+  nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;
+  nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops;
+  nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts;
+
+  // We keep an extra reference to each scaled font, because they currently
+  // always get removed immediately. These can be cleared using ClearSavedFonts,
+  // when we know that things have been flushed to the print device.
+  nsTHashtable<nsRefPtrHashKey<ScaledFont>> mSavedScaledFonts;
+};
+
+} // namespace layout
+} // namespace mozilla
+
+#endif // mozilla_layout_PrintTranslator_h
--- a/layout/printing/moz.build
+++ b/layout/printing/moz.build
@@ -20,16 +20,17 @@ XPIDL_MODULE = 'layout_printing'
 UNIFIED_SOURCES += [
     'ipc/RemotePrintJobChild.cpp',
     'ipc/RemotePrintJobParent.cpp',
     'nsPagePrintTimer.cpp',
     'nsPrintData.cpp',
     'nsPrintEngine.cpp',
     'nsPrintObject.cpp',
     'nsPrintPreviewListener.cpp',
+    'PrintTranslator.cpp',
 ]
 
 IPDL_SOURCES = [
     'ipc/PRemotePrintJob.ipdl',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')