Bug 1744135 Part 2: Annotate macOS font loading with font name if a crash happens...
[gecko.git] / gfx / thebes / gfxContext.h
blobfedb74d16153acc1ea75bfbe1da0c2734f73c894
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/. */
6 #ifndef GFX_CONTEXT_H
7 #define GFX_CONTEXT_H
9 #include "gfxTypes.h"
11 #include "gfxPoint.h"
12 #include "gfxRect.h"
13 #include "gfxMatrix.h"
14 #include "gfxPattern.h"
15 #include "nsTArray.h"
17 #include "mozilla/EnumSet.h"
18 #include "mozilla/gfx/2D.h"
20 typedef struct _cairo cairo_t;
21 class GlyphBufferAzure;
23 namespace mozilla {
24 namespace gfx {
25 struct RectCornerRadii;
26 } // namespace gfx
27 namespace layout {
28 class TextDrawTarget;
29 } // namespace layout
30 } // namespace mozilla
32 class ClipExporter;
34 /**
35 * This is the main class for doing actual drawing. It is initialized using
36 * a surface and can be drawn on. It manages various state information like
37 * a current transformation matrix (CTM), a current path, current color,
38 * etc.
40 * All drawing happens by creating a path and then stroking or filling it.
41 * The functions like Rectangle and Arc do not do any drawing themselves.
42 * When a path is drawn (stroked or filled), it is filled/stroked with a
43 * pattern set by SetPattern or SetColor.
45 * Note that the gfxContext takes coordinates in device pixels,
46 * as opposed to app units.
48 class gfxContext final {
49 typedef mozilla::gfx::CapStyle CapStyle;
50 typedef mozilla::gfx::CompositionOp CompositionOp;
51 typedef mozilla::gfx::JoinStyle JoinStyle;
52 typedef mozilla::gfx::FillRule FillRule;
53 typedef mozilla::gfx::Float Float;
54 typedef mozilla::gfx::Path Path;
55 typedef mozilla::gfx::Pattern Pattern;
56 typedef mozilla::gfx::Rect Rect;
57 typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
58 typedef mozilla::gfx::Size Size;
60 NS_INLINE_DECL_REFCOUNTING(gfxContext)
62 public:
63 /**
64 * Initialize this context from a DrawTarget.
65 * Strips any transform from aTarget.
66 * aTarget will be flushed in the gfxContext's destructor.
67 * If aTarget is null or invalid, nullptr is returned. The caller
68 * is responsible for handling this scenario as appropriate.
70 static already_AddRefed<gfxContext> CreateOrNull(
71 mozilla::gfx::DrawTarget* aTarget,
72 const mozilla::gfx::Point& aDeviceOffset = mozilla::gfx::Point());
74 /**
75 * Create a new gfxContext wrapping aTarget and preserving aTarget's
76 * transform. Note that the transform is moved from aTarget to the resulting
77 * gfxContext, aTarget will no longer have its transform.
78 * If aTarget is null or invalid, nullptr is returned. The caller
79 * is responsible for handling this scenario as appropriate.
81 static already_AddRefed<gfxContext> CreatePreservingTransformOrNull(
82 mozilla::gfx::DrawTarget* aTarget);
84 mozilla::gfx::DrawTarget* GetDrawTarget() { return mDT; }
86 /**
87 * Returns the DrawTarget if it's actually a TextDrawTarget.
89 mozilla::layout::TextDrawTarget* GetTextDrawer();
91 /**
92 ** State
93 **/
94 // XXX document exactly what bits are saved
95 void Save();
96 void Restore();
98 /**
99 ** Paths & Drawing
103 * Fill the current path according to the current settings.
105 * Does not consume the current path.
107 void Fill();
108 void Fill(const Pattern& aPattern);
111 * Forgets the current path.
113 void NewPath();
116 * Closes the path, i.e. connects the last drawn point to the first one.
118 * Filling a path will implicitly close it.
120 void ClosePath();
123 * Returns the current path.
125 already_AddRefed<Path> GetPath();
128 * Sets the given path as the current path.
130 void SetPath(Path* path);
133 * Moves the pen to a new point without drawing a line.
135 void MoveTo(const gfxPoint& pt);
138 * Draws a line from the current point to pt.
140 * @see MoveTo
142 void LineTo(const gfxPoint& pt);
144 // path helpers
146 * Draws a line from start to end.
148 void Line(const gfxPoint& start,
149 const gfxPoint& end); // XXX snapToPixels option?
152 * Draws the rectangle given by rect.
154 void Rectangle(const gfxRect& rect) { return Rectangle(rect, false); }
155 void SnappedRectangle(const gfxRect& rect) { return Rectangle(rect, true); }
157 private:
158 void Rectangle(const gfxRect& rect, bool snapToPixels);
160 public:
162 ** Transformation Matrix manipulation
166 * Post-multiplies 'other' onto the current CTM, i.e. this
167 * matrix's transformation will take place before the previously set
168 * transformations.
170 void Multiply(const gfxMatrix& other);
171 void Multiply(const mozilla::gfx::Matrix& other);
174 * Replaces the current transformation matrix with matrix.
176 void SetMatrix(const mozilla::gfx::Matrix& matrix);
177 void SetMatrixDouble(const gfxMatrix& matrix);
180 * Returns the current transformation matrix.
182 mozilla::gfx::Matrix CurrentMatrix() const;
183 gfxMatrix CurrentMatrixDouble() const;
186 * Converts a point from device to user coordinates using the inverse
187 * transformation matrix.
189 gfxPoint DeviceToUser(const gfxPoint& point) const;
192 * Converts a size from device to user coordinates. This does not apply
193 * translation components of the matrix.
195 Size DeviceToUser(const Size& size) const;
198 * Converts a rectangle from device to user coordinates; this has the
199 * same effect as using DeviceToUser on both the rectangle's point and
200 * size.
202 gfxRect DeviceToUser(const gfxRect& rect) const;
205 * Converts a point from user to device coordinates using the transformation
206 * matrix.
208 gfxPoint UserToDevice(const gfxPoint& point) const;
211 * Converts a size from user to device coordinates. This does not apply
212 * translation components of the matrix.
214 Size UserToDevice(const Size& size) const;
217 * Converts a rectangle from user to device coordinates. The
218 * resulting rectangle is the minimum device-space rectangle that
219 * encloses the user-space rectangle given.
221 gfxRect UserToDevice(const gfxRect& rect) const;
224 * Takes the given rect and tries to align it to device pixels. If
225 * this succeeds, the method will return true, and the rect will
226 * be in device coordinates (already transformed by the CTM). If it
227 * fails, the method will return false, and the rect will not be
228 * changed.
230 * aOptions parameter:
231 * If IgnoreScale is set, then snapping will take place even if the CTM
232 * has a scale applied. Snapping never takes place if there is a rotation
233 * in the CTM.
235 * If PrioritizeSize is set, the rect's dimensions will first be snapped
236 * and then its position aligned to device pixels, rather than snapping
237 * the position of each edge independently.
239 enum class SnapOption : uint8_t {
240 IgnoreScale = 1,
241 PrioritizeSize = 2,
243 using SnapOptions = mozilla::EnumSet<SnapOption>;
244 bool UserToDevicePixelSnapped(gfxRect& rect, SnapOptions aOptions = {}) const;
247 * Takes the given point and tries to align it to device pixels. If
248 * this succeeds, the method will return true, and the point will
249 * be in device coordinates (already transformed by the CTM). If it
250 * fails, the method will return false, and the point will not be
251 * changed.
253 * If ignoreScale is true, then snapping will take place even if
254 * the CTM has a scale applied. Snapping never takes place if
255 * there is a rotation in the CTM.
257 bool UserToDevicePixelSnapped(gfxPoint& pt, bool ignoreScale = false) const;
260 ** Painting sources
264 * Set a solid color to use for drawing. This color is in the device color
265 * space and is not transformed.
267 void SetDeviceColor(const mozilla::gfx::DeviceColor& aColor);
270 * Gets the current color. It's returned in the device color space.
271 * returns false if there is something other than a color
272 * set as the current source (pattern, surface, etc)
274 bool GetDeviceColor(mozilla::gfx::DeviceColor& aColorOut);
277 * Returns true if color is neither opaque nor transparent (i.e. alpha is not
278 * 0 or 1), and false otherwise. If true, aColorOut is set on output.
280 bool HasNonOpaqueNonTransparentColor(mozilla::gfx::DeviceColor& aColorOut) {
281 return GetDeviceColor(aColorOut) && 0.f < aColorOut.a && aColorOut.a < 1.f;
285 * Set a solid color in the sRGB color space to use for drawing.
286 * If CMS is not enabled, the color is treated as a device-space color
287 * and this call is identical to SetDeviceColor().
289 void SetColor(const mozilla::gfx::sRGBColor& aColor);
292 * Uses a pattern for drawing.
294 void SetPattern(gfxPattern* pattern);
297 * Get the source pattern (solid color, normal pattern, surface, etc)
299 already_AddRefed<gfxPattern> GetPattern();
302 ** Painting
305 * Paints the current source surface/pattern everywhere in the current
306 * clip region.
308 void Paint(Float alpha = 1.0);
311 ** Painting with a Mask
314 * Like Paint, except that it only draws the source where pattern is
315 * non-transparent.
317 void Mask(mozilla::gfx::SourceSurface* aSurface, mozilla::gfx::Float aAlpha,
318 const mozilla::gfx::Matrix& aTransform);
319 void Mask(mozilla::gfx::SourceSurface* aSurface,
320 const mozilla::gfx::Matrix& aTransform) {
321 Mask(aSurface, 1.0f, aTransform);
323 void Mask(mozilla::gfx::SourceSurface* surface, float alpha = 1.0f,
324 const mozilla::gfx::Point& offset = mozilla::gfx::Point());
327 ** Line Properties
330 void SetDash(const Float* dashes, int ndash, Float offset);
331 // Return true if dashing is set, false if it's not enabled or the
332 // context is in an error state. |offset| can be nullptr to mean
333 // "don't care".
334 bool CurrentDash(FallibleTArray<Float>& dashes, Float* offset) const;
337 * Sets the line width that's used for line drawing.
339 void SetLineWidth(Float width);
342 * Returns the currently set line width.
344 * @see SetLineWidth
346 Float CurrentLineWidth() const;
349 * Sets the line caps, i.e. how line endings are drawn.
351 void SetLineCap(CapStyle cap);
352 CapStyle CurrentLineCap() const;
355 * Sets the line join, i.e. how the connection between two lines is
356 * drawn.
358 void SetLineJoin(JoinStyle join);
359 JoinStyle CurrentLineJoin() const;
361 void SetMiterLimit(Float limit);
362 Float CurrentMiterLimit() const;
365 * Sets the operator used for all further drawing. The operator affects
366 * how drawing something will modify the destination. For example, the
367 * OVER operator will do alpha blending of source and destination, while
368 * SOURCE will replace the destination with the source.
370 void SetOp(CompositionOp op);
371 CompositionOp CurrentOp() const;
373 void SetAntialiasMode(mozilla::gfx::AntialiasMode mode);
374 mozilla::gfx::AntialiasMode CurrentAntialiasMode() const;
377 ** Clipping
381 * Clips all further drawing to the current path.
382 * This does not consume the current path.
384 void Clip();
387 * Helper functions that will create a rect path and call Clip().
388 * Any current path will be destroyed by these functions!
390 void Clip(const Rect& rect);
391 void Clip(const gfxRect& rect); // will clip to a rect
392 void SnappedClip(const gfxRect& rect); // snap rect and clip to the result
393 void Clip(Path* aPath);
395 void PopClip();
397 enum ClipExtentsSpace {
398 eUserSpace = 0,
399 eDeviceSpace = 1,
403 * According to aSpace, this function will return the current bounds of
404 * the clip region in user space or device space.
406 gfxRect GetClipExtents(ClipExtentsSpace aSpace = eUserSpace) const;
409 * Returns true if the given rectangle is fully contained in the current clip.
410 * This is conservative; it may return false even when the given rectangle is
411 * fully contained by the current clip.
413 bool ClipContainsRect(const gfxRect& aRect);
416 * Exports the current clip using the provided exporter.
418 bool ExportClip(ClipExporter& aExporter);
421 * Groups
423 void PushGroupForBlendBack(
424 gfxContentType content, mozilla::gfx::Float aOpacity = 1.0f,
425 mozilla::gfx::SourceSurface* aMask = nullptr,
426 const mozilla::gfx::Matrix& aMaskTransform = mozilla::gfx::Matrix());
428 void PopGroupAndBlend();
430 mozilla::gfx::Point GetDeviceOffset() const;
431 void SetDeviceOffset(const mozilla::gfx::Point& aOffset);
433 #ifdef MOZ_DUMP_PAINTING
435 * Debug functions to encode the current surface as a PNG and export it.
439 * Writes a binary PNG file.
441 void WriteAsPNG(const char* aFile);
444 * Write as a PNG encoded Data URL to stdout.
446 void DumpAsDataURI();
449 * Copy a PNG encoded Data URL to the clipboard.
451 void CopyAsDataURI();
452 #endif
454 private:
456 * Initialize this context from a DrawTarget.
457 * Strips any transform from aTarget.
458 * aTarget will be flushed in the gfxContext's destructor. Use the static
459 * ContextForDrawTargetNoTransform() when you want this behavior, as that
460 * version deals with null DrawTarget better.
462 explicit gfxContext(
463 mozilla::gfx::DrawTarget* aTarget,
464 const mozilla::gfx::Point& aDeviceOffset = mozilla::gfx::Point());
465 ~gfxContext();
467 friend class PatternFromState;
468 friend class GlyphBufferAzure;
470 typedef mozilla::gfx::Matrix Matrix;
471 typedef mozilla::gfx::DrawTarget DrawTarget;
472 typedef mozilla::gfx::sRGBColor sRGBColor;
473 typedef mozilla::gfx::DeviceColor DeviceColor;
474 typedef mozilla::gfx::StrokeOptions StrokeOptions;
475 typedef mozilla::gfx::PathBuilder PathBuilder;
476 typedef mozilla::gfx::SourceSurface SourceSurface;
478 struct AzureState {
479 AzureState()
480 : op(mozilla::gfx::CompositionOp::OP_OVER),
481 color(0, 0, 0, 1.0f),
482 aaMode(mozilla::gfx::AntialiasMode::SUBPIXEL),
483 patternTransformChanged(false)
484 #ifdef DEBUG
486 mContentChanged(false)
487 #endif
491 mozilla::gfx::CompositionOp op;
492 DeviceColor color;
493 RefPtr<gfxPattern> pattern;
494 Matrix transform;
495 struct PushedClip {
496 RefPtr<Path> path;
497 Rect rect;
498 Matrix transform;
500 CopyableTArray<PushedClip> pushedClips;
501 CopyableTArray<Float> dashPattern;
502 StrokeOptions strokeOptions;
503 RefPtr<DrawTarget> drawTarget;
504 mozilla::gfx::AntialiasMode aaMode;
505 bool patternTransformChanged;
506 Matrix patternTransform;
507 DeviceColor fontSmoothingBackgroundColor;
508 // This is used solely for using minimal intermediate surface size.
509 mozilla::gfx::Point deviceOffset;
510 #ifdef DEBUG
511 // Whether the content of this AzureState changed after construction.
512 bool mContentChanged;
513 #endif
516 // This ensures mPath contains a valid path (in user space!)
517 void EnsurePath();
518 // This ensures mPathBuilder contains a valid PathBuilder (in user space!)
519 void EnsurePathBuilder();
520 CompositionOp GetOp();
521 void ChangeTransform(const mozilla::gfx::Matrix& aNewMatrix,
522 bool aUpdatePatternTransform = true);
523 Rect GetAzureDeviceSpaceClipBounds() const;
524 Matrix GetDTTransform() const;
526 bool mPathIsRect;
527 bool mTransformChanged;
528 Matrix mPathTransform;
529 Rect mRect;
530 RefPtr<PathBuilder> mPathBuilder;
531 RefPtr<Path> mPath;
532 Matrix mTransform;
533 nsTArray<AzureState> mStateStack;
535 AzureState& CurrentState() { return mStateStack[mStateStack.Length() - 1]; }
536 const AzureState& CurrentState() const {
537 return mStateStack[mStateStack.Length() - 1];
540 RefPtr<DrawTarget> mDT;
544 * Sentry helper class for functions with multiple return points that need to
545 * call Save() on a gfxContext and have Restore() called automatically on the
546 * gfxContext before they return.
548 class gfxContextAutoSaveRestore {
549 public:
550 gfxContextAutoSaveRestore() : mContext(nullptr) {}
552 explicit gfxContextAutoSaveRestore(gfxContext* aContext)
553 : mContext(aContext) {
554 mContext->Save();
557 ~gfxContextAutoSaveRestore() { Restore(); }
559 void SetContext(gfxContext* aContext) {
560 NS_ASSERTION(!mContext, "Not going to call Restore() on some context!!!");
561 mContext = aContext;
562 mContext->Save();
565 void EnsureSaved(gfxContext* aContext) {
566 MOZ_ASSERT(!mContext || mContext == aContext, "wrong context");
567 if (!mContext) {
568 mContext = aContext;
569 mContext->Save();
573 void Restore() {
574 if (mContext) {
575 mContext->Restore();
576 mContext = nullptr;
580 private:
581 gfxContext* mContext;
585 * Sentry helper class for functions with multiple return points that need to
586 * back up the current matrix of a context and have it automatically restored
587 * before they return.
589 class gfxContextMatrixAutoSaveRestore {
590 public:
591 gfxContextMatrixAutoSaveRestore() : mContext(nullptr) {}
593 explicit gfxContextMatrixAutoSaveRestore(gfxContext* aContext)
594 : mContext(aContext), mMatrix(aContext->CurrentMatrix()) {}
596 ~gfxContextMatrixAutoSaveRestore() {
597 if (mContext) {
598 mContext->SetMatrix(mMatrix);
602 void SetContext(gfxContext* aContext) {
603 NS_ASSERTION(!mContext, "Not going to restore the matrix on some context!");
604 mContext = aContext;
605 mMatrix = aContext->CurrentMatrix();
608 void Restore() {
609 if (mContext) {
610 mContext->SetMatrix(mMatrix);
611 mContext = nullptr;
615 const mozilla::gfx::Matrix& Matrix() {
616 MOZ_ASSERT(mContext, "mMatrix doesn't contain a useful matrix");
617 return mMatrix;
620 bool HasMatrix() const { return !!mContext; }
622 private:
623 gfxContext* mContext;
624 mozilla::gfx::Matrix mMatrix;
627 class DrawTargetAutoDisableSubpixelAntialiasing {
628 public:
629 typedef mozilla::gfx::DrawTarget DrawTarget;
631 DrawTargetAutoDisableSubpixelAntialiasing(DrawTarget* aDT, bool aDisable)
632 : mSubpixelAntialiasingEnabled(false) {
633 if (aDisable) {
634 mDT = aDT;
635 mSubpixelAntialiasingEnabled = mDT->GetPermitSubpixelAA();
636 mDT->SetPermitSubpixelAA(false);
639 ~DrawTargetAutoDisableSubpixelAntialiasing() {
640 if (mDT) {
641 mDT->SetPermitSubpixelAA(mSubpixelAntialiasingEnabled);
645 private:
646 RefPtr<DrawTarget> mDT;
647 bool mSubpixelAntialiasingEnabled;
650 /* This class lives on the stack and allows gfxContext users to easily, and
651 * performantly get a gfx::Pattern to use for drawing in their current context.
653 class PatternFromState {
654 public:
655 explicit PatternFromState(gfxContext* aContext)
656 : mContext(aContext), mPattern(nullptr) {}
657 ~PatternFromState() {
658 if (mPattern) {
659 mPattern->~Pattern();
663 operator mozilla::gfx::Pattern&();
665 private:
666 union {
667 mozilla::AlignedStorage2<mozilla::gfx::ColorPattern> mColorPattern;
668 mozilla::AlignedStorage2<mozilla::gfx::SurfacePattern> mSurfacePattern;
671 gfxContext* mContext;
672 mozilla::gfx::Pattern* mPattern;
675 /* This interface should be implemented to handle exporting the clip from a
676 * context.
678 class ClipExporter : public mozilla::gfx::PathSink {
679 public:
680 virtual void BeginClip(const mozilla::gfx::Matrix& aMatrix) = 0;
681 virtual void EndClip() = 0;
684 #endif /* GFX_CONTEXT_H */