PrintTarget.h (5796B)
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. 34 virtual nsresult BeginPrinting(const nsAString& aTitle, 35 const nsAString& aPrintToFileName, 36 int32_t aStartPage, int32_t aEndPage) { 37 return NS_OK; 38 } 39 virtual nsresult EndPrinting() { return NS_OK; } 40 virtual nsresult AbortPrinting() { 41 #ifdef DEBUG 42 mHasActivePage = false; 43 #endif 44 return NS_OK; 45 } 46 /** 47 * Note: not all print devices implement mixed page sizing. Most PrintTarget 48 * subclasses will ignore `aSizeInPoints`. 49 */ 50 virtual nsresult BeginPage(const IntSize& aSizeInPoints) { 51 #ifdef DEBUG 52 MOZ_ASSERT(!mHasActivePage, "Missing EndPage() call"); 53 mHasActivePage = true; 54 #endif 55 return NS_OK; 56 } 57 virtual nsresult EndPage() { 58 #ifdef DEBUG 59 mHasActivePage = false; 60 #endif 61 return NS_OK; 62 } 63 64 /** 65 * Releases the resources used by this PrintTarget. Typically this should be 66 * called after calling EndPrinting(). Calling this more than once is 67 * allowed, but subsequent calls are a no-op. 68 * 69 * Note that any DrawTarget obtained from this PrintTarget will no longer be 70 * useful after this method has been called. 71 */ 72 virtual void Finish(); 73 74 const IntSize& GetSize() const { return mSize; } 75 76 /** 77 * Makes a DrawTarget to draw the printer output to, or returns null on 78 * failure. 79 * 80 * If aRecorder is passed a recording DrawTarget will be created instead of 81 * the type of DrawTarget that would normally be returned for a particular 82 * subclass of this class. This argument is only intended to be used in 83 * the e10s content process if printing output can't otherwise be transfered 84 * over to the parent process using the normal DrawTarget type. 85 * 86 * NOTE: this should only be called between BeginPage()/EndPage() calls, and 87 * the returned DrawTarget should not be drawn to after EndPage() has been 88 * called. 89 * 90 * XXX For consistency with the old code this takes a size parameter even 91 * though we already have the size passed to our subclass's CreateOrNull 92 * factory methods. The size passed to the factory method comes from 93 * nsIDeviceContextSpec::MakePrintTarget overrides, whereas the size 94 * passed to us comes from nsDeviceContext::CreateRenderingContext. In at 95 * least one case (nsDeviceContextSpecAndroid::MakePrintTarget) these are 96 * different. At some point we should align the two sources and get rid of 97 * this method's size parameter. 98 * 99 * XXX For consistency with the old code this returns a new DrawTarget for 100 * each call. Perhaps we can create and cache a DrawTarget in our subclass's 101 * CreateOrNull factory methods and return that on each call? Currently that 102 * seems to cause Mochitest failures on Windows though, which coincidentally 103 * is the only platform where we get passed an aRecorder. Probably the 104 * issue is that we get called more than once with a different aRecorder, so 105 * storing one recording DrawTarget for our lifetime doesn't currently work. 106 * 107 * XXX Could we pass aRecorder to our subclass's CreateOrNull factory methods? 108 * We'd need to check that our consumers always pass the same aRecorder for 109 * our entire lifetime. 110 * 111 * XXX Once PrintTargetThebes is removed this can become non-virtual. 112 * 113 * XXX In the long run, this class and its sub-classes should be converted to 114 * use STL classes and mozilla::RefCounted<> so the can be moved to Moz2D. 115 * 116 * TODO: Consider adding a SetDPI method that calls 117 * cairo_surface_set_fallback_resolution. 118 */ 119 virtual already_AddRefed<DrawTarget> MakeDrawTarget( 120 const IntSize& aSize, DrawEventRecorder* aRecorder = nullptr); 121 122 /** 123 * Returns a reference DrawTarget. Unlike MakeDrawTarget, this method is not 124 * restricted to being called between BeginPage()/EndPage() calls, and the 125 * returned DrawTarget is still valid to use after EndPage() has been called. 126 */ 127 virtual already_AddRefed<DrawTarget> GetReferenceDrawTarget(); 128 129 static void AdjustPrintJobNameForIPP(const nsAString& aJobName, 130 nsCString& aAdjustedJobName); 131 static void AdjustPrintJobNameForIPP(const nsAString& aJobName, 132 nsString& aAdjustedJobName); 133 134 protected: 135 // Only created via subclass's constructors 136 explicit PrintTarget(cairo_surface_t* aCairoSurface, const IntSize& aSize); 137 138 // Protected because we're refcounted 139 virtual ~PrintTarget(); 140 141 static already_AddRefed<DrawTarget> CreateRecordingDrawTarget( 142 DrawEventRecorder* aRecorder, DrawTarget* aDrawTarget); 143 144 cairo_surface_t* mCairoSurface; 145 RefPtr<DrawTarget> mRefDT; // reference DT 146 147 IntSize mSize; 148 bool mIsFinished; 149 #ifdef DEBUG 150 bool mHasActivePage; 151 #endif 152 }; 153 154 } // namespace gfx 155 } // namespace mozilla 156 157 #endif /* MOZILLA_GFX_PRINTTARGET_H */