1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef MOZILLA_GFX_PRINTTARGET_H 7 #define MOZILLA_GFX_PRINTTARGET_H 8 9 #include <functional> 10 11 #include "mozilla/RefPtr.h" 12 #include "mozilla/gfx/2D.h" 13 #include "nsISupportsImpl.h" 14 #include "nsStringFwd.h" 15 16 namespace mozilla { 17 namespace gfx { 18 19 class DrawEventRecorder; 20 21 /** 22 * A class that is used to draw output that is to be sent to a printer or print 23 * preview. 24 * 25 * This class wraps a cairo_surface_t* and provides access to it via a 26 * DrawTarget. The various checkpointing methods manage the state of the 27 * platform specific cairo_surface_t*. 28 */ 29 class PrintTarget { 30 public: 31 NS_INLINE_DECL_REFCOUNTING(PrintTarget); 32 33 /// Must be matched 1:1 by an EndPrinting/AbortPrinting call. BeginPrinting(const nsAString & aTitle,const nsAString & aPrintToFileName,int32_t aStartPage,int32_t aEndPage)34 virtual nsresult BeginPrinting(const nsAString& aTitle, 35 const nsAString& aPrintToFileName, 36 int32_t aStartPage, int32_t aEndPage) { 37 return NS_OK; 38 } EndPrinting()39 virtual nsresult EndPrinting() { return NS_OK; } AbortPrinting()40 virtual nsresult AbortPrinting() { 41 #ifdef DEBUG 42 mHasActivePage = false; 43 #endif 44 return NS_OK; 45 } BeginPage()46 virtual nsresult BeginPage() { 47 #ifdef DEBUG 48 MOZ_ASSERT(!mHasActivePage, "Missing EndPage() call"); 49 mHasActivePage = true; 50 #endif 51 return NS_OK; 52 } EndPage()53 virtual nsresult EndPage() { 54 #ifdef DEBUG 55 mHasActivePage = false; 56 #endif 57 return NS_OK; 58 } 59 60 /** 61 * Releases the resources used by this PrintTarget. Typically this should be 62 * called after calling EndPrinting(). Calling this more than once is 63 * allowed, but subsequent calls are a no-op. 64 * 65 * Note that any DrawTarget obtained from this PrintTarget will no longer be 66 * useful after this method has been called. 67 */ 68 virtual void Finish(); 69 70 /** 71 * Returns true if to print landscape our consumers must apply a 90 degrees 72 * rotation to our DrawTarget. 73 */ RotateNeededForLandscape()74 virtual bool RotateNeededForLandscape() const { return false; } 75 GetSize()76 const IntSize& GetSize() const { return mSize; } 77 78 /** 79 * Makes a DrawTarget to draw the printer output to, or returns null on 80 * failure. 81 * 82 * If aRecorder is passed a recording DrawTarget will be created instead of 83 * the type of DrawTarget that would normally be returned for a particular 84 * subclass of this class. This argument is only intended to be used in 85 * the e10s content process if printing output can't otherwise be transfered 86 * over to the parent process using the normal DrawTarget type. 87 * 88 * NOTE: this should only be called between BeginPage()/EndPage() calls, and 89 * the returned DrawTarget should not be drawn to after EndPage() has been 90 * called. 91 * 92 * XXX For consistency with the old code this takes a size parameter even 93 * though we already have the size passed to our subclass's CreateOrNull 94 * factory methods. The size passed to the factory method comes from 95 * nsIDeviceContextSpec::MakePrintTarget overrides, whereas the size 96 * passed to us comes from nsDeviceContext::CreateRenderingContext. In at 97 * least one case (nsDeviceContextSpecAndroid::MakePrintTarget) these are 98 * different. At some point we should align the two sources and get rid of 99 * this method's size parameter. 100 * 101 * XXX For consistency with the old code this returns a new DrawTarget for 102 * each call. Perhaps we can create and cache a DrawTarget in our subclass's 103 * CreateOrNull factory methods and return that on each call? Currently that 104 * seems to cause Mochitest failures on Windows though, which coincidentally 105 * is the only platform where we get passed an aRecorder. Probably the 106 * issue is that we get called more than once with a different aRecorder, so 107 * storing one recording DrawTarget for our lifetime doesn't currently work. 108 * 109 * XXX Could we pass aRecorder to our subclass's CreateOrNull factory methods? 110 * We'd need to check that our consumers always pass the same aRecorder for 111 * our entire lifetime. 112 * 113 * XXX Once PrintTargetThebes is removed this can become non-virtual. 114 * 115 * XXX In the long run, this class and its sub-classes should be converted to 116 * use STL classes and mozilla::RefCounted<> so the can be moved to Moz2D. 117 * 118 * TODO: Consider adding a SetDPI method that calls 119 * cairo_surface_set_fallback_resolution. 120 */ 121 virtual already_AddRefed<DrawTarget> MakeDrawTarget( 122 const IntSize& aSize, DrawEventRecorder* aRecorder = nullptr); 123 124 /** 125 * Returns a reference DrawTarget. Unlike MakeDrawTarget, this method is not 126 * restricted to being called between BeginPage()/EndPage() calls, and the 127 * returned DrawTarget is still valid to use after EndPage() has been called. 128 */ 129 virtual already_AddRefed<DrawTarget> GetReferenceDrawTarget(); 130 131 static void AdjustPrintJobNameForIPP(const nsAString& aJobName, 132 nsCString& aAdjustedJobName); 133 static void AdjustPrintJobNameForIPP(const nsAString& aJobName, 134 nsString& aAdjustedJobName); 135 136 protected: 137 // Only created via subclass's constructors 138 explicit PrintTarget(cairo_surface_t* aCairoSurface, const IntSize& aSize); 139 140 // Protected because we're refcounted 141 virtual ~PrintTarget(); 142 143 static already_AddRefed<DrawTarget> CreateRecordingDrawTarget( 144 DrawEventRecorder* aRecorder, DrawTarget* aDrawTarget); 145 146 cairo_surface_t* mCairoSurface; 147 RefPtr<DrawTarget> mRefDT; // reference DT 148 149 IntSize mSize; 150 bool mIsFinished; 151 #ifdef DEBUG 152 bool mHasActivePage; 153 #endif 154 }; 155 156 } // namespace gfx 157 } // namespace mozilla 158 159 #endif /* MOZILLA_GFX_PRINTTARGET_H */ 160