1 /* -*- Mode: C++; tab-width: 8; 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 _NS_DEVICECONTEXT_H_
7 #define _NS_DEVICECONTEXT_H_
8 
9 #include <stdint.h>                   // for uint32_t
10 #include <sys/types.h>                // for int32_t
11 #include "gfxTypes.h"                 // for gfxFloat
12 #include "gfxFont.h"                  // for gfxFont::Orientation
13 #include "mozilla/Assertions.h"       // for MOZ_ASSERT_HELPER2
14 #include "mozilla/RefPtr.h"           // for RefPtr
15 #include "nsCOMPtr.h"                 // for nsCOMPtr
16 #include "nsCoord.h"                  // for nscoord
17 #include "nsError.h"                  // for nsresult
18 #include "nsISupports.h"              // for NS_INLINE_DECL_REFCOUNTING
19 #include "nsMathUtils.h"              // for NS_round
20 #include "nscore.h"                   // for char16_t, nsAString
21 #include "mozilla/AppUnits.h"         // for AppUnits
22 #include "nsFontMetrics.h"            // for nsFontMetrics::Params
23 #include "mozilla/gfx/PrintTarget.h"  // for PrintTarget::PageDoneCallback
24 
25 class gfxContext;
26 class gfxTextPerfMetrics;
27 class gfxUserFontSet;
28 struct nsFont;
29 class nsFontCache;
30 class nsAtom;
31 class nsIDeviceContextSpec;
32 class nsIScreen;
33 class nsIScreenManager;
34 class nsIWidget;
35 struct nsRect;
36 
37 class nsDeviceContext final {
38  public:
39   typedef mozilla::gfx::PrintTarget PrintTarget;
40 
41   nsDeviceContext();
42 
43   NS_INLINE_DECL_REFCOUNTING(nsDeviceContext)
44 
45   /**
46    * Initialize the device context from a widget
47    * @param aWidget a widget to initialize the device context from
48    * @return error status
49    */
50   nsresult Init(nsIWidget* aWidget);
51 
52   /*
53    * Initialize the font cache if it hasn't been initialized yet.
54    * (Needed for stylo)
55    */
56   void InitFontCache();
57 
58   void UpdateFontCacheUserFonts(gfxUserFontSet* aUserFontSet);
59 
60   /**
61    * Initialize the device context from a device context spec
62    * @param aDevSpec the specification of the printing device
63    * @return error status
64    */
65   nsresult InitForPrinting(nsIDeviceContextSpec* aDevSpec);
66 
67   /**
68    * Create a rendering context and initialize it.  Only call this
69    * method on device contexts that were initialized for printing.
70    *
71    * @return the new rendering context (guaranteed to be non-null)
72    */
73   already_AddRefed<gfxContext> CreateRenderingContext();
74 
75   /**
76    * Create a reference rendering context and initialize it.  Only call this
77    * method on device contexts that were initialized for printing.
78    *
79    * @return the new rendering context.
80    */
81   already_AddRefed<gfxContext> CreateReferenceRenderingContext();
82 
83   /**
84    * Gets the number of app units in one device pixel; this number
85    * is usually a factor of AppUnitsPerCSSPixel(), although that is
86    * not guaranteed.
87    */
AppUnitsPerDevPixel()88   int32_t AppUnitsPerDevPixel() const { return mAppUnitsPerDevPixel; }
89 
90   /**
91    * Convert device pixels which is used for gfx/thebes to nearest
92    * (rounded) app units
93    */
GfxUnitsToAppUnits(gfxFloat aGfxUnits)94   nscoord GfxUnitsToAppUnits(gfxFloat aGfxUnits) const {
95     return nscoord(NS_round(aGfxUnits * AppUnitsPerDevPixel()));
96   }
97 
98   /**
99    * Convert app units to device pixels which is used for gfx/thebes.
100    */
AppUnitsToGfxUnits(nscoord aAppUnits)101   gfxFloat AppUnitsToGfxUnits(nscoord aAppUnits) const {
102     return gfxFloat(aAppUnits) / AppUnitsPerDevPixel();
103   }
104 
105   /**
106    * Gets the number of app units in one physical inch; this is the
107    * device's DPI times AppUnitsPerDevPixel().
108    */
AppUnitsPerPhysicalInch()109   int32_t AppUnitsPerPhysicalInch() const { return mAppUnitsPerPhysicalInch; }
110 
111   /**
112    * Get the ratio of app units to dev pixels that would be used at unit
113    * (100%) full zoom.
114    */
AppUnitsPerDevPixelAtUnitFullZoom()115   int32_t AppUnitsPerDevPixelAtUnitFullZoom() const {
116     return mAppUnitsPerDevPixelAtUnitFullZoom;
117   }
118 
119   /**
120    * Get the nsFontMetrics that describe the properties of
121    * an nsFont.
122    * @param aFont font description to obtain metrics for
123    */
124   already_AddRefed<nsFontMetrics> GetMetricsFor(
125       const nsFont& aFont, const nsFontMetrics::Params& aParams);
126 
127   /**
128    * Notification when a font metrics instance created for this device is
129    * about to be deleted
130    */
131   nsresult FontMetricsDeleted(const nsFontMetrics* aFontMetrics);
132 
133   /**
134    * Attempt to free up resources by flushing out any fonts no longer
135    * referenced by anything other than the font cache itself.
136    * @return error status
137    */
138   nsresult FlushFontCache();
139 
140   /**
141    * Return the bit depth of the device.
142    */
143   nsresult GetDepth(uint32_t& aDepth);
144 
145   /**
146    * Get the size of the displayable area of the output device
147    * in app units.
148    * @param aWidth out parameter for width
149    * @param aHeight out parameter for height
150    * @return error status
151    */
152   nsresult GetDeviceSurfaceDimensions(nscoord& aWidth, nscoord& aHeight);
153 
154   /**
155    * Get the size of the content area of the output device in app
156    * units.  This corresponds on a screen device, for instance, to
157    * the entire screen.
158    * @param aRect out parameter for full rect. Position (x,y) will
159    *              be (0,0) or relative to the primary monitor if
160    *              this is not the primary.
161    * @return error status
162    */
163   nsresult GetRect(nsRect& aRect);
164 
165   /**
166    * Get the size of the content area of the output device in app
167    * units.  This corresponds on a screen device, for instance, to
168    * the area reported by GetDeviceSurfaceDimensions, minus the
169    * taskbar (Windows) or menubar (Macintosh).
170    * @param aRect out parameter for client rect. Position (x,y) will
171    *              be (0,0) adjusted for any upper/left non-client
172    *              space if present or relative to the primary
173    *              monitor if this is not the primary.
174    * @return error status
175    */
176   nsresult GetClientRect(nsRect& aRect);
177 
178   /**
179    * Returns true if we're currently between BeginDocument() and
180    * EndDocument() calls.
181    */
IsCurrentlyPrintingDocument()182   bool IsCurrentlyPrintingDocument() const { return mIsCurrentlyPrintingDoc; }
183 
184   /**
185    * Inform the output device that output of a document is beginning
186    * Used for print related device contexts. Must be matched 1:1 with
187    * EndDocument() or AbortDocument().
188    *
189    * @param aTitle - title of Document
190    * @param aPrintToFileName - name of file to print to, if empty then don't
191    *                           print to file
192    * @param aStartPage - starting page number (must be greater than zero)
193    * @param aEndPage - ending page number (must be less than or
194    * equal to number of pages)
195    *
196    * @return error status
197    */
198   nsresult BeginDocument(const nsAString& aTitle,
199                          const nsAString& aPrintToFileName, int32_t aStartPage,
200                          int32_t aEndPage);
201 
202   /**
203    * Inform the output device that output of a document is ending.
204    * Used for print related device contexts. Must be matched 1:1 with
205    * BeginDocument()
206    * @return error status
207    */
208   nsresult EndDocument();
209 
210   /**
211    * Inform the output device that output of a document is being aborted.
212    * Must be matched 1:1 with BeginDocument()
213    * @return error status
214    */
215   nsresult AbortDocument();
216 
217   /**
218    * Inform the output device that output of a page is beginning
219    * Used for print related device contexts. Must be matched 1:1 with
220    * EndPage() and within a BeginDocument()/EndDocument() pair.
221    * @return error status
222    */
223   nsresult BeginPage();
224 
225   /**
226    * Inform the output device that output of a page is ending
227    * Used for print related device contexts. Must be matched 1:1 with
228    * BeginPage() and within a BeginDocument()/EndDocument() pair.
229    * @return error status
230    */
231   nsresult EndPage();
232 
233   /**
234    * Check to see if the DPI has changed, or impose a new DPI scale value.
235    * @param  aScale - If non-null, the default (unzoomed) CSS to device pixel
236    *                  scale factor will be returned here; and if it is > 0.0
237    *                  on input, the given value will be used instead of
238    *                  getting it from the widget (if any). This is used to
239    *                  allow subdocument contexts to inherit the resolution
240    *                  setting of their parent.
241    * @return whether there was actually a change in the DPI (whether
242    *         AppUnitsPerDevPixel() or AppUnitsPerPhysicalInch()
243    *         changed)
244    */
245   bool CheckDPIChange(double* aScale = nullptr);
246 
247   /**
248    * Set the full zoom factor: all lengths are multiplied by this factor
249    * when we convert them to device pixels. Returns whether the ratio of
250    * app units to dev pixels changed because of the zoom factor.
251    */
252   bool SetFullZoom(float aScale);
253 
254   /**
255    * Returns the page full zoom factor applied.
256    */
GetFullZoom()257   float GetFullZoom() const { return mFullZoom; }
258 
259   /**
260    * True if this device context was created for printing.
261    */
262   bool IsPrinterContext();
263 
264   mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale();
265 
266  private:
267   // Private destructor, to discourage deletion outside of Release():
268   ~nsDeviceContext();
269 
270   /**
271    * Implementation shared by CreateRenderingContext and
272    * CreateReferenceRenderingContext.
273    */
274   already_AddRefed<gfxContext> CreateRenderingContextCommon(
275       bool aWantReferenceContext);
276 
277   void SetDPI(double* aScale = nullptr);
278   void ComputeClientRectUsingScreen(nsRect* outRect);
279   void ComputeFullAreaUsingScreen(nsRect* outRect);
280   void FindScreen(nsIScreen** outScreen);
281 
282   // Return false if the surface is not right
283   bool CalcPrintingSize();
284   void UpdateAppUnitsForFullZoom();
285 
286   nscoord mWidth;
287   nscoord mHeight;
288   int32_t mAppUnitsPerDevPixel;
289   int32_t mAppUnitsPerDevPixelAtUnitFullZoom;
290   int32_t mAppUnitsPerPhysicalInch;
291   float mFullZoom;
292   float mPrintingScale;
293   gfxPoint mPrintingTranslate;
294 
295   RefPtr<nsFontCache> mFontCache;
296   nsCOMPtr<nsIWidget> mWidget;
297   nsCOMPtr<nsIScreenManager> mScreenManager;
298   nsCOMPtr<nsIDeviceContextSpec> mDeviceContextSpec;
299   RefPtr<PrintTarget> mPrintTarget;
300   bool mIsCurrentlyPrintingDoc;
301 #ifdef DEBUG
302   bool mIsInitialized;
303 #endif
304 };
305 
306 #endif /* _NS_DEVICECONTEXT_H_ */
307