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