зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1614510 - Use cbindgen for shape-outside and clip-path. r=boris
Differential Revision: https://phabricator.services.mozilla.com/D62372 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
90b8c7c6b2
Коммит
628f21dc90
|
@ -9934,17 +9934,59 @@ static nsRect ComputeHTMLReferenceRect(nsIFrame* aFrame,
|
|||
return r;
|
||||
}
|
||||
|
||||
static StyleGeometryBox ShapeBoxToGeometryBox(const StyleShapeBox& aBox) {
|
||||
switch (aBox) {
|
||||
case StyleShapeBox::BorderBox:
|
||||
return StyleGeometryBox::BorderBox;
|
||||
case StyleShapeBox::ContentBox:
|
||||
return StyleGeometryBox::ContentBox;
|
||||
case StyleShapeBox::MarginBox:
|
||||
return StyleGeometryBox::MarginBox;
|
||||
case StyleShapeBox::PaddingBox:
|
||||
return StyleGeometryBox::PaddingBox;
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown shape box type");
|
||||
return StyleGeometryBox::MarginBox;
|
||||
}
|
||||
|
||||
static StyleGeometryBox ClipPathBoxToGeometryBox(
|
||||
const StyleShapeGeometryBox& aBox) {
|
||||
using Tag = StyleShapeGeometryBox::Tag;
|
||||
switch (aBox.tag) {
|
||||
case Tag::ShapeBox:
|
||||
return ShapeBoxToGeometryBox(aBox.AsShapeBox());
|
||||
case Tag::ElementDependent:
|
||||
return StyleGeometryBox::NoBox;
|
||||
case Tag::FillBox:
|
||||
return StyleGeometryBox::FillBox;
|
||||
case Tag::StrokeBox:
|
||||
return StyleGeometryBox::StrokeBox;
|
||||
case Tag::ViewBox:
|
||||
return StyleGeometryBox::ViewBox;
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown shape box type");
|
||||
return StyleGeometryBox::NoBox;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsRect nsLayoutUtils::ComputeGeometryBox(nsIFrame* aFrame,
|
||||
StyleGeometryBox aGeometryBox) {
|
||||
// We use ComputeSVGReferenceRect for all SVG elements, except <svg>
|
||||
// element, which does have an associated CSS layout box. In this case we
|
||||
// should still use ComputeHTMLReferenceRect for region computing.
|
||||
nsRect r = (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)
|
||||
? ComputeSVGReferenceRect(aFrame, aGeometryBox)
|
||||
: ComputeHTMLReferenceRect(aFrame, aGeometryBox);
|
||||
return aFrame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)
|
||||
? ComputeSVGReferenceRect(aFrame, aGeometryBox)
|
||||
: ComputeHTMLReferenceRect(aFrame, aGeometryBox);
|
||||
}
|
||||
|
||||
return r;
|
||||
nsRect nsLayoutUtils::ComputeGeometryBox(nsIFrame* aFrame,
|
||||
const StyleShapeBox& aBox) {
|
||||
return ComputeGeometryBox(aFrame, ShapeBoxToGeometryBox(aBox));
|
||||
}
|
||||
|
||||
nsRect nsLayoutUtils::ComputeGeometryBox(nsIFrame* aFrame,
|
||||
const StyleShapeGeometryBox& aBox) {
|
||||
return ComputeGeometryBox(aFrame, ClipPathBoxToGeometryBox(aBox));
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -2942,8 +2942,12 @@ class nsLayoutUtils {
|
|||
static bool IsInvisibleBreak(nsINode* aNode,
|
||||
nsIFrame** aNextLineFrame = nullptr);
|
||||
|
||||
static nsRect ComputeGeometryBox(nsIFrame* aFrame,
|
||||
StyleGeometryBox aGeometryBox);
|
||||
static nsRect ComputeGeometryBox(nsIFrame*, StyleGeometryBox);
|
||||
|
||||
static nsRect ComputeGeometryBox(nsIFrame*,
|
||||
const mozilla::StyleShapeGeometryBox&);
|
||||
|
||||
static nsRect ComputeGeometryBox(nsIFrame*, const mozilla::StyleShapeBox&);
|
||||
|
||||
static nsPoint ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame);
|
||||
|
|
|
@ -654,9 +654,9 @@ static nscoord FloatMarginISize(const ReflowInput& aCBReflowInput,
|
|||
// Maybe all this code could be refactored to make this cleaner, but keeping the
|
||||
// two properties separated was slightly nicer.
|
||||
struct ShapeInvalidationData {
|
||||
StyleShapeSource mShapeOutside;
|
||||
StyleFloatAreaShape mShapeOutside{StyleFloatAreaShape::None()};
|
||||
float mShapeImageThreshold = 0.0;
|
||||
mozilla::LengthPercentage mShapeMargin;
|
||||
LengthPercentage mShapeMargin;
|
||||
|
||||
ShapeInvalidationData() = default;
|
||||
|
||||
|
@ -665,7 +665,7 @@ struct ShapeInvalidationData {
|
|||
}
|
||||
|
||||
static bool IsNeeded(const nsStyleDisplay& aDisplay) {
|
||||
return aDisplay.mShapeOutside.GetType() != StyleShapeSourceType::None;
|
||||
return !aDisplay.mShapeOutside.IsNone();
|
||||
}
|
||||
|
||||
void Update(const nsStyleDisplay& aDisplay) {
|
||||
|
|
|
@ -524,8 +524,7 @@ class nsFloatManager::ShapeInfo {
|
|||
// Translate the current origin by the specified offsets.
|
||||
virtual void Translate(nscoord aLineLeft, nscoord aBlockStart) = 0;
|
||||
|
||||
static LogicalRect ComputeShapeBoxRect(const StyleShapeSource& aShapeOutside,
|
||||
nsIFrame* const aFrame,
|
||||
static LogicalRect ComputeShapeBoxRect(StyleShapeBox, nsIFrame* const aFrame,
|
||||
const LogicalRect& aMarginRect,
|
||||
WritingMode aWM);
|
||||
|
||||
|
@ -2257,6 +2256,7 @@ nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame, nscoord aLineLeft,
|
|||
mRect(ShapeInfo::ConvertToFloatLogical(aMarginRect, aWM, aContainerSize) +
|
||||
nsPoint(aLineLeft, aBlockStart)) {
|
||||
MOZ_COUNT_CTOR(nsFloatManager::FloatInfo);
|
||||
using ShapeOutsideType = StyleFloatAreaShape::Tag;
|
||||
|
||||
if (IsEmpty()) {
|
||||
// Per spec, a float area defined by a shape is clipped to the float’s
|
||||
|
@ -2269,27 +2269,23 @@ nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame, nscoord aLineLeft,
|
|||
}
|
||||
|
||||
const nsStyleDisplay* styleDisplay = mFrame->StyleDisplay();
|
||||
const StyleShapeSource& shapeOutside = styleDisplay->mShapeOutside;
|
||||
const auto& shapeOutside = styleDisplay->mShapeOutside;
|
||||
|
||||
nscoord shapeMargin = (shapeOutside.GetType() == StyleShapeSourceType::None)
|
||||
nscoord shapeMargin = shapeOutside.IsNone()
|
||||
? 0
|
||||
: nsLayoutUtils::ResolveToLength<true>(
|
||||
styleDisplay->mShapeMargin,
|
||||
LogicalSize(aWM, aContainerSize).ISize(aWM));
|
||||
|
||||
switch (shapeOutside.GetType()) {
|
||||
case StyleShapeSourceType::None:
|
||||
switch (shapeOutside.tag) {
|
||||
case ShapeOutsideType::None:
|
||||
// No need to create shape info.
|
||||
return;
|
||||
|
||||
case StyleShapeSourceType::Path:
|
||||
MOZ_ASSERT_UNREACHABLE("shape-outside doesn't have Path source type!");
|
||||
return;
|
||||
|
||||
case StyleShapeSourceType::Image: {
|
||||
case ShapeOutsideType::ImageOrUrl: {
|
||||
float shapeImageThreshold = styleDisplay->mShapeImageThreshold;
|
||||
mShapeInfo = ShapeInfo::CreateImageShape(
|
||||
shapeOutside.ShapeImage(), shapeImageThreshold, shapeMargin, mFrame,
|
||||
shapeOutside.AsImageOrUrl(), shapeImageThreshold, shapeMargin, mFrame,
|
||||
aMarginRect, aWM, aContainerSize);
|
||||
if (!mShapeInfo) {
|
||||
// Image is not ready, or fails to load, etc.
|
||||
|
@ -2299,23 +2295,28 @@ nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame, nscoord aLineLeft,
|
|||
break;
|
||||
}
|
||||
|
||||
case StyleShapeSourceType::Box: {
|
||||
case ShapeOutsideType::Path:
|
||||
// FIXME(emilio): We shouldn't generate the enum then.
|
||||
MOZ_ASSERT_UNREACHABLE("shape-outside doesn't have Path source type!");
|
||||
return;
|
||||
|
||||
case ShapeOutsideType::Box: {
|
||||
// Initialize <shape-box>'s reference rect.
|
||||
LogicalRect shapeBoxRect = ShapeInfo::ComputeShapeBoxRect(
|
||||
shapeOutside, mFrame, aMarginRect, aWM);
|
||||
shapeOutside.AsBox(), mFrame, aMarginRect, aWM);
|
||||
mShapeInfo = ShapeInfo::CreateShapeBox(mFrame, shapeMargin, shapeBoxRect,
|
||||
aWM, aContainerSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case StyleShapeSourceType::Shape: {
|
||||
const StyleBasicShape& basicShape = shapeOutside.BasicShape();
|
||||
case ShapeOutsideType::Shape: {
|
||||
const auto& shape = *shapeOutside.AsShape()._0;
|
||||
// Initialize <shape-box>'s reference rect.
|
||||
LogicalRect shapeBoxRect = ShapeInfo::ComputeShapeBoxRect(
|
||||
shapeOutside, mFrame, aMarginRect, aWM);
|
||||
mShapeInfo = ShapeInfo::CreateBasicShape(basicShape, shapeMargin, mFrame,
|
||||
shapeBoxRect, aMarginRect, aWM,
|
||||
aContainerSize);
|
||||
shapeOutside.AsShape()._1, mFrame, aMarginRect, aWM);
|
||||
mShapeInfo =
|
||||
ShapeInfo::CreateBasicShape(shape, shapeMargin, mFrame, shapeBoxRect,
|
||||
aMarginRect, aWM, aContainerSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2437,27 +2438,25 @@ bool nsFloatManager::FloatInfo::MayNarrowInBlockDirection(
|
|||
|
||||
/* static */
|
||||
LogicalRect nsFloatManager::ShapeInfo::ComputeShapeBoxRect(
|
||||
const StyleShapeSource& aShapeOutside, nsIFrame* const aFrame,
|
||||
const LogicalRect& aMarginRect, WritingMode aWM) {
|
||||
StyleShapeBox aBox, nsIFrame* const aFrame, const LogicalRect& aMarginRect,
|
||||
WritingMode aWM) {
|
||||
LogicalRect rect = aMarginRect;
|
||||
|
||||
switch (aShapeOutside.GetReferenceBox()) {
|
||||
case StyleGeometryBox::ContentBox:
|
||||
switch (aBox) {
|
||||
case StyleShapeBox::ContentBox:
|
||||
rect.Deflate(aWM, aFrame->GetLogicalUsedPadding(aWM));
|
||||
[[fallthrough]];
|
||||
case StyleGeometryBox::PaddingBox:
|
||||
case StyleShapeBox::PaddingBox:
|
||||
rect.Deflate(aWM, aFrame->GetLogicalUsedBorder(aWM));
|
||||
[[fallthrough]];
|
||||
case StyleGeometryBox::BorderBox:
|
||||
case StyleShapeBox::BorderBox:
|
||||
rect.Deflate(aWM, aFrame->GetLogicalUsedMargin(aWM));
|
||||
break;
|
||||
case StyleGeometryBox::MarginBox:
|
||||
case StyleShapeBox::MarginBox:
|
||||
// Do nothing. rect is already a margin rect.
|
||||
break;
|
||||
case StyleGeometryBox::NoBox:
|
||||
default:
|
||||
MOZ_ASSERT(aShapeOutside.GetType() != StyleShapeSourceType::Box,
|
||||
"Box source type must have <shape-box> specified!");
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown shape box");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2673,7 +2672,7 @@ nsFloatManager::ShapeInfo::CreateImageShape(const StyleImage& aShapeImage,
|
|||
WritingMode aWM,
|
||||
const nsSize& aContainerSize) {
|
||||
MOZ_ASSERT(
|
||||
&aShapeImage == &aFrame->StyleDisplay()->mShapeOutside.ShapeImage(),
|
||||
&aShapeImage == &aFrame->StyleDisplay()->mShapeOutside.AsImageOrUrl(),
|
||||
"aFrame should be the frame that we got aShapeImage from");
|
||||
|
||||
nsImageRenderer imageRenderer(aFrame, &aShapeImage,
|
||||
|
|
|
@ -1324,13 +1324,19 @@ void nsFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
|||
}
|
||||
}
|
||||
|
||||
imgIRequest* oldShapeImage =
|
||||
aOldComputedStyle
|
||||
? aOldComputedStyle->StyleDisplay()->mShapeOutside.GetShapeImageData()
|
||||
: nullptr;
|
||||
imgIRequest* newShapeImage =
|
||||
StyleDisplay()->mShapeOutside.GetShapeImageData();
|
||||
auto GetShapeImageRequest = [](const ComputedStyle* aStyle) -> imgIRequest* {
|
||||
if (!aStyle) {
|
||||
return nullptr;
|
||||
}
|
||||
auto& shape = aStyle->StyleDisplay()->mShapeOutside;
|
||||
if (!shape.IsImageOrUrl()) {
|
||||
return nullptr;
|
||||
}
|
||||
return shape.AsImageOrUrl().GetImageRequest();
|
||||
};
|
||||
|
||||
imgIRequest* oldShapeImage = GetShapeImageRequest(aOldComputedStyle);
|
||||
imgIRequest* newShapeImage = GetShapeImageRequest(Style());
|
||||
if (oldShapeImage != newShapeImage) {
|
||||
if (oldShapeImage && HasImageRequest()) {
|
||||
loader->DisassociateRequestFromFrame(oldShapeImage, this);
|
||||
|
@ -2016,16 +2022,30 @@ bool nsIFrame::GetBoxBorderRadii(nscoord aRadii[8], nsMargin aOffset,
|
|||
}
|
||||
|
||||
bool nsIFrame::GetShapeBoxBorderRadii(nscoord aRadii[8]) const {
|
||||
switch (StyleDisplay()->mShapeOutside.GetReferenceBox()) {
|
||||
case StyleGeometryBox::NoBox:
|
||||
using Tag = StyleFloatAreaShape::Tag;
|
||||
auto& shapeOutside = StyleDisplay()->mShapeOutside;
|
||||
auto box = StyleShapeBox::MarginBox;
|
||||
switch (shapeOutside.tag) {
|
||||
case Tag::Path:
|
||||
case Tag::ImageOrUrl:
|
||||
case Tag::None:
|
||||
return false;
|
||||
case StyleGeometryBox::ContentBox:
|
||||
case Tag::Box:
|
||||
box = shapeOutside.AsBox();
|
||||
break;
|
||||
case Tag::Shape:
|
||||
box = shapeOutside.AsShape()._1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (box) {
|
||||
case StyleShapeBox::ContentBox:
|
||||
return GetContentBoxBorderRadii(aRadii);
|
||||
case StyleGeometryBox::PaddingBox:
|
||||
case StyleShapeBox::PaddingBox:
|
||||
return GetPaddingBoxBorderRadii(aRadii);
|
||||
case StyleGeometryBox::BorderBox:
|
||||
case StyleShapeBox::BorderBox:
|
||||
return GetBorderRadii(aRadii);
|
||||
case StyleGeometryBox::MarginBox:
|
||||
case StyleShapeBox::MarginBox:
|
||||
return GetMarginBoxBorderRadii(aRadii);
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected box value");
|
||||
|
|
|
@ -9956,11 +9956,11 @@ static Maybe<wr::WrClipId> CreateSimpleClipRegion(
|
|||
}
|
||||
|
||||
const auto& clipPath = style->mClipPath;
|
||||
const auto& shape = clipPath.BasicShape();
|
||||
const auto& shape = *clipPath.AsShape()._0;
|
||||
|
||||
auto appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
|
||||
const nsRect refBox =
|
||||
nsLayoutUtils::ComputeGeometryBox(frame, clipPath.GetReferenceBox());
|
||||
nsLayoutUtils::ComputeGeometryBox(frame, clipPath.AsShape()._1);
|
||||
|
||||
AutoTArray<wr::ComplexClipRegion, 1> clipRegions;
|
||||
|
||||
|
|
|
@ -1263,29 +1263,6 @@ PropertyValuePair* Gecko_AppendPropertyValuePair(
|
|||
return aProperties->AppendElement(PropertyValuePair{aProperty});
|
||||
}
|
||||
|
||||
void Gecko_CopyShapeSourceFrom(StyleShapeSource* aDst,
|
||||
const StyleShapeSource* aSrc) {
|
||||
MOZ_ASSERT(aDst);
|
||||
MOZ_ASSERT(aSrc);
|
||||
|
||||
*aDst = *aSrc;
|
||||
}
|
||||
|
||||
void Gecko_DestroyShapeSource(StyleShapeSource* aShape) {
|
||||
aShape->~StyleShapeSource();
|
||||
}
|
||||
|
||||
void Gecko_NewShapeImage(StyleShapeSource* aShape) {
|
||||
aShape->SetShapeImage(MakeUnique<StyleImage>(StyleImage::None()));
|
||||
}
|
||||
|
||||
void Gecko_SetToSVGPath(StyleShapeSource* aShape,
|
||||
StyleForgottenArcSlicePtr<StylePathCommand> aCommands,
|
||||
StyleFillRule aFill) {
|
||||
MOZ_ASSERT(aShape);
|
||||
aShape->SetPath(MakeUnique<StyleSVGPath>(aCommands, aFill));
|
||||
}
|
||||
|
||||
void Gecko_nsStyleSVG_SetDashArrayLength(nsStyleSVG* aSvg, uint32_t aLen) {
|
||||
aSvg->mStrokeDasharray.Clear();
|
||||
aSvg->mStrokeDasharray.SetLength(aLen);
|
||||
|
|
|
@ -441,18 +441,6 @@ mozilla::Keyframe* Gecko_GetOrCreateFinalKeyframe(
|
|||
mozilla::PropertyValuePair* Gecko_AppendPropertyValuePair(
|
||||
nsTArray<mozilla::PropertyValuePair>*, nsCSSPropertyID aProperty);
|
||||
|
||||
void Gecko_CopyShapeSourceFrom(mozilla::StyleShapeSource* dst,
|
||||
const mozilla::StyleShapeSource* src);
|
||||
|
||||
void Gecko_DestroyShapeSource(mozilla::StyleShapeSource* shape);
|
||||
|
||||
void Gecko_NewShapeImage(mozilla::StyleShapeSource* shape);
|
||||
|
||||
void Gecko_SetToSVGPath(
|
||||
mozilla::StyleShapeSource* shape,
|
||||
mozilla::StyleForgottenArcSlicePtr<mozilla::StylePathCommand>,
|
||||
mozilla::StyleFillRule);
|
||||
|
||||
void Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len);
|
||||
|
||||
void Gecko_CopyFiltersFrom(nsStyleEffects* aSrc, nsStyleEffects* aDest);
|
||||
|
|
|
@ -565,6 +565,8 @@ cbindgen-types = [
|
|||
{ gecko = "StyleJustifyContent", servo = "values::computed::align::JustifyContent" },
|
||||
{ gecko = "StyleComputedValueFlags", servo = "computed_value_flags::ComputedValueFlags" },
|
||||
{ gecko = "StyleImage", servo = "values::computed::Image" },
|
||||
{ gecko = "StyleClippingShape", servo = "values::computed::basic_shape::ClippingShape" },
|
||||
{ gecko = "StyleFloatAreaShape", servo = "values::computed::basic_shape::FloatAreaShape" },
|
||||
]
|
||||
|
||||
mapped-generic-types = [
|
||||
|
|
|
@ -633,14 +633,17 @@ static void AddImageURL(const StyleImage& aImage,
|
|||
}
|
||||
}
|
||||
|
||||
static void AddImageURL(const StyleShapeSource& aShapeSource,
|
||||
static void AddImageURL(const StyleFloatAreaShape& aShapeOutside,
|
||||
nsTArray<nsCString>& aURLs) {
|
||||
switch (aShapeSource.GetType()) {
|
||||
case StyleShapeSourceType::Image:
|
||||
AddImageURL(aShapeSource.ShapeImage(), aURLs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (aShapeOutside.IsImageOrUrl()) {
|
||||
AddImageURL(aShapeOutside.AsImageOrUrl(), aURLs);
|
||||
}
|
||||
}
|
||||
|
||||
static void AddImageURL(const StyleClippingShape& aClipPath,
|
||||
nsTArray<nsCString>& aURLs) {
|
||||
if (aClipPath.IsImageOrUrl()) {
|
||||
AddImageURL(aClipPath.AsImageOrUrl(), aURLs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -956,149 +956,6 @@ nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aNewData) const {
|
|||
return hint;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// StyleShapeSource
|
||||
StyleShapeSource::StyleShapeSource() : mBasicShape() {}
|
||||
|
||||
StyleShapeSource::StyleShapeSource(const StyleShapeSource& aSource) {
|
||||
DoCopy(aSource);
|
||||
}
|
||||
|
||||
StyleShapeSource::~StyleShapeSource() { DoDestroy(); }
|
||||
|
||||
StyleShapeSource& StyleShapeSource::operator=(const StyleShapeSource& aOther) {
|
||||
if (this != &aOther) {
|
||||
DoCopy(aOther);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool StyleShapeSource::operator==(const StyleShapeSource& aOther) const {
|
||||
if (mType != aOther.mType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (mType) {
|
||||
case StyleShapeSourceType::None:
|
||||
return true;
|
||||
|
||||
case StyleShapeSourceType::Image:
|
||||
return *mShapeImage == *aOther.mShapeImage;
|
||||
|
||||
case StyleShapeSourceType::Shape:
|
||||
return *mBasicShape == *aOther.mBasicShape &&
|
||||
mReferenceBox == aOther.mReferenceBox;
|
||||
|
||||
case StyleShapeSourceType::Box:
|
||||
return mReferenceBox == aOther.mReferenceBox;
|
||||
|
||||
case StyleShapeSourceType::Path:
|
||||
return *mSVGPath == *aOther.mSVGPath;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected shape source type!");
|
||||
return true;
|
||||
}
|
||||
|
||||
void StyleShapeSource::SetShapeImage(UniquePtr<StyleImage> aShapeImage) {
|
||||
MOZ_ASSERT(aShapeImage);
|
||||
DoDestroy();
|
||||
new (&mShapeImage) UniquePtr<StyleImage>(std::move(aShapeImage));
|
||||
mType = StyleShapeSourceType::Image;
|
||||
}
|
||||
|
||||
imgIRequest* StyleShapeSource::GetShapeImageData() const {
|
||||
if (mType != StyleShapeSourceType::Image) {
|
||||
return nullptr;
|
||||
}
|
||||
return mShapeImage->GetImageRequest();
|
||||
}
|
||||
|
||||
void StyleShapeSource::SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
|
||||
StyleGeometryBox aReferenceBox) {
|
||||
MOZ_ASSERT(aBasicShape);
|
||||
DoDestroy();
|
||||
new (&mBasicShape) UniquePtr<StyleBasicShape>(std::move(aBasicShape));
|
||||
mReferenceBox = aReferenceBox;
|
||||
mType = StyleShapeSourceType::Shape;
|
||||
}
|
||||
|
||||
void StyleShapeSource::SetPath(UniquePtr<StyleSVGPath> aPath) {
|
||||
MOZ_ASSERT(aPath);
|
||||
DoDestroy();
|
||||
new (&mSVGPath) UniquePtr<StyleSVGPath>(std::move(aPath));
|
||||
mType = StyleShapeSourceType::Path;
|
||||
}
|
||||
|
||||
void StyleShapeSource::TriggerImageLoads(
|
||||
Document& aDocument, const StyleShapeSource* aOldShapeSource) {
|
||||
if (GetType() != StyleShapeSourceType::Image) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* oldShapeImage = (aOldShapeSource && aOldShapeSource->GetType() ==
|
||||
StyleShapeSourceType::Image)
|
||||
? &aOldShapeSource->ShapeImage()
|
||||
: nullptr;
|
||||
mShapeImage->ResolveImage(aDocument, oldShapeImage);
|
||||
}
|
||||
|
||||
void StyleShapeSource::SetReferenceBox(StyleGeometryBox aReferenceBox) {
|
||||
DoDestroy();
|
||||
mReferenceBox = aReferenceBox;
|
||||
mType = StyleShapeSourceType::Box;
|
||||
}
|
||||
|
||||
void StyleShapeSource::DoCopy(const StyleShapeSource& aOther) {
|
||||
switch (aOther.mType) {
|
||||
case StyleShapeSourceType::None:
|
||||
mReferenceBox = StyleGeometryBox::NoBox;
|
||||
mType = StyleShapeSourceType::None;
|
||||
break;
|
||||
|
||||
case StyleShapeSourceType::Image:
|
||||
SetShapeImage(MakeUnique<StyleImage>(aOther.ShapeImage()));
|
||||
break;
|
||||
|
||||
case StyleShapeSourceType::Shape: {
|
||||
UniquePtr<StyleBasicShape> shape(
|
||||
Servo_CloneBasicShape(&aOther.BasicShape()));
|
||||
// TODO(emilio): This could be a copy-ctor call like above if we teach
|
||||
// cbindgen to generate copy-constructors for tagged unions.
|
||||
SetBasicShape(std::move(shape), aOther.GetReferenceBox());
|
||||
break;
|
||||
}
|
||||
|
||||
case StyleShapeSourceType::Box:
|
||||
SetReferenceBox(aOther.GetReferenceBox());
|
||||
break;
|
||||
|
||||
case StyleShapeSourceType::Path:
|
||||
SetPath(MakeUnique<StyleSVGPath>(aOther.Path()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void StyleShapeSource::DoDestroy() {
|
||||
switch (mType) {
|
||||
case StyleShapeSourceType::Shape:
|
||||
mBasicShape.~UniquePtr<StyleBasicShape>();
|
||||
break;
|
||||
case StyleShapeSourceType::Image:
|
||||
mShapeImage.~UniquePtr<StyleImage>();
|
||||
break;
|
||||
case StyleShapeSourceType::Path:
|
||||
mSVGPath.~UniquePtr<StyleSVGPath>();
|
||||
break;
|
||||
case StyleShapeSourceType::None:
|
||||
case StyleShapeSourceType::Box:
|
||||
// Not a union type, so do nothing.
|
||||
break;
|
||||
}
|
||||
mType = StyleShapeSourceType::None;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// nsStyleSVGReset
|
||||
//
|
||||
|
@ -1111,6 +968,7 @@ nsStyleSVGReset::nsStyleSVGReset(const Document& aDocument)
|
|||
mRy(NonNegativeLengthPercentageOrAuto::Auto()),
|
||||
mR(NonNegativeLengthPercentage::Zero()),
|
||||
mMask(nsStyleImageLayers::LayerType::Mask),
|
||||
mClipPath(StyleClippingShape::None()),
|
||||
mStopColor(StyleColor::Black()),
|
||||
mFloodColor(StyleColor::Black()),
|
||||
mLightingColor(StyleColor::White()),
|
||||
|
@ -2417,7 +2275,8 @@ nsStyleDisplay::nsStyleDisplay(const Document& aDocument)
|
|||
mPerspectiveOrigin(Position::FromPercentage(0.5f)),
|
||||
mVerticalAlign(
|
||||
StyleVerticalAlign::Keyword(StyleVerticalAlignKeyword::Baseline)),
|
||||
mShapeMargin(LengthPercentage::Zero()) {
|
||||
mShapeMargin(LengthPercentage::Zero()),
|
||||
mShapeOutside(StyleFloatAreaShape::None()) {
|
||||
MOZ_COUNT_CTOR(nsStyleDisplay);
|
||||
|
||||
mTransitions[0].SetInitialValues();
|
||||
|
@ -2493,8 +2352,15 @@ void nsStyleDisplay::TriggerImageLoads(Document& aDocument,
|
|||
const nsStyleDisplay* aOldStyle) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mShapeOutside.TriggerImageLoads(
|
||||
aDocument, aOldStyle ? &aOldStyle->mShapeOutside : nullptr);
|
||||
if (mShapeOutside.IsImageOrUrl()) {
|
||||
auto* old = aOldStyle && aOldStyle->mShapeOutside.IsImageOrUrl()
|
||||
? &aOldStyle->mShapeOutside.AsImageOrUrl()
|
||||
: nullptr;
|
||||
// Const-cast is ugly but legit, we could avoid it by generating mut-casts
|
||||
// with cbindgen.
|
||||
const_cast<StyleImage&>(mShapeOutside.AsImageOrUrl())
|
||||
.ResolveImage(aDocument, old);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TransformLike>
|
||||
|
|
|
@ -1130,104 +1130,6 @@ struct StyleAnimation {
|
|||
float mIterationCount; // mozilla::PositiveInfinity<float>() means infinite
|
||||
};
|
||||
|
||||
struct StyleSVGPath final {
|
||||
StyleSVGPath(StyleForgottenArcSlicePtr<StylePathCommand> aPath,
|
||||
StyleFillRule aFill)
|
||||
: mPath(aPath), mFillRule(aFill) {}
|
||||
|
||||
Span<const StylePathCommand> Path() const { return mPath.AsSpan(); }
|
||||
|
||||
StyleFillRule FillRule() const { return mFillRule; }
|
||||
|
||||
bool operator==(const StyleSVGPath& aOther) const {
|
||||
return mPath == aOther.mPath && mFillRule == aOther.mFillRule;
|
||||
}
|
||||
|
||||
bool operator!=(const StyleSVGPath& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
private:
|
||||
StyleArcSlice<StylePathCommand> mPath;
|
||||
StyleFillRule mFillRule = StyleFillRule::Nonzero;
|
||||
};
|
||||
|
||||
struct StyleShapeSource final {
|
||||
StyleShapeSource();
|
||||
|
||||
StyleShapeSource(const StyleShapeSource& aSource);
|
||||
|
||||
~StyleShapeSource();
|
||||
|
||||
StyleShapeSource& operator=(const StyleShapeSource& aOther);
|
||||
|
||||
bool operator==(const StyleShapeSource& aOther) const;
|
||||
|
||||
bool operator!=(const StyleShapeSource& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
StyleShapeSourceType GetType() const { return mType; }
|
||||
|
||||
const StyleImage& ShapeImage() const {
|
||||
MOZ_ASSERT(mType == StyleShapeSourceType::Image,
|
||||
"Wrong shape source type!");
|
||||
MOZ_ASSERT(mShapeImage);
|
||||
return *mShapeImage;
|
||||
}
|
||||
|
||||
// Iff we have "shape-outside:<image>" with an image URI (not a gradient),
|
||||
// this method returns the corresponding imgIRequest*. Else, returns
|
||||
// null.
|
||||
imgIRequest* GetShapeImageData() const;
|
||||
|
||||
void SetShapeImage(UniquePtr<StyleImage> aShapeImage);
|
||||
|
||||
const StyleBasicShape& BasicShape() const {
|
||||
MOZ_ASSERT(mType == StyleShapeSourceType::Shape,
|
||||
"Wrong shape source type!");
|
||||
MOZ_ASSERT(mBasicShape);
|
||||
return *mBasicShape;
|
||||
}
|
||||
|
||||
void SetBasicShape(UniquePtr<mozilla::StyleBasicShape> aBasicShape,
|
||||
StyleGeometryBox aReferenceBox);
|
||||
|
||||
StyleGeometryBox GetReferenceBox() const {
|
||||
MOZ_ASSERT(mType == StyleShapeSourceType::Box ||
|
||||
mType == StyleShapeSourceType::Shape,
|
||||
"Wrong shape source type!");
|
||||
return mReferenceBox;
|
||||
}
|
||||
|
||||
void SetReferenceBox(StyleGeometryBox aReferenceBox);
|
||||
|
||||
const StyleSVGPath& Path() const {
|
||||
MOZ_ASSERT(mType == StyleShapeSourceType::Path, "Wrong shape source type!");
|
||||
MOZ_ASSERT(mSVGPath);
|
||||
return *mSVGPath;
|
||||
}
|
||||
void SetPath(UniquePtr<StyleSVGPath> aPath);
|
||||
|
||||
void TriggerImageLoads(mozilla::dom::Document&,
|
||||
const StyleShapeSource* aOldShapeSource);
|
||||
|
||||
private:
|
||||
void* operator new(size_t) = delete;
|
||||
|
||||
void DoCopy(const StyleShapeSource& aOther);
|
||||
void DoDestroy();
|
||||
|
||||
union {
|
||||
UniquePtr<StyleBasicShape> mBasicShape;
|
||||
UniquePtr<StyleImage> mShapeImage;
|
||||
UniquePtr<StyleSVGPath> mSVGPath;
|
||||
// TODO: Bug 1480665, implement ray() function.
|
||||
};
|
||||
StyleShapeSourceType mType = StyleShapeSourceType::None;
|
||||
StyleGeometryBox mReferenceBox = StyleGeometryBox::NoBox;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
|
||||
|
@ -1371,7 +1273,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
|
|||
// The margin around a shape-outside: <image>.
|
||||
mozilla::NonNegativeLengthPercentage mShapeMargin;
|
||||
|
||||
mozilla::StyleShapeSource mShapeOutside;
|
||||
mozilla::StyleFloatAreaShape mShapeOutside;
|
||||
|
||||
bool HasAppearance() const {
|
||||
return mAppearance != mozilla::StyleAppearance::None;
|
||||
|
@ -1944,9 +1846,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset {
|
|||
|
||||
nsChangeHint CalcDifference(const nsStyleSVGReset& aNewData) const;
|
||||
|
||||
bool HasClipPath() const {
|
||||
return mClipPath.GetType() != mozilla::StyleShapeSourceType::None;
|
||||
}
|
||||
bool HasClipPath() const { return !mClipPath.IsNone(); }
|
||||
|
||||
bool HasMask() const;
|
||||
|
||||
|
@ -1964,7 +1864,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset {
|
|||
mozilla::NonNegativeLengthPercentage mR;
|
||||
|
||||
nsStyleImageLayers mMask;
|
||||
mozilla::StyleShapeSource mClipPath;
|
||||
mozilla::StyleClippingShape mClipPath;
|
||||
mozilla::StyleColor mStopColor;
|
||||
mozilla::StyleColor mFloodColor;
|
||||
mozilla::StyleColor mLightingColor;
|
||||
|
|
|
@ -1261,14 +1261,12 @@ static nsSVGPaintingProperty* GetOrCreateClipPathObserver(
|
|||
"Require first continuation");
|
||||
|
||||
const nsStyleSVGReset* svgStyleReset = aClippedFrame->StyleSVGReset();
|
||||
if (svgStyleReset->mClipPath.GetType() != StyleShapeSourceType::Image) {
|
||||
if (!svgStyleReset->mClipPath.IsImageOrUrl()) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto* url =
|
||||
svgStyleReset->mClipPath.ShapeImage().GetImageRequestURLValue();
|
||||
MOZ_ASSERT(url, "Clip-path only supports url() images");
|
||||
const auto& url = svgStyleReset->mClipPath.AsImageOrUrl();
|
||||
RefPtr<URLAndReferrerInfo> pathURI =
|
||||
ResolveURLUsingLocalRef(aClippedFrame, *url);
|
||||
ResolveURLUsingLocalRef(aClippedFrame, url);
|
||||
return GetPaintingProperty(pathURI, aClippedFrame, ClipPathProperty());
|
||||
}
|
||||
|
||||
|
|
|
@ -28,14 +28,10 @@ using namespace mozilla::gfx;
|
|||
void nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(
|
||||
gfxContext& aContext, nsIFrame* aFrame, const gfxMatrix& aTransform) {
|
||||
auto& clipPathStyle = aFrame->StyleSVGReset()->mClipPath;
|
||||
|
||||
#ifdef DEBUG
|
||||
StyleShapeSourceType type = clipPathStyle.GetType();
|
||||
MOZ_ASSERT(type == StyleShapeSourceType::Shape ||
|
||||
type == StyleShapeSourceType::Box ||
|
||||
type == StyleShapeSourceType::Path,
|
||||
MOZ_ASSERT(clipPathStyle.IsShape() || clipPathStyle.IsBox() ||
|
||||
clipPathStyle.IsPath(),
|
||||
"This is used with basic-shape, geometry-box, and path() only");
|
||||
#endif
|
||||
|
||||
nsCSSClipPathInstance instance(aFrame, clipPathStyle);
|
||||
|
||||
aContext.NewPath();
|
||||
|
@ -52,11 +48,10 @@ void nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(
|
|||
bool nsCSSClipPathInstance::HitTestBasicShapeOrPathClip(
|
||||
nsIFrame* aFrame, const gfxPoint& aPoint) {
|
||||
auto& clipPathStyle = aFrame->StyleSVGReset()->mClipPath;
|
||||
StyleShapeSourceType type = clipPathStyle.GetType();
|
||||
MOZ_ASSERT(type != StyleShapeSourceType::None, "unexpected none value");
|
||||
MOZ_ASSERT(!clipPathStyle.IsNone(), "unexpected none value");
|
||||
// In the future nsCSSClipPathInstance may handle <clipPath> references as
|
||||
// well. For the time being return early.
|
||||
if (type == StyleShapeSourceType::Image) {
|
||||
if (clipPathStyle.IsImageOrUrl()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -73,10 +68,9 @@ bool nsCSSClipPathInstance::HitTestBasicShapeOrPathClip(
|
|||
|
||||
/* static */
|
||||
Maybe<Rect> nsCSSClipPathInstance::GetBoundingRectForBasicShapeOrPathClip(
|
||||
nsIFrame* aFrame, const StyleShapeSource& aClipPathStyle) {
|
||||
MOZ_ASSERT(aClipPathStyle.GetType() == StyleShapeSourceType::Shape ||
|
||||
aClipPathStyle.GetType() == StyleShapeSourceType::Box ||
|
||||
aClipPathStyle.GetType() == StyleShapeSourceType::Path);
|
||||
nsIFrame* aFrame, const StyleClippingShape& aClipPathStyle) {
|
||||
MOZ_ASSERT(aClipPathStyle.IsShape() || aClipPathStyle.IsBox() ||
|
||||
aClipPathStyle.IsPath());
|
||||
|
||||
nsCSSClipPathInstance instance(aFrame, aClipPathStyle);
|
||||
|
||||
|
@ -89,15 +83,20 @@ Maybe<Rect> nsCSSClipPathInstance::GetBoundingRectForBasicShapeOrPathClip(
|
|||
|
||||
already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPath(
|
||||
DrawTarget* aDrawTarget, const gfxMatrix& aTransform) {
|
||||
if (mClipPathStyle.GetType() == StyleShapeSourceType::Path) {
|
||||
if (mClipPathStyle.IsPath()) {
|
||||
return CreateClipPathPath(aDrawTarget);
|
||||
}
|
||||
|
||||
nscoord appUnitsPerDevPixel =
|
||||
mTargetFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
|
||||
nsRect r = nsLayoutUtils::ComputeGeometryBox(
|
||||
mTargetFrame, mClipPathStyle.GetReferenceBox());
|
||||
nsRect r;
|
||||
if (mClipPathStyle.IsBox()) {
|
||||
r = nsLayoutUtils::ComputeGeometryBox(mTargetFrame, mClipPathStyle.AsBox());
|
||||
} else {
|
||||
r = nsLayoutUtils::ComputeGeometryBox(mTargetFrame,
|
||||
mClipPathStyle.AsShape()._1);
|
||||
}
|
||||
|
||||
gfxRect rr(r.x, r.y, r.width, r.height);
|
||||
rr.Scale(1.0 / AppUnitsPerCSSPixel());
|
||||
|
@ -107,17 +106,17 @@ already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPath(
|
|||
|
||||
r = nsRect(int(rr.x), int(rr.y), int(rr.width), int(rr.height));
|
||||
|
||||
if (mClipPathStyle.GetType() == StyleShapeSourceType::Box) {
|
||||
if (mClipPathStyle.IsBox()) {
|
||||
RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
|
||||
AppendRectToPath(builder, NSRectToRect(r, appUnitsPerDevPixel), true);
|
||||
return builder->Finish();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mClipPathStyle.GetType() == StyleShapeSourceType::Shape);
|
||||
MOZ_ASSERT(mClipPathStyle.IsShape());
|
||||
|
||||
r = ToAppUnits(r.ToNearestPixels(appUnitsPerDevPixel), appUnitsPerDevPixel);
|
||||
|
||||
const auto& basicShape = mClipPathStyle.BasicShape();
|
||||
const auto& basicShape = *mClipPathStyle.AsShape()._0;
|
||||
switch (basicShape.tag) {
|
||||
case StyleBasicShape::Tag::Circle:
|
||||
return CreateClipPathCircle(aDrawTarget, r);
|
||||
|
@ -138,7 +137,7 @@ already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPath(
|
|||
|
||||
already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathCircle(
|
||||
DrawTarget* aDrawTarget, const nsRect& aRefBox) {
|
||||
const auto& basicShape = mClipPathStyle.BasicShape();
|
||||
const auto& basicShape = *mClipPathStyle.AsShape()._0;
|
||||
|
||||
RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
|
||||
|
||||
|
@ -155,7 +154,7 @@ already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathCircle(
|
|||
|
||||
already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathEllipse(
|
||||
DrawTarget* aDrawTarget, const nsRect& aRefBox) {
|
||||
const auto& basicShape = mClipPathStyle.BasicShape();
|
||||
const auto& basicShape = *mClipPathStyle.AsShape()._0;
|
||||
|
||||
RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
|
||||
|
||||
|
@ -173,7 +172,7 @@ already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathEllipse(
|
|||
|
||||
already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathPolygon(
|
||||
DrawTarget* aDrawTarget, const nsRect& aRefBox) {
|
||||
const auto& basicShape = mClipPathStyle.BasicShape();
|
||||
const auto& basicShape = *mClipPathStyle.AsShape()._0;
|
||||
auto fillRule = basicShape.AsPolygon().fill == StyleFillRule::Nonzero
|
||||
? FillRule::FILL_WINDING
|
||||
: FillRule::FILL_EVEN_ODD;
|
||||
|
@ -198,7 +197,7 @@ already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathPolygon(
|
|||
|
||||
already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathInset(
|
||||
DrawTarget* aDrawTarget, const nsRect& aRefBox) {
|
||||
const auto& basicShape = mClipPathStyle.BasicShape();
|
||||
const auto& basicShape = *mClipPathStyle.AsShape()._0;
|
||||
|
||||
RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
|
||||
|
||||
|
@ -224,13 +223,13 @@ already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathInset(
|
|||
|
||||
already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPathPath(
|
||||
DrawTarget* aDrawTarget) {
|
||||
const StyleSVGPath& path = mClipPathStyle.Path();
|
||||
const auto& path = mClipPathStyle.AsPath();
|
||||
|
||||
RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder(
|
||||
path.FillRule() == StyleFillRule::Nonzero ? FillRule::FILL_WINDING
|
||||
: FillRule::FILL_EVEN_ODD);
|
||||
path.fill == StyleFillRule::Nonzero ? FillRule::FILL_WINDING
|
||||
: FillRule::FILL_EVEN_ODD);
|
||||
float scale = float(AppUnitsPerCSSPixel()) /
|
||||
mTargetFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
return SVGPathData::BuildPath(path.Path(), builder, StyleStrokeLinecap::Butt,
|
||||
0.0, scale);
|
||||
return SVGPathData::BuildPath(path.path._0.AsSpan(), builder,
|
||||
StyleStrokeLinecap::Butt, 0.0, scale);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class gfxContext;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class nsCSSClipPathInstance {
|
||||
class MOZ_STACK_CLASS nsCSSClipPathInstance {
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
typedef mozilla::gfx::Path Path;
|
||||
typedef mozilla::gfx::Rect Rect;
|
||||
|
@ -31,11 +31,11 @@ class nsCSSClipPathInstance {
|
|||
const gfxPoint& aPoint);
|
||||
|
||||
static Maybe<Rect> GetBoundingRectForBasicShapeOrPathClip(
|
||||
nsIFrame* aFrame, const StyleShapeSource& aClipPathStyle);
|
||||
nsIFrame* aFrame, const StyleClippingShape& aClipPathStyle);
|
||||
|
||||
private:
|
||||
explicit nsCSSClipPathInstance(nsIFrame* aFrame,
|
||||
const StyleShapeSource& aClipPathStyle)
|
||||
const StyleClippingShape& aClipPathStyle)
|
||||
: mTargetFrame(aFrame), mClipPathStyle(aClipPathStyle) {}
|
||||
|
||||
already_AddRefed<Path> CreateClipPath(DrawTarget* aDrawTarget,
|
||||
|
@ -59,7 +59,7 @@ class nsCSSClipPathInstance {
|
|||
* The frame for the element that is currently being clipped.
|
||||
*/
|
||||
nsIFrame* mTargetFrame;
|
||||
StyleShapeSource mClipPathStyle;
|
||||
const StyleClippingShape& mClipPathStyle;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -183,12 +183,11 @@ bool nsSVGIntegrationUtils::UsingSimpleClipPathForFrame(
|
|||
}
|
||||
|
||||
const auto& clipPath = style->mClipPath;
|
||||
if (clipPath.GetType() != StyleShapeSourceType::Shape) {
|
||||
if (!clipPath.IsShape()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& shape = clipPath.BasicShape();
|
||||
return !shape.IsPolygon();
|
||||
return !clipPath.AsShape()._0->IsPolygon();
|
||||
}
|
||||
|
||||
nsPoint nsSVGIntegrationUtils::GetOffsetToBoundingBox(nsIFrame* aFrame) {
|
||||
|
|
|
@ -429,6 +429,8 @@ float nsSVGUtils::ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity) {
|
|||
|
||||
void nsSVGUtils::DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
|
||||
MaskUsage& aUsage) {
|
||||
using ClipPathType = StyleClippingShape::Tag;
|
||||
|
||||
aUsage.opacity = ComputeOpacity(aFrame, aHandleOpacity);
|
||||
|
||||
nsIFrame* firstFrame =
|
||||
|
@ -444,11 +446,10 @@ void nsSVGUtils::DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
|
|||
nsSVGClipPathFrame* clipPathFrame;
|
||||
// XXX check return value?
|
||||
SVGObserverUtils::GetAndObserveClipPath(firstFrame, &clipPathFrame);
|
||||
MOZ_ASSERT(!clipPathFrame ||
|
||||
svgReset->mClipPath.GetType() == StyleShapeSourceType::Image);
|
||||
MOZ_ASSERT(!clipPathFrame || svgReset->mClipPath.IsImageOrUrl());
|
||||
|
||||
switch (svgReset->mClipPath.GetType()) {
|
||||
case StyleShapeSourceType::Image:
|
||||
switch (svgReset->mClipPath.tag) {
|
||||
case ClipPathType::ImageOrUrl:
|
||||
if (clipPathFrame) {
|
||||
if (clipPathFrame->IsTrivial()) {
|
||||
aUsage.shouldApplyClipPath = true;
|
||||
|
@ -457,12 +458,12 @@ void nsSVGUtils::DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
|
|||
}
|
||||
}
|
||||
break;
|
||||
case StyleShapeSourceType::Shape:
|
||||
case StyleShapeSourceType::Box:
|
||||
case StyleShapeSourceType::Path:
|
||||
case ClipPathType::Shape:
|
||||
case ClipPathType::Box:
|
||||
case ClipPathType::Path:
|
||||
aUsage.shouldApplyBasicShapeOrPath = true;
|
||||
break;
|
||||
case StyleShapeSourceType::None:
|
||||
case ClipPathType::None:
|
||||
MOZ_ASSERT(!aUsage.shouldGenerateClipMaskLayer &&
|
||||
!aUsage.shouldApplyClipPath &&
|
||||
!aUsage.shouldApplyBasicShapeOrPath);
|
||||
|
|
|
@ -15,159 +15,6 @@ use crate::stylesheets::RulesMutateError;
|
|||
use crate::values::computed::transform::Matrix3D;
|
||||
use crate::values::computed::TextAlign;
|
||||
|
||||
pub mod basic_shape {
|
||||
//! Conversions from and to CSS shape representations.
|
||||
use crate::gecko_bindings::structs::{
|
||||
StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
|
||||
};
|
||||
use crate::values::computed::basic_shape::{BasicShape, ClippingShape, FloatAreaShape};
|
||||
use crate::values::computed::motion::OffsetPath;
|
||||
use crate::values::generics::basic_shape::{ShapeGeometryBox, Path, ShapeBox, ShapeSource};
|
||||
use crate::values::specified::SVGPathData;
|
||||
|
||||
impl StyleShapeSource {
|
||||
/// Convert StyleShapeSource to ShapeSource except URL and Image
|
||||
/// types.
|
||||
fn to_shape_source<ReferenceBox, ImageOrUrl>(
|
||||
&self,
|
||||
) -> Option<ShapeSource<BasicShape, ReferenceBox, ImageOrUrl>>
|
||||
where
|
||||
ReferenceBox: From<StyleGeometryBox> + Default + PartialEq,
|
||||
{
|
||||
match self.mType {
|
||||
StyleShapeSourceType::None => Some(ShapeSource::None),
|
||||
StyleShapeSourceType::Box => Some(ShapeSource::Box(self.mReferenceBox.into())),
|
||||
StyleShapeSourceType::Shape => {
|
||||
let other_shape = unsafe { &*self.__bindgen_anon_1.mBasicShape.as_ref().mPtr };
|
||||
let shape = Box::new(other_shape.clone());
|
||||
let reference_box = self.mReferenceBox.into();
|
||||
Some(ShapeSource::Shape(shape, reference_box))
|
||||
},
|
||||
StyleShapeSourceType::Image => None,
|
||||
StyleShapeSourceType::Path => {
|
||||
let path = self.to_svg_path().expect("expect an SVGPathData");
|
||||
let fill = unsafe { &*self.__bindgen_anon_1.mSVGPath.as_ref().mPtr }.mFillRule;
|
||||
Some(ShapeSource::Path(Path { fill, path }))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a SVGPathData from StyleShapeSource if possible.
|
||||
fn to_svg_path(&self) -> Option<SVGPathData> {
|
||||
match self.mType {
|
||||
StyleShapeSourceType::Path => {
|
||||
let gecko_path = unsafe { &*self.__bindgen_anon_1.mSVGPath.as_ref().mPtr };
|
||||
Some(SVGPathData(gecko_path.mPath.clone()))
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a StyleShapeSource> for ClippingShape {
|
||||
fn from(other: &'a StyleShapeSource) -> Self {
|
||||
match other.mType {
|
||||
StyleShapeSourceType::Image => unsafe {
|
||||
use crate::values::generics::image::Image as GenericImage;
|
||||
|
||||
let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
|
||||
match *shape_image {
|
||||
GenericImage::Url(ref url) => ShapeSource::ImageOrUrl(url.0.clone()),
|
||||
_ => panic!("ClippingShape doesn't support non-url images"),
|
||||
}
|
||||
},
|
||||
_ => other
|
||||
.to_shape_source()
|
||||
.expect("Couldn't convert to StyleSource!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a StyleShapeSource> for FloatAreaShape {
|
||||
fn from(other: &'a StyleShapeSource) -> Self {
|
||||
match other.mType {
|
||||
StyleShapeSourceType::Image => unsafe {
|
||||
let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
|
||||
ShapeSource::ImageOrUrl(shape_image.clone())
|
||||
},
|
||||
_ => other
|
||||
.to_shape_source()
|
||||
.expect("Couldn't convert to StyleSource!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a StyleShapeSource> for OffsetPath {
|
||||
fn from(other: &'a StyleShapeSource) -> Self {
|
||||
use crate::values::generics::motion::GenericOffsetPath;
|
||||
match other.mType {
|
||||
StyleShapeSourceType::Path => GenericOffsetPath::Path(
|
||||
other.to_svg_path().expect("Cannot convert to SVGPathData"),
|
||||
),
|
||||
StyleShapeSourceType::None => OffsetPath::none(),
|
||||
StyleShapeSourceType::Shape |
|
||||
StyleShapeSourceType::Box |
|
||||
StyleShapeSourceType::Image => unreachable!("Unsupported offset-path type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ShapeBox> for StyleGeometryBox {
|
||||
fn from(reference: ShapeBox) -> Self {
|
||||
use crate::gecko_bindings::structs::StyleGeometryBox::*;
|
||||
match reference {
|
||||
ShapeBox::ContentBox => ContentBox,
|
||||
ShapeBox::PaddingBox => PaddingBox,
|
||||
ShapeBox::BorderBox => BorderBox,
|
||||
ShapeBox::MarginBox => MarginBox,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ShapeGeometryBox> for StyleGeometryBox {
|
||||
fn from(reference: ShapeGeometryBox) -> Self {
|
||||
use crate::gecko_bindings::structs::StyleGeometryBox::*;
|
||||
match reference {
|
||||
ShapeGeometryBox::ShapeBox(shape_box) => From::from(shape_box),
|
||||
ShapeGeometryBox::FillBox => FillBox,
|
||||
ShapeGeometryBox::StrokeBox => StrokeBox,
|
||||
ShapeGeometryBox::ViewBox => ViewBox,
|
||||
ShapeGeometryBox::ElementDependent => NoBox,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StyleGeometryBox> for ShapeGeometryBox {
|
||||
fn from(reference: StyleGeometryBox) -> Self {
|
||||
use crate::gecko_bindings::structs::StyleGeometryBox::*;
|
||||
match reference {
|
||||
ContentBox => ShapeGeometryBox::ShapeBox(ShapeBox::ContentBox),
|
||||
PaddingBox => ShapeGeometryBox::ShapeBox(ShapeBox::PaddingBox),
|
||||
BorderBox => ShapeGeometryBox::ShapeBox(ShapeBox::BorderBox),
|
||||
MarginBox => ShapeGeometryBox::ShapeBox(ShapeBox::MarginBox),
|
||||
FillBox => ShapeGeometryBox::FillBox,
|
||||
StrokeBox => ShapeGeometryBox::StrokeBox,
|
||||
ViewBox => ShapeGeometryBox::ViewBox,
|
||||
NoBox => ShapeGeometryBox::ElementDependent,
|
||||
NoClip | Text | MozAlmostPadding => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StyleGeometryBox> for ShapeBox {
|
||||
fn from(reference: StyleGeometryBox) -> Self {
|
||||
use crate::gecko_bindings::structs::StyleGeometryBox::*;
|
||||
match reference {
|
||||
ContentBox => ShapeBox::ContentBox,
|
||||
PaddingBox => ShapeBox::PaddingBox,
|
||||
BorderBox => ShapeBox::BorderBox,
|
||||
MarginBox => ShapeBox::MarginBox,
|
||||
_ => panic!("Unexpected StyleGeometryBox while converting to ShapeBox"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RulesMutateError> for nsresult {
|
||||
fn from(other: RulesMutateError) -> Self {
|
||||
match other {
|
||||
|
|
|
@ -41,7 +41,6 @@ use std::mem::{forget, MaybeUninit};
|
|||
use std::{cmp, ops, ptr};
|
||||
use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
|
||||
use crate::values::computed::{Percentage, TransitionProperty};
|
||||
use crate::values::computed::url::ComputedImageUrl;
|
||||
use crate::values::computed::BorderStyle;
|
||||
use crate::values::computed::font::FontSize;
|
||||
use crate::values::generics::column::ColumnCount;
|
||||
|
@ -1433,7 +1432,7 @@ fn static_assert() {
|
|||
animation-iteration-count animation-timing-function
|
||||
clear transition-duration transition-delay
|
||||
transition-timing-function transition-property
|
||||
shape-outside -webkit-line-clamp""" %>
|
||||
-webkit-line-clamp""" %>
|
||||
<%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
|
||||
#[inline]
|
||||
pub fn set_display(&mut self, v: longhands::display::computed_value::T) {
|
||||
|
@ -1693,8 +1692,6 @@ fn static_assert() {
|
|||
|
||||
${impl_animation_timing_function()}
|
||||
|
||||
<% impl_shape_source("shape_outside", "mShapeOutside") %>
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set__webkit_line_clamp(&mut self, v: longhands::_webkit_line_clamp::computed_value::T) {
|
||||
self.gecko.mLineClamp = match v {
|
||||
|
@ -2202,84 +2199,8 @@ fn static_assert() {
|
|||
}
|
||||
</%self:impl_trait>
|
||||
|
||||
// Set SVGPathData to StyleShapeSource.
|
||||
fn set_style_svg_path(
|
||||
shape_source: &mut structs::mozilla::StyleShapeSource,
|
||||
servo_path: values::specified::svg_path::SVGPathData,
|
||||
fill: values::generics::basic_shape::FillRule,
|
||||
) {
|
||||
// Setup path.
|
||||
unsafe {
|
||||
bindings::Gecko_SetToSVGPath(
|
||||
shape_source,
|
||||
servo_path.0.forget(),
|
||||
fill,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
<%def name="impl_shape_source(ident, gecko_ffi_name)">
|
||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||
use crate::values::generics::basic_shape::ShapeSource;
|
||||
use crate::gecko_bindings::structs::StyleShapeSourceType;
|
||||
|
||||
let ref mut ${ident} = self.gecko.${gecko_ffi_name};
|
||||
|
||||
// clean up existing struct.
|
||||
unsafe { bindings::Gecko_DestroyShapeSource(${ident}) };
|
||||
|
||||
${ident}.mType = StyleShapeSourceType::None;
|
||||
|
||||
match v {
|
||||
ShapeSource::None => {} // don't change the type
|
||||
ShapeSource::ImageOrUrl(image) => {
|
||||
% if ident == "clip_path":
|
||||
use crate::values::generics::image::Image;
|
||||
|
||||
let image = Image::Url(ComputedImageUrl(image));
|
||||
% endif
|
||||
unsafe {
|
||||
bindings::Gecko_NewShapeImage(${ident});
|
||||
let style_image = &mut *${ident}.__bindgen_anon_1.mShapeImage.as_mut().mPtr;
|
||||
*style_image = image;
|
||||
}
|
||||
}
|
||||
ShapeSource::Box(reference) => {
|
||||
${ident}.mReferenceBox = reference.into();
|
||||
${ident}.mType = StyleShapeSourceType::Box;
|
||||
}
|
||||
ShapeSource::Path(p) => set_style_svg_path(${ident}, p.path, p.fill),
|
||||
ShapeSource::Shape(servo_shape, reference_box) => {
|
||||
unsafe {
|
||||
${ident}.__bindgen_anon_1.mBasicShape.as_mut().mPtr =
|
||||
Box::into_raw(servo_shape);
|
||||
}
|
||||
${ident}.mReferenceBox = reference_box.into();
|
||||
${ident}.mType = StyleShapeSourceType::Shape;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
(&self.gecko.${gecko_ffi_name}).into()
|
||||
}
|
||||
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
use crate::gecko_bindings::bindings::Gecko_CopyShapeSourceFrom;
|
||||
unsafe {
|
||||
Gecko_CopyShapeSourceFrom(&mut self.gecko.${gecko_ffi_name}, &other.gecko.${gecko_ffi_name});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_${ident}(&mut self, other: &Self) {
|
||||
self.copy_${ident}_from(other)
|
||||
}
|
||||
</%def>
|
||||
|
||||
<% skip_svg_longhands = """
|
||||
mask-mode mask-repeat mask-clip mask-origin mask-composite mask-position-x mask-position-y mask-size mask-image
|
||||
clip-path
|
||||
"""
|
||||
%>
|
||||
<%self:impl_trait style_struct_name="SVG"
|
||||
|
@ -2288,7 +2209,6 @@ clip-path
|
|||
<% impl_common_image_layer_properties("mask") %>
|
||||
<% impl_simple_image_array_property("mode", "mask", "mMask", "mMaskMode", "SVG") %>
|
||||
<% impl_simple_image_array_property("composite", "mask", "mMask", "mComposite", "SVG") %>
|
||||
<% impl_shape_source("clip_path", "mClipPath") %>
|
||||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="InheritedSVG"
|
||||
|
|
|
@ -205,6 +205,8 @@ include = [
|
|||
"JustifyContent",
|
||||
"TransformStyle",
|
||||
"Image",
|
||||
"ClippingShape",
|
||||
"FloatAreaShape",
|
||||
]
|
||||
item_types = ["enums", "structs", "unions", "typedefs", "functions", "constants"]
|
||||
renaming_overrides_prefixing = true
|
||||
|
|
Загрузка…
Ссылка в новой задаче