blob: f5362599c3b9317f3e3902c5edf49400e7f0202e [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_FLAGS_H_
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_FLAGS_H_
#include "flutter/display_list/display_list_paint.h"
#include "flutter/display_list/types.h"
#include "flutter/fml/logging.h"
namespace flutter {
class DlPathEffect;
/// The base class for the classes that maintain a list of
/// attributes that might be important for a number of operations
/// including which rendering attributes need to be set before
/// calling a rendering method (all |drawSomething| calls),
/// or for determining which exceptional conditions may need
/// to be accounted for in bounds calculations.
/// This class contains only protected definitions and helper methods
/// for the public classes |DisplayListAttributeFlags| and
/// |DisplayListSpecialGeometryFlags|.
class DisplayListFlags {
protected:
// A drawing operation that is not geometric in nature (but which
// may still apply a MaskFilter - see |kUsesMaskFilter_| below).
static constexpr int kIsNonGeometric_ = 0;
// A geometric operation that is defined as a fill operation
// regardless of what the current paint Style is set to.
// This flag will automatically assume |kUsesMaskFilter_|.
static constexpr int kIsFilledGeometry_ = 1 << 0;
// A geometric operation that is defined as a stroke operation
// regardless of what the current paint Style is set to.
// This flag will automatically assume |kUsesMaskFilter_|.
static constexpr int kIsStrokedGeometry_ = 1 << 1;
// A geometric operation that may be a stroke or fill operation
// depending on the current state of the paint Style attribute.
// This flag will automatically assume |kUsesMaskFilter_|.
static constexpr int kIsDrawnGeometry_ = 1 << 2;
static constexpr int kIsAnyGeometryMask_ = //
kIsFilledGeometry_ | //
kIsStrokedGeometry_ | //
kIsDrawnGeometry_;
// A primitive that floods the surface (or clip) with no
// natural bounds, such as |drawColor| or |drawPaint|.
static constexpr int kFloodsSurface_ = 1 << 3;
static constexpr int kMayHaveCaps_ = 1 << 4;
static constexpr int kMayHaveJoins_ = 1 << 5;
static constexpr int kButtCapIsSquare_ = 1 << 6;
// A geometric operation which has a path that might have
// end caps that are not rectilinear which means that square
// end caps might project further than half the stroke width
// from the geometry bounds.
// A rectilinear path such as |drawRect| will not have
// diagonal end caps. |drawLine| might have diagonal end
// caps depending on the angle of the line, and more likely
// |drawPath| will often have such end caps.
static constexpr int kMayHaveDiagonalCaps_ = 1 << 7;
// A geometric operation which has joined vertices that are
// not guaranteed to be smooth (angles of incoming and outgoing)
// segments at some joins may not have the same angle) or
// rectilinear (squares have right angles at the corners, but
// those corners will never extend past the bounding box of
// the geometry pre-transform).
// |drawRect|, |drawOval| and |drawRRect| all have well
// behaved joins, but |drawPath| might have joins that cause
// mitered extensions outside the pre-transformed bounding box.
static constexpr int kMayHaveAcuteJoins_ = 1 << 8;
static constexpr int kAnySpecialGeometryMask_ = //
kMayHaveCaps_ | kMayHaveJoins_ | kButtCapIsSquare_ | //
kMayHaveDiagonalCaps_ | kMayHaveAcuteJoins_;
// clang-format off
static constexpr int kUsesAntiAlias_ = 1 << 10;
static constexpr int kUsesDither_ = 1 << 11;
static constexpr int kUsesAlpha_ = 1 << 12;
static constexpr int kUsesColor_ = 1 << 13;
static constexpr int kUsesBlend_ = 1 << 14;
static constexpr int kUsesShader_ = 1 << 15;
static constexpr int kUsesColorFilter_ = 1 << 16;
static constexpr int kUsesPathEffect_ = 1 << 17;
static constexpr int kUsesMaskFilter_ = 1 << 18;
static constexpr int kUsesImageFilter_ = 1 << 19;
// Some ops have an optional paint argument. If the version
// stored in the DisplayList ignores the paint, but there
// is an option to render the same op with a paint then
// both of the following flags are set to indicate that
// a default paint object can be constructed when rendering
// the op to carry information imposed from outside the
// DisplayList (for example, the opacity override).
static constexpr int kIgnoresPaint_ = 1 << 30;
// clang-format on
static constexpr int kAnyAttributeMask_ = //
kUsesAntiAlias_ | kUsesDither_ | kUsesAlpha_ | kUsesColor_ | kUsesBlend_ |
kUsesShader_ | kUsesColorFilter_ | kUsesPathEffect_ | kUsesMaskFilter_ |
kUsesImageFilter_;
};
class DisplayListFlagsBase : protected DisplayListFlags {
protected:
explicit DisplayListFlagsBase(int flags) : flags_(flags) {}
const int flags_;
bool has_any(int qFlags) const { return (flags_ & qFlags) != 0; }
bool has_all(int qFlags) const { return (flags_ & qFlags) == qFlags; }
bool has_none(int qFlags) const { return (flags_ & qFlags) == 0; }
};
/// An attribute class for advertising specific properties of
/// a geometric attribute that can affect the computation of
/// the bounds of the primitive.
class DisplayListSpecialGeometryFlags : DisplayListFlagsBase {
public:
/// The geometry may have segments that end without closing the path.
bool may_have_end_caps() const { return has_any(kMayHaveCaps_); }
/// The geometry may have segments connect non-continuously.
bool may_have_joins() const { return has_any(kMayHaveJoins_); }
/// Mainly for drawPoints(PointMode) where Butt caps are rendered as squares.
bool butt_cap_becomes_square() const { return has_any(kButtCapIsSquare_); }
/// The geometry may have segments that end on a diagonal
/// such that their end caps extend further than the default
/// |strokeWidth * 0.5| margin around the geometry.
bool may_have_diagonal_caps() const { return has_any(kMayHaveDiagonalCaps_); }
/// The geometry may have segments that meet at vertices at
/// an acute angle such that the miter joins will extend
/// further than the default |strokeWidth * 0.5| margin around
/// the geometry.
bool may_have_acute_joins() const { return has_any(kMayHaveAcuteJoins_); }
private:
explicit DisplayListSpecialGeometryFlags(int flags)
: DisplayListFlagsBase(flags) {
FML_DCHECK((flags & kAnySpecialGeometryMask_) == flags);
}
const DisplayListSpecialGeometryFlags with(int extra) const {
return extra == 0 ? *this : DisplayListSpecialGeometryFlags(flags_ | extra);
}
friend class DisplayListAttributeFlags;
};
class DisplayListAttributeFlags : DisplayListFlagsBase {
public:
const DisplayListSpecialGeometryFlags WithPathEffect(
const DlPathEffect* effect) const;
bool ignores_paint() const { return has_any(kIgnoresPaint_); }
bool applies_anti_alias() const { return has_any(kUsesAntiAlias_); }
bool applies_dither() const { return has_any(kUsesDither_); }
bool applies_color() const { return has_any(kUsesColor_); }
bool applies_alpha() const { return has_any(kUsesAlpha_); }
bool applies_alpha_or_color() const {
return has_any(kUsesAlpha_ | kUsesColor_);
}
/// The primitive dynamically determines whether it is a stroke or fill
/// operation (or both) based on the setting of the |Style| attribute.
bool applies_style() const { return has_any(kIsDrawnGeometry_); }
/// The primitive can use any of the stroke attributes, such as
/// StrokeWidth, StrokeMiter, StrokeCap, or StrokeJoin. This
/// method will return if the primitive is defined as one that
/// strokes its geometry (such as |drawLine|) or if it is defined
/// as one that honors the Style attribute. If the Style attribute
/// is known then a more accurate answer can be returned from
/// the |is_stroked| method by supplying the actual setting of
/// the style.
// bool applies_stroke_attributes() const { return is_stroked(); }
bool applies_shader() const { return has_any(kUsesShader_); }
/// The primitive honors the current SkColorFilter, including
/// the related attribute InvertColors
bool applies_color_filter() const { return has_any(kUsesColorFilter_); }
/// The primitive honors the SkBlendMode or SkBlender
bool applies_blend() const { return has_any(kUsesBlend_); }
bool applies_path_effect() const { return has_any(kUsesPathEffect_); }
/// The primitive honors the SkMaskFilter whether set using the
/// filter object or using the convenience method |setMaskBlurFilter|
bool applies_mask_filter() const { return has_any(kUsesMaskFilter_); }
bool applies_image_filter() const { return has_any(kUsesImageFilter_); }
bool is_geometric() const { return has_any(kIsAnyGeometryMask_); }
bool always_stroked() const { return has_any(kIsStrokedGeometry_); }
bool is_stroked(DlDrawStyle style = DlDrawStyle::kStroke) const {
return (has_any(kIsStrokedGeometry_) ||
(style != DlDrawStyle::kFill && has_any(kIsDrawnGeometry_)));
}
bool is_flood() const { return has_any(kFloodsSurface_); }
private:
explicit DisplayListAttributeFlags(int flags)
: DisplayListFlagsBase(flags),
special_flags_(flags & kAnySpecialGeometryMask_) {
FML_DCHECK((flags & kIsAnyGeometryMask_) == kIsNonGeometric_ ||
(flags & kIsAnyGeometryMask_) == kIsFilledGeometry_ ||
(flags & kIsAnyGeometryMask_) == kIsStrokedGeometry_ ||
(flags & kIsAnyGeometryMask_) == kIsDrawnGeometry_);
FML_DCHECK(((flags & kAnyAttributeMask_) == 0) !=
((flags & kIgnoresPaint_) == 0));
FML_DCHECK((flags & kIsAnyGeometryMask_) != 0 ||
(flags & kAnySpecialGeometryMask_) == 0);
}
const DisplayListAttributeFlags with(int extra) const {
return extra == 0 ? *this : DisplayListAttributeFlags(flags_ | extra);
}
const DisplayListAttributeFlags without(int remove) const {
FML_DCHECK(has_all(remove));
return DisplayListAttributeFlags(flags_ & ~remove);
}
const DisplayListSpecialGeometryFlags special_flags_;
friend class DisplayListOpFlags;
};
class DisplayListOpFlags : DisplayListFlags {
public:
static const DisplayListAttributeFlags kSaveLayerFlags;
static const DisplayListAttributeFlags kSaveLayerWithPaintFlags;
static const DisplayListAttributeFlags kDrawColorFlags;
static const DisplayListAttributeFlags kDrawPaintFlags;
static const DisplayListAttributeFlags kDrawLineFlags;
// Special case flags for horizonal and vertical lines
static const DisplayListAttributeFlags kDrawHVLineFlags;
static const DisplayListAttributeFlags kDrawRectFlags;
static const DisplayListAttributeFlags kDrawOvalFlags;
static const DisplayListAttributeFlags kDrawCircleFlags;
static const DisplayListAttributeFlags kDrawRRectFlags;
static const DisplayListAttributeFlags kDrawDRRectFlags;
static const DisplayListAttributeFlags kDrawPathFlags;
static const DisplayListAttributeFlags kDrawArcNoCenterFlags;
static const DisplayListAttributeFlags kDrawArcWithCenterFlags;
static const DisplayListAttributeFlags kDrawPointsAsPointsFlags;
static const DisplayListAttributeFlags kDrawPointsAsLinesFlags;
static const DisplayListAttributeFlags kDrawPointsAsPolygonFlags;
static const DisplayListAttributeFlags kDrawVerticesFlags;
static const DisplayListAttributeFlags kDrawImageFlags;
static const DisplayListAttributeFlags kDrawImageWithPaintFlags;
static const DisplayListAttributeFlags kDrawImageRectFlags;
static const DisplayListAttributeFlags kDrawImageRectWithPaintFlags;
static const DisplayListAttributeFlags kDrawImageNineFlags;
static const DisplayListAttributeFlags kDrawImageNineWithPaintFlags;
static const DisplayListAttributeFlags kDrawImageLatticeFlags;
static const DisplayListAttributeFlags kDrawImageLatticeWithPaintFlags;
static const DisplayListAttributeFlags kDrawAtlasFlags;
static const DisplayListAttributeFlags kDrawAtlasWithPaintFlags;
static const DisplayListAttributeFlags kDrawPictureFlags;
static const DisplayListAttributeFlags kDrawPictureWithPaintFlags;
static const DisplayListAttributeFlags kDrawDisplayListFlags;
static const DisplayListAttributeFlags kDrawTextBlobFlags;
static const DisplayListAttributeFlags kDrawShadowFlags;
};
} // namespace flutter
#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_FLAGS_H_