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