mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 18:04:46 +00:00
Bug 1614198 - Use cbindgen instead of nsStyleImage. r=aosmond
The trickier part is that we represent -moz-image-rect as a Rect() type instead of image with non-null clip-rect. So we need to add a bit of code to distinguish "image request types" from other types of images. But it's not too annoying, and we need to do the same for fancier images like image-set and such whenever we implement it, so seems nice to get rid of most explicit usages of nsStyleImage::GetType(). Differential Revision: https://phabricator.services.mozilla.com/D62164 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
21f524eca1
commit
006e5cca66
@ -26,8 +26,8 @@ namespace image {
|
||||
* SUCCESS_NOT_COMPLETE: The image was drawn successfully and completely, but
|
||||
* it hasn't notified about the sync-decode yet. This can only happen when
|
||||
* layout pokes at the internal image state beforehand via
|
||||
* nsStyleImage::StartDecoding. This should probably go away eventually,
|
||||
* somehow, see bug 1471583.
|
||||
* StyleImage::StartDecoding. This should probably go away eventually, somehow,
|
||||
* see bug 1471583.
|
||||
*
|
||||
* INCOMPLETE: We successfully drew a frame that was partially decoded. (Note
|
||||
* that successfully drawing a partially decoded frame may not actually draw any
|
||||
|
@ -519,7 +519,7 @@ void nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
// Create separate items for each background layer.
|
||||
const nsStyleImageLayers& layers = bg->StyleBackground()->mImage;
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, layers) {
|
||||
if (layers.mLayers[i].mImage.IsEmpty()) {
|
||||
if (layers.mLayers[i].mImage.IsNone()) {
|
||||
continue;
|
||||
}
|
||||
if (layers.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
|
||||
|
@ -237,7 +237,7 @@ void nsColumnSetFrame::CreateBorderRenderers(
|
||||
// Assert that we're not drawing a border-image here; if we were, we
|
||||
// couldn't ignore the ImgDrawResult that PaintBorderWithStyleBorder
|
||||
// returns.
|
||||
MOZ_ASSERT(border.mBorderImageSource.GetType() == eStyleImageType_Null);
|
||||
MOZ_ASSERT(border.mBorderImageSource.IsNone());
|
||||
|
||||
gfx::DrawTarget* dt = aCtx ? aCtx->GetDrawTarget() : nullptr;
|
||||
bool borderIsEmpty = false;
|
||||
|
@ -569,7 +569,7 @@ class nsFloatManager::ShapeInfo {
|
||||
WritingMode aWM,
|
||||
const nsSize& aContainerSize);
|
||||
|
||||
static UniquePtr<ShapeInfo> CreateImageShape(const nsStyleImage& aShapeImage,
|
||||
static UniquePtr<ShapeInfo> CreateImageShape(const StyleImage& aShapeImage,
|
||||
float aShapeImageThreshold,
|
||||
nscoord aShapeMargin,
|
||||
nsIFrame* const aFrame,
|
||||
@ -2665,7 +2665,7 @@ nsFloatManager::ShapeInfo::CreatePolygon(const StyleBasicShape& aBasicShape,
|
||||
}
|
||||
|
||||
/* static */ UniquePtr<nsFloatManager::ShapeInfo>
|
||||
nsFloatManager::ShapeInfo::CreateImageShape(const nsStyleImage& aShapeImage,
|
||||
nsFloatManager::ShapeInfo::CreateImageShape(const StyleImage& aShapeImage,
|
||||
float aShapeImageThreshold,
|
||||
nscoord aShapeMargin,
|
||||
nsIFrame* const aFrame,
|
||||
@ -2682,10 +2682,8 @@ nsFloatManager::ShapeInfo::CreateImageShape(const nsStyleImage& aShapeImage,
|
||||
if (!imageRenderer.PrepareImage()) {
|
||||
// The image is not ready yet. Boost its loading priority since it will
|
||||
// affect layout.
|
||||
if (aShapeImage.GetType() == eStyleImageType_Image) {
|
||||
if (imgRequestProxy* req = aShapeImage.GetImageData()) {
|
||||
req->BoostPriority(imgIRequest::CATEGORY_SIZE_QUERY);
|
||||
}
|
||||
if (imgRequestProxy* req = aShapeImage.GetImageRequest()) {
|
||||
req->BoostPriority(imgIRequest::CATEGORY_SIZE_QUERY);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -923,8 +923,8 @@ static void CompareLayers(
|
||||
const nsStyleImageLayers* aSecondLayers,
|
||||
const std::function<void(imgRequestProxy* aReq)>& aCallback) {
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aFirstLayers)) {
|
||||
const nsStyleImage& image = aFirstLayers->mLayers[i].mImage;
|
||||
if (image.GetType() != eStyleImageType_Image || !image.IsResolved()) {
|
||||
const auto& image = aFirstLayers->mLayers[i].mImage;
|
||||
if (!image.IsImageRequestType() || !image.IsResolved()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -932,8 +932,8 @@ static void CompareLayers(
|
||||
// be different with the corresponded one in aSecondLayers
|
||||
if (!aSecondLayers || i >= aSecondLayers->mImageCount ||
|
||||
(!aSecondLayers->mLayers[i].mImage.IsResolved() ||
|
||||
!image.ImageDataEquals(aSecondLayers->mLayers[i].mImage))) {
|
||||
if (imgRequestProxy* req = image.GetImageData()) {
|
||||
image.GetImageRequest() != aSecondLayers->mLayers[i].mImage.GetImageRequest())) {
|
||||
if (imgRequestProxy* req = image.GetImageRequest()) {
|
||||
aCallback(req);
|
||||
}
|
||||
}
|
||||
@ -5523,12 +5523,8 @@ nsIFrame::ContentOffsets nsFrame::CalcContentOffsetsFromFramePoint(
|
||||
return OffsetsForSingleFrame(this, aPoint);
|
||||
}
|
||||
|
||||
bool nsIFrame::AssociateImage(const nsStyleImage& aImage) {
|
||||
if (aImage.GetType() != eStyleImageType_Image) {
|
||||
return false;
|
||||
}
|
||||
|
||||
imgRequestProxy* req = aImage.GetImageData();
|
||||
bool nsIFrame::AssociateImage(const StyleImage& aImage) {
|
||||
imgRequestProxy* req = aImage.GetImageRequest();
|
||||
if (!req) {
|
||||
return false;
|
||||
}
|
||||
@ -5540,12 +5536,8 @@ bool nsIFrame::AssociateImage(const nsStyleImage& aImage) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void nsIFrame::DisassociateImage(const nsStyleImage& aImage) {
|
||||
if (aImage.GetType() != eStyleImageType_Image) {
|
||||
return;
|
||||
}
|
||||
|
||||
imgRequestProxy* req = aImage.GetImageData();
|
||||
void nsIFrame::DisassociateImage(const StyleImage& aImage) {
|
||||
imgRequestProxy* req = aImage.GetImageRequest();
|
||||
if (!req) {
|
||||
return;
|
||||
}
|
||||
|
@ -2025,13 +2025,13 @@ class nsIFrame : public nsQueryFrame {
|
||||
*
|
||||
* Returns whether the image was in fact associated with the frame.
|
||||
*/
|
||||
MOZ_MUST_USE bool AssociateImage(const nsStyleImage&);
|
||||
MOZ_MUST_USE bool AssociateImage(const mozilla::StyleImage&);
|
||||
|
||||
/**
|
||||
* This needs to be called if the above caller returned true, once the above
|
||||
* caller doesn't care about getting notified anymore.
|
||||
*/
|
||||
void DisassociateImage(const nsStyleImage&);
|
||||
void DisassociateImage(const mozilla::StyleImage&);
|
||||
|
||||
enum class AllowCustomCursorImage {
|
||||
No,
|
||||
|
@ -1355,8 +1355,7 @@ ImgDrawResult nsImageFrame::DisplayAltFeedback(gfxContext& aRenderingContext,
|
||||
// Assert that we're not drawing a border-image here; if we were, we
|
||||
// couldn't ignore the ImgDrawResult that PaintBorderWithStyleBorder
|
||||
// returns.
|
||||
MOZ_ASSERT(recessedBorder.mBorderImageSource.GetType() ==
|
||||
eStyleImageType_Null);
|
||||
MOZ_ASSERT(recessedBorder.mBorderImageSource.IsNone());
|
||||
|
||||
Unused << nsCSSRendering::PaintBorderWithStyleBorder(
|
||||
PresContext(), aRenderingContext, this, inner, inner, recessedBorder,
|
||||
@ -1538,8 +1537,7 @@ ImgDrawResult nsImageFrame::DisplayAltFeedbackWithoutLayer(
|
||||
// Assert that we're not drawing a border-image here; if we were, we
|
||||
// couldn't ignore the ImgDrawResult that PaintBorderWithStyleBorder
|
||||
// returns.
|
||||
MOZ_ASSERT(recessedBorder.mBorderImageSource.GetType() ==
|
||||
eStyleImageType_Null);
|
||||
MOZ_ASSERT(recessedBorder.mBorderImageSource.IsNone());
|
||||
|
||||
nsRect rect = nsRect(aPt, GetSize());
|
||||
Unused << nsCSSRendering::CreateWebRenderCommandsForBorderWithStyleBorder(
|
||||
|
@ -702,9 +702,9 @@ ImgDrawResult nsCSSRendering::CreateWebRenderCommandsForBorderWithStyleBorder(
|
||||
mozilla::layers::RenderRootStateManager* aManager,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
const nsStyleBorder& aStyleBorder) {
|
||||
auto& borderImage = aStyleBorder.mBorderImageSource;
|
||||
// First try to create commands for simple borders.
|
||||
nsStyleImageType type = aStyleBorder.mBorderImageSource.GetType();
|
||||
if (type == eStyleImageType_Null) {
|
||||
if (borderImage.IsNone()) {
|
||||
CreateWebRenderCommandsForNullBorder(
|
||||
aItem, aForFrame, aBorderArea, aBuilder, aResources, aSc, aStyleBorder);
|
||||
return ImgDrawResult::SUCCESS;
|
||||
@ -712,7 +712,7 @@ ImgDrawResult nsCSSRendering::CreateWebRenderCommandsForBorderWithStyleBorder(
|
||||
|
||||
// Next we try image and gradient borders. Gradients are not supported at
|
||||
// this very moment.
|
||||
if (type != eStyleImageType_Image) {
|
||||
if (!borderImage.IsImageRequestType()) {
|
||||
return ImgDrawResult::NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@ -845,7 +845,7 @@ ImgDrawResult nsCSSRendering::PaintBorderWithStyleBorder(
|
||||
}
|
||||
}
|
||||
|
||||
if (!aStyleBorder.mBorderImageSource.IsEmpty()) {
|
||||
if (!aStyleBorder.mBorderImageSource.IsNone()) {
|
||||
ImgDrawResult result = ImgDrawResult::SUCCESS;
|
||||
|
||||
uint32_t irFlags = 0;
|
||||
@ -873,7 +873,7 @@ ImgDrawResult nsCSSRendering::PaintBorderWithStyleBorder(
|
||||
// If we had a border-image, but it wasn't loaded, then we should return
|
||||
// ImgDrawResult::NOT_READY; we'll want to try again if we do a paint with
|
||||
// sync decoding enabled.
|
||||
if (aStyleBorder.mBorderImageSource.GetType() != eStyleImageType_Null) {
|
||||
if (!aStyleBorder.mBorderImageSource.IsNone()) {
|
||||
result = ImgDrawResult::NOT_READY;
|
||||
}
|
||||
|
||||
@ -910,7 +910,7 @@ Maybe<nsCSSBorderRenderer> nsCSSRendering::CreateBorderRendererWithStyleBorder(
|
||||
const nsRect& aDirtyRect, const nsRect& aBorderArea,
|
||||
const nsStyleBorder& aStyleBorder, ComputedStyle* aStyle,
|
||||
bool* aOutBorderIsEmpty, Sides aSkipSides) {
|
||||
if (aStyleBorder.mBorderImageSource.GetType() != eStyleImageType_Null) {
|
||||
if (!aStyleBorder.mBorderImageSource.IsNone()) {
|
||||
return Nothing();
|
||||
}
|
||||
return CreateNullBorderRendererWithStyleBorder(
|
||||
@ -1881,15 +1881,15 @@ bool nsCSSRendering::CanBuildWebRenderDisplayItemsForStyleImageLayer(
|
||||
}
|
||||
}
|
||||
|
||||
// We only support painting gradients and image for a single style image layer
|
||||
const nsStyleImage* styleImage =
|
||||
&aBackgroundStyle->mImage.mLayers[aLayer].mImage;
|
||||
if (styleImage->GetType() == eStyleImageType_Image) {
|
||||
if (styleImage->GetCropRect()) {
|
||||
// We only support painting gradients and image for a single style image
|
||||
// layer, and we don't support crop-rects.
|
||||
const auto& styleImage = aBackgroundStyle->mImage.mLayers[aLayer].mImage;
|
||||
if (styleImage.IsImageRequestType()) {
|
||||
if (styleImage.IsRect()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
imgRequestProxy* requestProxy = styleImage->GetImageData();
|
||||
imgRequestProxy* requestProxy = styleImage.GetImageRequest();
|
||||
if (!requestProxy) {
|
||||
return false;
|
||||
}
|
||||
@ -1909,7 +1909,7 @@ bool nsCSSRendering::CanBuildWebRenderDisplayItemsForStyleImageLayer(
|
||||
return true;
|
||||
}
|
||||
|
||||
if (styleImage->GetType() == eStyleImageType_Gradient) {
|
||||
if (styleImage.IsGradient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1966,8 +1966,9 @@ static bool IsOpaqueBorderEdge(const nsStyleBorder& aBorder,
|
||||
// because we may not even have the image loaded at this point, and
|
||||
// even if we did, checking whether the relevant tile is fully
|
||||
// opaque would be too much work.
|
||||
if (aBorder.mBorderImageSource.GetType() != eStyleImageType_Null)
|
||||
if (!aBorder.mBorderImageSource.IsNone()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StyleColor color = aBorder.BorderColorFor(aSide);
|
||||
// We don't know the foreground color here, so if it's being used
|
||||
|
@ -62,7 +62,7 @@ struct nsBackgroundLayerState {
|
||||
/**
|
||||
* @param aFlags some combination of nsCSSRendering::PAINTBG_* flags
|
||||
*/
|
||||
nsBackgroundLayerState(nsIFrame* aForFrame, const nsStyleImage* aImage,
|
||||
nsBackgroundLayerState(nsIFrame* aForFrame, const mozilla::StyleImage* aImage,
|
||||
uint32_t aFlags)
|
||||
: mImageRenderer(aForFrame, aImage, aFlags) {}
|
||||
|
||||
|
@ -3609,7 +3609,8 @@ ImgDrawResult nsCSSBorderImageRenderer::CreateWebRenderCommands(
|
||||
|
||||
ImgDrawResult drawResult = ImgDrawResult::SUCCESS;
|
||||
switch (mImageRenderer.GetType()) {
|
||||
case eStyleImageType_Image: {
|
||||
case StyleImage::Tag::Rect:
|
||||
case StyleImage::Tag::Url: {
|
||||
RefPtr<imgIContainer> img = mImageRenderer.GetImage();
|
||||
if (!img || img->GetType() == imgIContainer::TYPE_VECTOR) {
|
||||
// Vector images will redraw each segment of the border up to 8 times.
|
||||
@ -3693,7 +3694,7 @@ ImgDrawResult nsCSSBorderImageRenderer::CreateWebRenderCommands(
|
||||
aBuilder.PushBorderImage(dest, clip, !aItem->BackfaceIsHidden(), params);
|
||||
break;
|
||||
}
|
||||
case eStyleImageType_Gradient: {
|
||||
case StyleImage::Tag::Gradient: {
|
||||
const StyleGradient& gradient = *mImageRenderer.GetGradientData();
|
||||
nsCSSGradientRenderer renderer = nsCSSGradientRenderer::Create(
|
||||
aForFrame->PresContext(), aForFrame->Style(), gradient, mImageSize);
|
||||
|
@ -3914,7 +3914,7 @@ nsDisplayBackgroundImage::GetInitData(nsDisplayListBuilder* aBuilder,
|
||||
layer.mAttachment == StyleImageLayerAttachment::Fixed &&
|
||||
!isTransformedFixed;
|
||||
|
||||
bool shouldFixToViewport = shouldTreatAsFixed && !layer.mImage.IsEmpty();
|
||||
bool shouldFixToViewport = shouldTreatAsFixed && !layer.mImage.IsNone();
|
||||
bool isRasterImage = state.mImageRenderer.IsRasterImage();
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
if (isRasterImage) {
|
||||
@ -4204,7 +4204,7 @@ bool nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
|
||||
// Passing bg == nullptr in this macro will result in one iteration with
|
||||
// i = 0.
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, bg->mImage) {
|
||||
if (bg->mImage.mLayers[i].mImage.IsEmpty()) {
|
||||
if (bg->mImage.mLayers[i].mImage.IsNone()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -4410,12 +4410,10 @@ nsDisplayBackgroundImage::ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
|
||||
if (StaticPrefs::layout_animated_image_layers_enabled() && mBackgroundStyle) {
|
||||
const nsStyleImageLayers::Layer& layer =
|
||||
mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
|
||||
const nsStyleImage* image = &layer.mImage;
|
||||
if (image->GetType() == eStyleImageType_Image) {
|
||||
imgIRequest* imgreq = image->GetImageData();
|
||||
const auto* image = &layer.mImage;
|
||||
if (auto* request = image->GetImageRequest()) {
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
if (imgreq && NS_SUCCEEDED(imgreq->GetImage(getter_AddRefs(image))) &&
|
||||
image) {
|
||||
if (NS_SUCCEEDED(request->GetImage(getter_AddRefs(image))) && image) {
|
||||
bool animated = false;
|
||||
if (NS_SUCCEEDED(image->GetAnimated(&animated)) && animated) {
|
||||
return WHENEVER_POSSIBLE;
|
||||
@ -4734,9 +4732,9 @@ void nsDisplayBackgroundImage::ComputeInvalidationRegion(
|
||||
return;
|
||||
}
|
||||
if (aBuilder->ShouldSyncDecodeImages()) {
|
||||
const nsStyleImage& image =
|
||||
const auto& image =
|
||||
mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer].mImage;
|
||||
if (image.GetType() == eStyleImageType_Image &&
|
||||
if (image.IsImageRequestType() &&
|
||||
geometry->ShouldInvalidateToSyncDecodeImages()) {
|
||||
aInvalidRegion->Or(*aInvalidRegion, bounds);
|
||||
}
|
||||
@ -9884,8 +9882,8 @@ void nsDisplayMasksAndClipPaths::ComputeInvalidationRegion(
|
||||
geometry->ShouldInvalidateToSyncDecodeImages()) {
|
||||
const nsStyleSVGReset* svgReset = mFrame->StyleSVGReset();
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, svgReset->mMask) {
|
||||
const nsStyleImage& image = svgReset->mMask.mLayers[i].mImage;
|
||||
if (image.GetType() == eStyleImageType_Image) {
|
||||
const auto& image = svgReset->mMask.mLayers[i].mImage;
|
||||
if (image.IsImageRequestType()) {
|
||||
aInvalidRegion->Or(*aInvalidRegion, bounds);
|
||||
break;
|
||||
}
|
||||
|
@ -46,10 +46,10 @@ nsSize CSSSizeOrRatio::ComputeConcreteSize() const {
|
||||
}
|
||||
|
||||
nsImageRenderer::nsImageRenderer(nsIFrame* aForFrame,
|
||||
const nsStyleImage* aImage, uint32_t aFlags)
|
||||
const StyleImage* aImage, uint32_t aFlags)
|
||||
: mForFrame(aForFrame),
|
||||
mImage(aImage),
|
||||
mType(aImage->GetType()),
|
||||
mType(aImage->tag),
|
||||
mImageContainer(nullptr),
|
||||
mGradientData(nullptr),
|
||||
mPaintServerFrame(nullptr),
|
||||
@ -59,17 +59,13 @@ nsImageRenderer::nsImageRenderer(nsIFrame* aForFrame,
|
||||
mExtendMode(ExtendMode::CLAMP),
|
||||
mMaskOp(StyleMaskMode::MatchSource) {}
|
||||
|
||||
static bool ShouldTreatAsCompleteDueToSyncDecode(const nsStyleImage* aImage,
|
||||
static bool ShouldTreatAsCompleteDueToSyncDecode(const StyleImage* aImage,
|
||||
uint32_t aFlags) {
|
||||
if (!(aFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aImage->GetType() != eStyleImageType_Image) {
|
||||
return false;
|
||||
}
|
||||
|
||||
imgRequestProxy* req = aImage->GetImageData();
|
||||
imgRequestProxy* req = aImage->GetImageRequest();
|
||||
if (!req) {
|
||||
return false;
|
||||
}
|
||||
@ -97,10 +93,10 @@ static bool ShouldTreatAsCompleteDueToSyncDecode(const nsStyleImage* aImage,
|
||||
}
|
||||
|
||||
bool nsImageRenderer::PrepareImage() {
|
||||
if (mImage->IsEmpty() ||
|
||||
(mType == eStyleImageType_Image && !mImage->GetImageData())) {
|
||||
// mImage->GetImageData() could be null here if the nsStyleImage refused
|
||||
// to load a same-document URL.
|
||||
if (mImage->IsNone() ||
|
||||
(mImage->IsImageRequestType() && !mImage->GetImageRequest())) {
|
||||
// mImage->GetImageRequest() could be null here if the StyleImage refused
|
||||
// to load a same-document URL, or the url was invalid, for example.
|
||||
mPrepareResult = ImgDrawResult::BAD_IMAGE;
|
||||
return false;
|
||||
}
|
||||
@ -111,10 +107,10 @@ bool nsImageRenderer::PrepareImage() {
|
||||
|
||||
// Boost the loading priority since we know we want to draw the image.
|
||||
if ((mFlags & nsImageRenderer::FLAG_PAINTING_TO_WINDOW) &&
|
||||
mType == eStyleImageType_Image) {
|
||||
MOZ_ASSERT(mImage->GetImageData(),
|
||||
mImage->IsImageRequestType()) {
|
||||
MOZ_ASSERT(mImage->GetImageRequest(),
|
||||
"must have image data, since we checked above");
|
||||
mImage->GetImageData()->BoostPriority(imgIRequest::CATEGORY_DISPLAY);
|
||||
mImage->GetImageRequest()->BoostPriority(imgIRequest::CATEGORY_DISPLAY);
|
||||
}
|
||||
|
||||
// Check again to see if we finished.
|
||||
@ -128,75 +124,65 @@ bool nsImageRenderer::PrepareImage() {
|
||||
}
|
||||
}
|
||||
|
||||
switch (mType) {
|
||||
case eStyleImageType_Image: {
|
||||
MOZ_ASSERT(mImage->GetImageData(),
|
||||
"must have image data, since we checked above");
|
||||
nsCOMPtr<imgIContainer> srcImage;
|
||||
DebugOnly<nsresult> rv =
|
||||
mImage->GetImageData()->GetImage(getter_AddRefs(srcImage));
|
||||
if (mImage->IsImageRequestType()) {
|
||||
MOZ_ASSERT(mImage->GetImageRequest(),
|
||||
"must have image data, since we checked above");
|
||||
nsCOMPtr<imgIContainer> srcImage;
|
||||
DebugOnly<nsresult> rv =
|
||||
mImage->GetImageRequest()->GetImage(getter_AddRefs(srcImage));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv) && srcImage,
|
||||
"If GetImage() is failing, mImage->IsComplete() "
|
||||
"should have returned false");
|
||||
|
||||
if (!mImage->GetCropRect()) {
|
||||
if (!mImage->IsRect()) {
|
||||
mImageContainer.swap(srcImage);
|
||||
} else {
|
||||
auto croprect = mImage->ComputeActualCropRect();
|
||||
if (!croprect || croprect->mRect.IsEmpty()) {
|
||||
// The cropped image has zero size
|
||||
mPrepareResult = ImgDrawResult::BAD_IMAGE;
|
||||
return false;
|
||||
}
|
||||
if (croprect->mIsEntireImage) {
|
||||
// The cropped image is identical to the source image
|
||||
mImageContainer.swap(srcImage);
|
||||
} else {
|
||||
nsIntRect actualCropRect;
|
||||
bool isEntireImage;
|
||||
bool success =
|
||||
mImage->ComputeActualCropRect(actualCropRect, &isEntireImage);
|
||||
if (!success || actualCropRect.IsEmpty()) {
|
||||
// The cropped image has zero size
|
||||
mPrepareResult = ImgDrawResult::BAD_IMAGE;
|
||||
return false;
|
||||
}
|
||||
if (isEntireImage) {
|
||||
// The cropped image is identical to the source image
|
||||
mImageContainer.swap(srcImage);
|
||||
} else {
|
||||
nsCOMPtr<imgIContainer> subImage =
|
||||
ImageOps::Clip(srcImage, actualCropRect, Nothing());
|
||||
mImageContainer.swap(subImage);
|
||||
}
|
||||
nsCOMPtr<imgIContainer> subImage =
|
||||
ImageOps::Clip(srcImage, croprect->mRect, Nothing());
|
||||
mImageContainer.swap(subImage);
|
||||
}
|
||||
mPrepareResult = ImgDrawResult::SUCCESS;
|
||||
break;
|
||||
}
|
||||
case eStyleImageType_Gradient:
|
||||
mGradientData = &mImage->GetGradient();
|
||||
mPrepareResult = ImgDrawResult::SUCCESS;
|
||||
break;
|
||||
case eStyleImageType_Element: {
|
||||
dom::Element* paintElement = // may be null
|
||||
SVGObserverUtils::GetAndObserveBackgroundImage(
|
||||
mForFrame->FirstContinuation(), mImage->GetElementId());
|
||||
// If the referenced element is an <img>, <canvas>, or <video> element,
|
||||
// prefer SurfaceFromElement as it's more reliable.
|
||||
mImageElementSurface = nsLayoutUtils::SurfaceFromElement(paintElement);
|
||||
mPrepareResult = ImgDrawResult::SUCCESS;
|
||||
} else if (mImage->IsGradient()) {
|
||||
mGradientData = &*mImage->AsGradient();
|
||||
mPrepareResult = ImgDrawResult::SUCCESS;
|
||||
} else if (mImage->IsElement()) {
|
||||
dom::Element* paintElement = // may be null
|
||||
SVGObserverUtils::GetAndObserveBackgroundImage(
|
||||
mForFrame->FirstContinuation(), mImage->AsElement().AsAtom());
|
||||
// If the referenced element is an <img>, <canvas>, or <video> element,
|
||||
// prefer SurfaceFromElement as it's more reliable.
|
||||
mImageElementSurface = nsLayoutUtils::SurfaceFromElement(paintElement);
|
||||
|
||||
if (!mImageElementSurface.GetSourceSurface()) {
|
||||
nsIFrame* paintServerFrame =
|
||||
paintElement ? paintElement->GetPrimaryFrame() : nullptr;
|
||||
// If there's no referenced frame, or the referenced frame is
|
||||
// non-displayable SVG, then we have nothing valid to paint.
|
||||
if (!paintServerFrame ||
|
||||
(paintServerFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||
!paintServerFrame->IsFrameOfType(nsIFrame::eSVGPaintServer) &&
|
||||
!static_cast<nsSVGDisplayableFrame*>(
|
||||
do_QueryFrame(paintServerFrame)))) {
|
||||
mPrepareResult = ImgDrawResult::BAD_IMAGE;
|
||||
return false;
|
||||
}
|
||||
mPaintServerFrame = paintServerFrame;
|
||||
if (!mImageElementSurface.GetSourceSurface()) {
|
||||
nsIFrame* paintServerFrame =
|
||||
paintElement ? paintElement->GetPrimaryFrame() : nullptr;
|
||||
// If there's no referenced frame, or the referenced frame is
|
||||
// non-displayable SVG, then we have nothing valid to paint.
|
||||
if (!paintServerFrame ||
|
||||
(paintServerFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||
!paintServerFrame->IsFrameOfType(nsIFrame::eSVGPaintServer) &&
|
||||
!static_cast<nsSVGDisplayableFrame*>(
|
||||
do_QueryFrame(paintServerFrame)))) {
|
||||
mPrepareResult = ImgDrawResult::BAD_IMAGE;
|
||||
return false;
|
||||
}
|
||||
|
||||
mPrepareResult = ImgDrawResult::SUCCESS;
|
||||
break;
|
||||
mPaintServerFrame = paintServerFrame;
|
||||
}
|
||||
case eStyleImageType_Null:
|
||||
default:
|
||||
break;
|
||||
|
||||
mPrepareResult = ImgDrawResult::SUCCESS;
|
||||
} else {
|
||||
MOZ_ASSERT(mImage->IsNone(), "Unknown image type?");
|
||||
}
|
||||
|
||||
return IsReady();
|
||||
@ -209,7 +195,8 @@ CSSSizeOrRatio nsImageRenderer::ComputeIntrinsicSize() {
|
||||
|
||||
CSSSizeOrRatio result;
|
||||
switch (mType) {
|
||||
case eStyleImageType_Image: {
|
||||
case StyleImage::Tag::Rect:
|
||||
case StyleImage::Tag::Url: {
|
||||
bool haveWidth, haveHeight;
|
||||
CSSIntSize imageIntSize;
|
||||
nsLayoutUtils::ComputeSizeForDrawing(
|
||||
@ -235,7 +222,7 @@ CSSSizeOrRatio nsImageRenderer::ComputeIntrinsicSize() {
|
||||
|
||||
break;
|
||||
}
|
||||
case eStyleImageType_Element: {
|
||||
case StyleImage::Tag::Element: {
|
||||
// XXX element() should have the width/height of the referenced element,
|
||||
// and that element's ratio, if it matches. If it doesn't match, it
|
||||
// should have no width/height or ratio. See element() in CSS images:
|
||||
@ -265,11 +252,10 @@ CSSSizeOrRatio nsImageRenderer::ComputeIntrinsicSize() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eStyleImageType_Gradient:
|
||||
// Per <http://dev.w3.org/csswg/css3-images/#gradients>, gradients have no
|
||||
// intrinsic dimensions.
|
||||
case eStyleImageType_Null:
|
||||
default:
|
||||
// Per <http://dev.w3.org/csswg/css3-images/#gradients>, gradients have no
|
||||
// intrinsic dimensions.
|
||||
case StyleImage::Tag::Gradient:
|
||||
case StyleImage::Tag::None:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -487,14 +473,15 @@ ImgDrawResult nsImageRenderer::Draw(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
switch (mType) {
|
||||
case eStyleImageType_Image: {
|
||||
case StyleImage::Tag::Rect:
|
||||
case StyleImage::Tag::Url: {
|
||||
result = nsLayoutUtils::DrawBackgroundImage(
|
||||
*ctx, mForFrame, aPresContext, mImageContainer, samplingFilter, aDest,
|
||||
aFill, aRepeatSize, aAnchor, aDirtyRect,
|
||||
ConvertImageRendererToDrawFlags(mFlags), mExtendMode, aOpacity);
|
||||
break;
|
||||
}
|
||||
case eStyleImageType_Gradient: {
|
||||
case StyleImage::Tag::Gradient: {
|
||||
nsCSSGradientRenderer renderer = nsCSSGradientRenderer::Create(
|
||||
aPresContext, mForFrame->Style(), *mGradientData, mSize);
|
||||
|
||||
@ -502,7 +489,7 @@ ImgDrawResult nsImageRenderer::Draw(nsPresContext* aPresContext,
|
||||
aOpacity);
|
||||
break;
|
||||
}
|
||||
case eStyleImageType_Element: {
|
||||
case StyleImage::Tag::Element: {
|
||||
RefPtr<gfxDrawable> drawable = DrawableForElement(aDest, *ctx);
|
||||
if (!drawable) {
|
||||
NS_WARNING("Could not create drawable for element");
|
||||
@ -516,8 +503,7 @@ ImgDrawResult nsImageRenderer::Draw(nsPresContext* aPresContext,
|
||||
aOpacity);
|
||||
break;
|
||||
}
|
||||
case eStyleImageType_Null:
|
||||
default:
|
||||
case StyleImage::Tag::None:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -573,7 +559,7 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
|
||||
|
||||
ImgDrawResult drawResult = ImgDrawResult::SUCCESS;
|
||||
switch (mType) {
|
||||
case eStyleImageType_Gradient: {
|
||||
case StyleImage::Tag::Gradient: {
|
||||
nsCSSGradientRenderer renderer = nsCSSGradientRenderer::Create(
|
||||
aPresContext, mForFrame->Style(), *mGradientData, mSize);
|
||||
|
||||
@ -582,7 +568,8 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
|
||||
!aItem->BackfaceIsHidden(), aOpacity);
|
||||
break;
|
||||
}
|
||||
case eStyleImageType_Image: {
|
||||
case StyleImage::Tag::Rect:
|
||||
case StyleImage::Tag::Url: {
|
||||
uint32_t containerFlags = imgIContainer::FLAG_ASYNC_NOTIFY;
|
||||
if (mFlags & nsImageRenderer::FLAG_PAINTING_TO_WINDOW) {
|
||||
containerFlags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
|
||||
@ -684,7 +671,7 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
|
||||
|
||||
already_AddRefed<gfxDrawable> nsImageRenderer::DrawableForElement(
|
||||
const nsRect& aImageRect, gfxContext& aContext) {
|
||||
NS_ASSERTION(mType == eStyleImageType_Element,
|
||||
NS_ASSERTION(mType == StyleImage::Tag::Element,
|
||||
"DrawableForElement only makes sense if backed by an element");
|
||||
if (mPaintServerFrame) {
|
||||
// XXX(seth): In order to not pass FLAG_SYNC_DECODE_IMAGES here,
|
||||
@ -878,7 +865,11 @@ ImgDrawResult nsImageRenderer::DrawBorderImageComponent(
|
||||
return ImgDrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
if (mType == eStyleImageType_Image || mType == eStyleImageType_Element) {
|
||||
const bool isRequestBacked = mType == StyleImage::Tag::Url ||
|
||||
mType == StyleImage::Tag::Rect;
|
||||
MOZ_ASSERT(isRequestBacked == mImage->IsImageRequestType());
|
||||
|
||||
if (isRequestBacked || mType == StyleImage::Tag::Element) {
|
||||
nsCOMPtr<imgIContainer> subImage;
|
||||
|
||||
// To draw one portion of an image into a border component, we stretch that
|
||||
@ -897,7 +888,7 @@ ImgDrawResult nsImageRenderer::DrawBorderImageComponent(
|
||||
}
|
||||
// Retrieve or create the subimage we'll draw.
|
||||
nsIntRect srcRect(aSrc.x, aSrc.y, aSrc.width, aSrc.height);
|
||||
if (mType == eStyleImageType_Image) {
|
||||
if (isRequestBacked) {
|
||||
CachedBorderImageData* cachedData =
|
||||
mForFrame->GetProperty(nsIFrame::CachedBorderImageDataProperty());
|
||||
if (!cachedData) {
|
||||
@ -988,82 +979,62 @@ ImgDrawResult nsImageRenderer::DrawShapeImage(nsPresContext* aPresContext,
|
||||
return ImgDrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
ImgDrawResult result = ImgDrawResult::SUCCESS;
|
||||
|
||||
switch (mType) {
|
||||
case eStyleImageType_Image: {
|
||||
uint32_t drawFlags =
|
||||
ConvertImageRendererToDrawFlags(mFlags) | imgIContainer::FRAME_FIRST;
|
||||
nsRect dest(nsPoint(0, 0), mSize);
|
||||
// We have a tricky situation in our choice of SamplingFilter. Shape
|
||||
// images define a float area based on the alpha values in the rendered
|
||||
// pixels. When multiple device pixels are used for one css pixel, the
|
||||
// sampling can change crisp edges into aliased edges. For visual pixels,
|
||||
// that's usually the right choice. For defining a float area, it can
|
||||
// cause problems. If a style is using a shape-image-threshold value that
|
||||
// is less than the alpha of the edge pixels, any filtering may smear the
|
||||
// alpha into adjacent pixels and expand the float area in a confusing
|
||||
// way. Since the alpha threshold can be set precisely in CSS, and since a
|
||||
// web author may be counting on that threshold to define a precise float
|
||||
// area from an image, it is least confusing to have the rendered pixels
|
||||
// have unfiltered alpha. We use SamplingFilter::POINT to ensure that each
|
||||
// rendered pixel has an alpha that precisely matches the alpha of the
|
||||
// closest pixel in the image.
|
||||
result = nsLayoutUtils::DrawSingleImage(
|
||||
aRenderingContext, aPresContext, mImageContainer,
|
||||
SamplingFilter::POINT, dest, dest, Nothing(), drawFlags, nullptr,
|
||||
nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
case eStyleImageType_Gradient: {
|
||||
nsCSSGradientRenderer renderer = nsCSSGradientRenderer::Create(
|
||||
aPresContext, mForFrame->Style(), *mGradientData, mSize);
|
||||
nsRect dest(nsPoint(0, 0), mSize);
|
||||
|
||||
renderer.Paint(aRenderingContext, dest, dest, mSize,
|
||||
CSSIntRect::FromAppUnitsRounded(dest), dest, 1.0);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Unsupported image type.
|
||||
result = ImgDrawResult::BAD_IMAGE;
|
||||
break;
|
||||
if (mImage->IsImageRequestType()) {
|
||||
uint32_t drawFlags =
|
||||
ConvertImageRendererToDrawFlags(mFlags) | imgIContainer::FRAME_FIRST;
|
||||
nsRect dest(nsPoint(0, 0), mSize);
|
||||
// We have a tricky situation in our choice of SamplingFilter. Shape
|
||||
// images define a float area based on the alpha values in the rendered
|
||||
// pixels. When multiple device pixels are used for one css pixel, the
|
||||
// sampling can change crisp edges into aliased edges. For visual pixels,
|
||||
// that's usually the right choice. For defining a float area, it can
|
||||
// cause problems. If a style is using a shape-image-threshold value that
|
||||
// is less than the alpha of the edge pixels, any filtering may smear the
|
||||
// alpha into adjacent pixels and expand the float area in a confusing
|
||||
// way. Since the alpha threshold can be set precisely in CSS, and since a
|
||||
// web author may be counting on that threshold to define a precise float
|
||||
// area from an image, it is least confusing to have the rendered pixels
|
||||
// have unfiltered alpha. We use SamplingFilter::POINT to ensure that each
|
||||
// rendered pixel has an alpha that precisely matches the alpha of the
|
||||
// closest pixel in the image.
|
||||
return nsLayoutUtils::DrawSingleImage(
|
||||
aRenderingContext, aPresContext, mImageContainer,
|
||||
SamplingFilter::POINT, dest, dest, Nothing(), drawFlags, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
return result;
|
||||
if (mImage->IsGradient()) {
|
||||
nsCSSGradientRenderer renderer = nsCSSGradientRenderer::Create(
|
||||
aPresContext, mForFrame->Style(), *mGradientData, mSize);
|
||||
nsRect dest(nsPoint(0, 0), mSize);
|
||||
renderer.Paint(aRenderingContext, dest, dest, mSize,
|
||||
CSSIntRect::FromAppUnitsRounded(dest), dest, 1.0);
|
||||
return ImgDrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
// Unsupported image type.
|
||||
return ImgDrawResult::BAD_IMAGE;
|
||||
}
|
||||
|
||||
bool nsImageRenderer::IsRasterImage() {
|
||||
if (mType != eStyleImageType_Image || !mImageContainer) return false;
|
||||
return mImageContainer->GetType() == imgIContainer::TYPE_RASTER;
|
||||
return mImageContainer &&
|
||||
mImageContainer->GetType() == imgIContainer::TYPE_RASTER;
|
||||
}
|
||||
|
||||
bool nsImageRenderer::IsAnimatedImage() {
|
||||
if (mType != eStyleImageType_Image || !mImageContainer) return false;
|
||||
bool animated = false;
|
||||
if (NS_SUCCEEDED(mImageContainer->GetAnimated(&animated)) && animated)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return mImageContainer &&
|
||||
NS_SUCCEEDED(mImageContainer->GetAnimated(&animated)) && animated;
|
||||
}
|
||||
|
||||
already_AddRefed<imgIContainer> nsImageRenderer::GetImage() {
|
||||
if (mType != eStyleImageType_Image || !mImageContainer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<imgIContainer> image = mImageContainer;
|
||||
return image.forget();
|
||||
return do_AddRef(mImageContainer);
|
||||
}
|
||||
|
||||
bool nsImageRenderer::IsImageContainerAvailable(layers::LayerManager* aManager,
|
||||
uint32_t aFlags) {
|
||||
if (!mImageContainer) {
|
||||
return false;
|
||||
}
|
||||
return mImageContainer->IsImageContainerAvailable(aManager, aFlags);
|
||||
return mImageContainer &&
|
||||
mImageContainer->IsImageContainerAvailable(aManager, aFlags);
|
||||
}
|
||||
|
||||
void nsImageRenderer::PurgeCacheForViewportChange(
|
||||
|
@ -85,8 +85,8 @@ struct CSSSizeOrRatio {
|
||||
|
||||
/**
|
||||
* This is a small wrapper class to encapsulate image drawing that can draw an
|
||||
* nsStyleImage image, which may internally be a real image, a sub image, or a
|
||||
* CSS gradient.
|
||||
* StyleImage image, which may internally be a real image, a sub image, or a CSS
|
||||
* gradient, etc...
|
||||
*
|
||||
* @note Always call the member functions in the order of PrepareImage(),
|
||||
* SetSize(), and Draw*().
|
||||
@ -100,7 +100,7 @@ class nsImageRenderer {
|
||||
enum { FLAG_SYNC_DECODE_IMAGES = 0x01, FLAG_PAINTING_TO_WINDOW = 0x02 };
|
||||
enum FitType { CONTAIN, COVER };
|
||||
|
||||
nsImageRenderer(nsIFrame* aForFrame, const nsStyleImage* aImage,
|
||||
nsImageRenderer(nsIFrame* aForFrame, const mozilla::StyleImage* aImage,
|
||||
uint32_t aFlags);
|
||||
~nsImageRenderer() = default;
|
||||
/**
|
||||
@ -248,7 +248,7 @@ class nsImageRenderer {
|
||||
void PurgeCacheForViewportChange(
|
||||
const mozilla::Maybe<nsSize>& aSVGViewportSize, const bool aHasRatio);
|
||||
const nsSize& GetSize() const { return mSize; }
|
||||
nsStyleImageType GetType() const { return mType; }
|
||||
mozilla::StyleImage::Tag GetType() const { return mType; }
|
||||
const mozilla::StyleGradient* GetGradientData() const {
|
||||
return mGradientData;
|
||||
}
|
||||
@ -286,15 +286,15 @@ class nsImageRenderer {
|
||||
/**
|
||||
* Helper method for creating a gfxDrawable from mPaintServerFrame or
|
||||
* mImageElementSurface.
|
||||
* Requires mType is eStyleImageType_Element.
|
||||
* Requires mType to be Element.
|
||||
* Returns null if we cannot create the drawable.
|
||||
*/
|
||||
already_AddRefed<gfxDrawable> DrawableForElement(const nsRect& aImageRect,
|
||||
gfxContext& aContext);
|
||||
|
||||
nsIFrame* mForFrame;
|
||||
const nsStyleImage* mImage;
|
||||
nsStyleImageType mType;
|
||||
const mozilla::StyleImage* mImage;
|
||||
mozilla::StyleImage::Tag mType;
|
||||
nsCOMPtr<imgIContainer> mImageContainer;
|
||||
const mozilla::StyleGradient* mGradientData;
|
||||
nsIFrame* mPaintServerFrame;
|
||||
|
@ -1105,43 +1105,6 @@ const AnonymousCounterStyle* Gecko_CounterStyle_GetAnonymous(
|
||||
return aPtr->AsAnonymous();
|
||||
}
|
||||
|
||||
void Gecko_SetNullImageValue(nsStyleImage* aImage) {
|
||||
MOZ_ASSERT(aImage);
|
||||
aImage->SetNull();
|
||||
}
|
||||
|
||||
void Gecko_SetGradientImageValue(nsStyleImage* aImage,
|
||||
StyleGradient* aGradient) {
|
||||
MOZ_ASSERT(aImage);
|
||||
aImage->SetGradientData(UniquePtr<StyleGradient>(aGradient));
|
||||
}
|
||||
|
||||
void Gecko_SetLayerImageImageValue(nsStyleImage* aImage,
|
||||
const StyleComputedImageUrl* aUrl) {
|
||||
MOZ_ASSERT(aImage && aUrl);
|
||||
aImage->SetImageUrl(*aUrl);
|
||||
}
|
||||
|
||||
void Gecko_SetImageElement(nsStyleImage* aImage, nsAtom* aAtom) {
|
||||
MOZ_ASSERT(aImage);
|
||||
aImage->SetElementId(do_AddRef(aAtom));
|
||||
}
|
||||
|
||||
void Gecko_CopyImageValueFrom(nsStyleImage* aImage,
|
||||
const nsStyleImage* aOther) {
|
||||
MOZ_ASSERT(aImage);
|
||||
MOZ_ASSERT(aOther);
|
||||
|
||||
*aImage = *aOther;
|
||||
}
|
||||
|
||||
void Gecko_InitializeImageCropRect(nsStyleImage* aImage) {
|
||||
MOZ_ASSERT(aImage);
|
||||
auto zero = StyleNumberOrPercentage::Number(0);
|
||||
aImage->SetCropRect(MakeUnique<nsStyleImage::CropRect>(
|
||||
nsStyleImage::CropRect{zero, zero, zero, zero}));
|
||||
}
|
||||
|
||||
void Gecko_SetCursorArrayCapacity(nsStyleUI* aUi, size_t aCapacity) {
|
||||
aUi->mCursorImages.Clear();
|
||||
aUi->mCursorImages.SetCapacity(aCapacity);
|
||||
@ -1156,11 +1119,6 @@ void Gecko_CopyCursorArrayFrom(nsStyleUI* aDest, const nsStyleUI* aSrc) {
|
||||
aDest->mCursorImages = aSrc->mCursorImages;
|
||||
}
|
||||
|
||||
nsAtom* Gecko_GetImageElement(const nsStyleImage* aImage) {
|
||||
MOZ_ASSERT(aImage && aImage->GetType() == eStyleImageType_Element);
|
||||
return const_cast<nsAtom*>(aImage->GetElementId());
|
||||
}
|
||||
|
||||
void Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity,
|
||||
size_t aElemSize) {
|
||||
auto base = reinterpret_cast<
|
||||
@ -1318,7 +1276,7 @@ void Gecko_DestroyShapeSource(StyleShapeSource* aShape) {
|
||||
}
|
||||
|
||||
void Gecko_NewShapeImage(StyleShapeSource* aShape) {
|
||||
aShape->SetShapeImage(MakeUnique<nsStyleImage>());
|
||||
aShape->SetShapeImage(MakeUnique<StyleImage>(StyleImage::None()));
|
||||
}
|
||||
|
||||
void Gecko_SetToSVGPath(StyleShapeSource* aShape,
|
||||
|
@ -336,21 +336,6 @@ nsAtom* Gecko_CounterStyle_GetName(const mozilla::CounterStylePtr* ptr);
|
||||
const mozilla::AnonymousCounterStyle* Gecko_CounterStyle_GetAnonymous(
|
||||
const mozilla::CounterStylePtr* ptr);
|
||||
|
||||
// background-image style.
|
||||
void Gecko_SetNullImageValue(nsStyleImage* image);
|
||||
|
||||
// NOTE: Takes ownership of the gradient.
|
||||
void Gecko_SetGradientImageValue(nsStyleImage*, mozilla::StyleGradient*);
|
||||
|
||||
void Gecko_SetLayerImageImageValue(nsStyleImage* image,
|
||||
const mozilla::StyleComputedImageUrl* url);
|
||||
|
||||
void Gecko_SetImageElement(nsStyleImage* image, nsAtom* atom);
|
||||
void Gecko_CopyImageValueFrom(nsStyleImage* image, const nsStyleImage* other);
|
||||
void Gecko_InitializeImageCropRect(nsStyleImage* image);
|
||||
|
||||
nsAtom* Gecko_GetImageElement(const nsStyleImage* image);
|
||||
|
||||
// list-style-image style.
|
||||
void Gecko_SetListStyleImageNone(nsStyleList* style_struct);
|
||||
|
||||
|
@ -564,6 +564,7 @@ cbindgen-types = [
|
||||
{ gecko = "StyleAlignContent", servo = "values::computed::align::AlignContent" },
|
||||
{ gecko = "StyleJustifyContent", servo = "values::computed::align::JustifyContent" },
|
||||
{ gecko = "StyleComputedValueFlags", servo = "computed_value_flags::ComputedValueFlags" },
|
||||
{ gecko = "StyleImage", servo = "values::computed::Image" },
|
||||
]
|
||||
|
||||
mapped-generic-types = [
|
||||
|
@ -912,6 +912,48 @@ inline RestyleHint RestyleHint::ForAnimations() {
|
||||
RestyleHint::RESTYLE_CSS_ANIMATIONS | RestyleHint::RESTYLE_SMIL;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool StyleImage::IsImageRequestType() const {
|
||||
return IsUrl() || IsRect();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const StyleComputedImageUrl* StyleImage::GetImageRequestURLValue()
|
||||
const {
|
||||
if (IsUrl()) {
|
||||
return &AsUrl();
|
||||
}
|
||||
if (IsRect()) {
|
||||
return &AsRect()->url;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline imgRequestProxy* StyleImage::GetImageRequest() const {
|
||||
auto* url = GetImageRequestURLValue();
|
||||
return url ? url->GetImage() : nullptr;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool StyleImage::IsResolved() const {
|
||||
auto* url = GetImageRequestURLValue();
|
||||
return !url || url->IsImageResolved();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool StyleImage::IsOpaque() const;
|
||||
template <>
|
||||
bool StyleImage::IsSizeAvailable() const;
|
||||
template <>
|
||||
bool StyleImage::IsComplete() const;
|
||||
template <>
|
||||
bool StyleImage::StartDecoding() const;
|
||||
template <>
|
||||
Maybe<StyleImage::ActualCropRect> StyleImage::ComputeActualCropRect() const;
|
||||
template <>
|
||||
void StyleImage::ResolveImage(dom::Document&, const StyleImage*);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
@ -626,9 +626,9 @@ static void AddImageURL(const StyleComputedUrl& aURL,
|
||||
}
|
||||
}
|
||||
|
||||
static void AddImageURL(const nsStyleImage& aImage,
|
||||
static void AddImageURL(const StyleImage& aImage,
|
||||
nsTArray<nsCString>& aURLs) {
|
||||
if (auto* urlValue = aImage.GetURLValue()) {
|
||||
if (auto* urlValue = aImage.GetImageRequestURLValue()) {
|
||||
AddImageURL(*urlValue, aURLs);
|
||||
}
|
||||
}
|
||||
@ -2494,14 +2494,13 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetMask() {
|
||||
firstLayer.mPosition, nsStyleImageLayers::LayerType::Mask) ||
|
||||
!firstLayer.mRepeat.IsInitialValue() ||
|
||||
!firstLayer.mSize.IsInitialValue() ||
|
||||
!(firstLayer.mImage.GetType() == eStyleImageType_Null ||
|
||||
firstLayer.mImage.GetType() == eStyleImageType_Image)) {
|
||||
!(firstLayer.mImage.IsNone() || firstLayer.mImage.IsUrl())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
|
||||
SetValueToURLValue(firstLayer.mImage.GetURLValue(), val);
|
||||
SetValueToURLValue(firstLayer.mImage.GetImageRequestURLValue(), val);
|
||||
|
||||
return val.forget();
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ class nsDOMCSSValueList;
|
||||
struct nsMargin;
|
||||
class nsROCSSPrimitiveValue;
|
||||
class nsStyleGradient;
|
||||
struct nsStyleImage;
|
||||
|
||||
class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
|
||||
public nsStubMutationObserver {
|
||||
|
@ -409,6 +409,7 @@ static inline BorderRadius ZeroBorderRadius() {
|
||||
|
||||
nsStyleBorder::nsStyleBorder(const Document& aDocument)
|
||||
: mBorderRadius(ZeroBorderRadius()),
|
||||
mBorderImageSource(StyleImage::None()),
|
||||
mBorderImageWidth(
|
||||
StyleRectWithAllSides(StyleBorderImageSideWidth::Number(1.))),
|
||||
mBorderImageOutset(
|
||||
@ -535,7 +536,7 @@ nsChangeHint nsStyleBorder::CalcDifference(
|
||||
// while CalcDifference might be executed on a background thread. As a
|
||||
// result, we have to check mBorderImage* fields even before border image was
|
||||
// actually loaded.
|
||||
if (!mBorderImageSource.IsEmpty() || !aNewData.mBorderImageSource.IsEmpty()) {
|
||||
if (!mBorderImageSource.IsNone() || !aNewData.mBorderImageSource.IsNone()) {
|
||||
if (mBorderImageSource != aNewData.mBorderImageSource ||
|
||||
mBorderImageRepeatH != aNewData.mBorderImageRepeatH ||
|
||||
mBorderImageRepeatV != aNewData.mBorderImageRepeatV ||
|
||||
@ -1000,10 +1001,10 @@ bool StyleShapeSource::operator==(const StyleShapeSource& aOther) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void StyleShapeSource::SetShapeImage(UniquePtr<nsStyleImage> aShapeImage) {
|
||||
void StyleShapeSource::SetShapeImage(UniquePtr<StyleImage> aShapeImage) {
|
||||
MOZ_ASSERT(aShapeImage);
|
||||
DoDestroy();
|
||||
new (&mShapeImage) UniquePtr<nsStyleImage>(std::move(aShapeImage));
|
||||
new (&mShapeImage) UniquePtr<StyleImage>(std::move(aShapeImage));
|
||||
mType = StyleShapeSourceType::Image;
|
||||
}
|
||||
|
||||
@ -1011,10 +1012,7 @@ imgIRequest* StyleShapeSource::GetShapeImageData() const {
|
||||
if (mType != StyleShapeSourceType::Image) {
|
||||
return nullptr;
|
||||
}
|
||||
if (mShapeImage->GetType() != eStyleImageType_Image) {
|
||||
return nullptr;
|
||||
}
|
||||
return mShapeImage->GetImageData();
|
||||
return mShapeImage->GetImageRequest();
|
||||
}
|
||||
|
||||
void StyleShapeSource::SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
|
||||
@ -1060,7 +1058,7 @@ void StyleShapeSource::DoCopy(const StyleShapeSource& aOther) {
|
||||
break;
|
||||
|
||||
case StyleShapeSourceType::Image:
|
||||
SetShapeImage(MakeUnique<nsStyleImage>(aOther.ShapeImage()));
|
||||
SetShapeImage(MakeUnique<StyleImage>(aOther.ShapeImage()));
|
||||
break;
|
||||
|
||||
case StyleShapeSourceType::Shape: {
|
||||
@ -1088,7 +1086,7 @@ void StyleShapeSource::DoDestroy() {
|
||||
mBasicShape.~UniquePtr<StyleBasicShape>();
|
||||
break;
|
||||
case StyleShapeSourceType::Image:
|
||||
mShapeImage.~UniquePtr<nsStyleImage>();
|
||||
mShapeImage.~UniquePtr<StyleImage>();
|
||||
break;
|
||||
case StyleShapeSourceType::Path:
|
||||
mSVGPath.~UniquePtr<StyleSVGPath>();
|
||||
@ -1151,33 +1149,32 @@ void nsStyleSVGReset::TriggerImageLoads(Document& aDocument,
|
||||
// NOTE(emilio): we intentionally don't call TriggerImageLoads for clip-path.
|
||||
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mMask) {
|
||||
nsStyleImage& image = mMask.mLayers[i].mImage;
|
||||
if (image.GetType() == eStyleImageType_Image) {
|
||||
const auto* url = image.GetURLValue();
|
||||
// If the url is a local ref, it must be a <mask-resource>, so we don't
|
||||
// need to resolve the style image.
|
||||
if (url->IsLocalRef()) {
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
// XXX The old style system also checks whether this is a reference to
|
||||
// the current document with reference, but it doesn't seem to be a
|
||||
// behavior mentioned anywhere, so we comment out the code for now.
|
||||
nsIURI* docURI = aPresContext->Document()->GetDocumentURI();
|
||||
if (url->EqualsExceptRef(docURI)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Otherwise, we may need the image even if it has a reference, in case
|
||||
// the referenced element isn't a valid SVG <mask> element.
|
||||
const nsStyleImage* oldImage =
|
||||
(aOldStyle && aOldStyle->mMask.mLayers.Length() > i)
|
||||
? &aOldStyle->mMask.mLayers[i].mImage
|
||||
: nullptr;
|
||||
|
||||
image.ResolveImage(aDocument, oldImage);
|
||||
auto& image = mMask.mLayers[i].mImage;
|
||||
if (!image.IsImageRequestType()) {
|
||||
continue;
|
||||
}
|
||||
const auto* url = image.GetImageRequestURLValue();
|
||||
// If the url is a local ref, it must be a <mask-resource>, so we don't
|
||||
// need to resolve the style image.
|
||||
if (url->IsLocalRef()) {
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
// XXX The old style system also checks whether this is a reference to
|
||||
// the current document with reference, but it doesn't seem to be a
|
||||
// behavior mentioned anywhere, so we comment out the code for now.
|
||||
nsIURI* docURI = aPresContext->Document()->GetDocumentURI();
|
||||
if (url->EqualsExceptRef(docURI)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
// Otherwise, we may need the image even if it has a reference, in case
|
||||
// the referenced element isn't a valid SVG <mask> element.
|
||||
const auto* oldImage = (aOldStyle && aOldStyle->mMask.mLayers.Length() > i)
|
||||
? &aOldStyle->mMask.mLayers[i].mImage
|
||||
: nullptr;
|
||||
|
||||
image.ResolveImage(aDocument, oldImage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1221,7 +1218,7 @@ nsChangeHint nsStyleSVGReset::CalcDifference(
|
||||
|
||||
bool nsStyleSVGReset::HasMask() const {
|
||||
for (uint32_t i = 0; i < mMask.mImageCount; i++) {
|
||||
if (!mMask.mLayers[i].mImage.IsEmpty()) {
|
||||
if (!mMask.mLayers[i].mImage.IsNone()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1605,104 +1602,6 @@ void CachedBorderImageData::PurgeCacheForViewportChange(
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// nsStyleImage
|
||||
//
|
||||
|
||||
nsStyleImage::nsStyleImage() : mCropRect(nullptr), mType(eStyleImageType_Null) {
|
||||
MOZ_COUNT_CTOR(nsStyleImage);
|
||||
}
|
||||
|
||||
nsStyleImage::~nsStyleImage() {
|
||||
MOZ_COUNT_DTOR(nsStyleImage);
|
||||
if (mType != eStyleImageType_Null) {
|
||||
SetNull();
|
||||
}
|
||||
}
|
||||
|
||||
nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
|
||||
: mCropRect(nullptr), mType(eStyleImageType_Null) {
|
||||
// We need our own copy constructor because we don't want
|
||||
// to copy the reference count
|
||||
MOZ_COUNT_CTOR(nsStyleImage);
|
||||
DoCopy(aOther);
|
||||
}
|
||||
|
||||
nsStyleImage& nsStyleImage::operator=(const nsStyleImage& aOther) {
|
||||
if (this != &aOther) {
|
||||
DoCopy(aOther);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void nsStyleImage::DoCopy(const nsStyleImage& aOther) {
|
||||
SetNull();
|
||||
|
||||
if (aOther.mType == eStyleImageType_Image) {
|
||||
SetImageUrl(aOther.mImage);
|
||||
} else if (aOther.mType == eStyleImageType_Gradient) {
|
||||
SetGradientData(MakeUnique<StyleGradient>(*aOther.mGradient));
|
||||
} else if (aOther.mType == eStyleImageType_Element) {
|
||||
SetElementId(do_AddRef(aOther.mElementId));
|
||||
}
|
||||
|
||||
UniquePtr<CropRect> cropRectCopy;
|
||||
if (aOther.mCropRect) {
|
||||
cropRectCopy = MakeUnique<CropRect>(*aOther.mCropRect.get());
|
||||
}
|
||||
SetCropRect(std::move(cropRectCopy));
|
||||
}
|
||||
|
||||
void nsStyleImage::SetNull() {
|
||||
if (mType == eStyleImageType_Gradient) {
|
||||
delete mGradient;
|
||||
mGradient = nullptr;
|
||||
} else if (mType == eStyleImageType_Image) {
|
||||
mImage.~StyleComputedImageUrl();
|
||||
} else if (mType == eStyleImageType_Element) {
|
||||
NS_RELEASE(mElementId);
|
||||
}
|
||||
|
||||
mType = eStyleImageType_Null;
|
||||
mCropRect = nullptr;
|
||||
}
|
||||
|
||||
void nsStyleImage::SetImageUrl(const StyleComputedImageUrl& aImage) {
|
||||
if (mType != eStyleImageType_Null) {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
new (&mImage) StyleComputedImageUrl(aImage);
|
||||
mType = eStyleImageType_Image;
|
||||
}
|
||||
|
||||
void nsStyleImage::SetGradientData(UniquePtr<StyleGradient> aGradient) {
|
||||
MOZ_ASSERT(aGradient);
|
||||
|
||||
if (mType != eStyleImageType_Null) {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
mGradient = aGradient.release();
|
||||
mType = eStyleImageType_Gradient;
|
||||
}
|
||||
|
||||
void nsStyleImage::SetElementId(already_AddRefed<nsAtom> aElementId) {
|
||||
if (mType != eStyleImageType_Null) {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
if (RefPtr<nsAtom> atom = aElementId) {
|
||||
mElementId = atom.forget().take();
|
||||
mType = eStyleImageType_Element;
|
||||
}
|
||||
}
|
||||
|
||||
void nsStyleImage::SetCropRect(UniquePtr<CropRect> aCropRect) {
|
||||
mCropRect = std::move(aCropRect);
|
||||
}
|
||||
|
||||
static int32_t ConvertToPixelCoord(const StyleNumberOrPercentage& aCoord,
|
||||
int32_t aPercentScale) {
|
||||
double pixelValue;
|
||||
@ -1717,109 +1616,105 @@ static int32_t ConvertToPixelCoord(const StyleNumberOrPercentage& aCoord,
|
||||
return NS_lround(pixelValue);
|
||||
}
|
||||
|
||||
bool nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
|
||||
bool* aIsEntireImage) const {
|
||||
MOZ_ASSERT(mType == eStyleImageType_Image,
|
||||
"This function is designed to be used only when mType"
|
||||
"is eStyleImageType_Image.");
|
||||
template <>
|
||||
Maybe<StyleImage::ActualCropRect> StyleImage::ComputeActualCropRect() const {
|
||||
MOZ_ASSERT(IsRect(),
|
||||
"This function is designed to be used only image-rect images");
|
||||
|
||||
imgRequestProxy* req = GetImageData();
|
||||
imgRequestProxy* req = GetImageRequest();
|
||||
if (!req) {
|
||||
return false;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
nsCOMPtr<imgIContainer> imageContainer;
|
||||
req->GetImage(getter_AddRefs(imageContainer));
|
||||
if (!imageContainer) {
|
||||
return false;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
nsIntSize imageSize;
|
||||
imageContainer->GetWidth(&imageSize.width);
|
||||
imageContainer->GetHeight(&imageSize.height);
|
||||
if (imageSize.width <= 0 || imageSize.height <= 0) {
|
||||
return false;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
int32_t left =
|
||||
ConvertToPixelCoord(mCropRect->Get(eSideLeft), imageSize.width);
|
||||
int32_t top = ConvertToPixelCoord(mCropRect->Get(eSideTop), imageSize.height);
|
||||
int32_t right =
|
||||
ConvertToPixelCoord(mCropRect->Get(eSideRight), imageSize.width);
|
||||
int32_t bottom =
|
||||
ConvertToPixelCoord(mCropRect->Get(eSideBottom), imageSize.height);
|
||||
auto& rect = AsRect();
|
||||
|
||||
int32_t left = ConvertToPixelCoord(rect->left, imageSize.width);
|
||||
int32_t top = ConvertToPixelCoord(rect->top, imageSize.height);
|
||||
int32_t right = ConvertToPixelCoord(rect->right, imageSize.width);
|
||||
int32_t bottom = ConvertToPixelCoord(rect->bottom, imageSize.height);
|
||||
|
||||
// IntersectRect() returns an empty rect if we get negative width or height
|
||||
nsIntRect cropRect(left, top, right - left, bottom - top);
|
||||
nsIntRect imageRect(nsIntPoint(0, 0), imageSize);
|
||||
aActualCropRect.IntersectRect(imageRect, cropRect);
|
||||
|
||||
if (aIsEntireImage) {
|
||||
*aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
|
||||
}
|
||||
return true;
|
||||
auto finalRect = imageRect.Intersect(cropRect);
|
||||
bool isEntireImage = finalRect.IsEqualInterior(imageRect);
|
||||
return Some(ActualCropRect{finalRect, isEntireImage});
|
||||
}
|
||||
|
||||
bool nsStyleImage::StartDecoding() const {
|
||||
if (mType == eStyleImageType_Image) {
|
||||
imgRequestProxy* req = GetImageData();
|
||||
if (!req) {
|
||||
return false;
|
||||
}
|
||||
return req->StartDecodingWithResult(imgIContainer::FLAG_ASYNC_NOTIFY);
|
||||
template <>
|
||||
bool StyleImage::StartDecoding() const {
|
||||
if (IsImageRequestType()) {
|
||||
imgRequestProxy* req = GetImageRequest();
|
||||
return req &&
|
||||
req->StartDecodingWithResult(imgIContainer::FLAG_ASYNC_NOTIFY);
|
||||
}
|
||||
// null image types always return false from IsComplete, so we do the same
|
||||
// here.
|
||||
return mType != eStyleImageType_Null;
|
||||
// None always returns false from IsComplete, so we do the same here.
|
||||
return !IsNone();
|
||||
}
|
||||
|
||||
bool nsStyleImage::IsOpaque() const {
|
||||
template <>
|
||||
bool StyleImage::IsOpaque() const {
|
||||
if (!IsComplete()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mType == eStyleImageType_Gradient) {
|
||||
return mGradient->IsOpaque();
|
||||
if (IsGradient()) {
|
||||
return AsGradient()->IsOpaque();
|
||||
}
|
||||
|
||||
if (mType == eStyleImageType_Element) {
|
||||
if (IsElement()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mType == eStyleImageType_Image, "unexpected image type");
|
||||
MOZ_ASSERT(GetImageData(), "should've returned earlier above");
|
||||
MOZ_ASSERT(IsImageRequestType(), "unexpected image type");
|
||||
MOZ_ASSERT(GetImageRequest(), "should've returned earlier above");
|
||||
|
||||
nsCOMPtr<imgIContainer> imageContainer;
|
||||
GetImageData()->GetImage(getter_AddRefs(imageContainer));
|
||||
GetImageRequest()->GetImage(getter_AddRefs(imageContainer));
|
||||
MOZ_ASSERT(imageContainer, "IsComplete() said image container is ready");
|
||||
|
||||
// Check if the crop region of the image is opaque.
|
||||
if (imageContainer->WillDrawOpaqueNow()) {
|
||||
if (!mCropRect) {
|
||||
if (!IsRect()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Must make sure if mCropRect contains at least a pixel.
|
||||
// Must make sure if the crop rect contains at least a pixel.
|
||||
// XXX Is this optimization worth it? Maybe I should just return false.
|
||||
nsIntRect actualCropRect;
|
||||
return ComputeActualCropRect(actualCropRect) && !actualCropRect.IsEmpty();
|
||||
auto croprect = ComputeActualCropRect();
|
||||
return croprect && !croprect->mRect.IsEmpty();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool nsStyleImage::IsComplete() const {
|
||||
switch (mType) {
|
||||
case eStyleImageType_Null:
|
||||
template <>
|
||||
bool StyleImage::IsComplete() const {
|
||||
switch (tag) {
|
||||
case Tag::None:
|
||||
return false;
|
||||
case eStyleImageType_Gradient:
|
||||
case eStyleImageType_Element:
|
||||
case Tag::Gradient:
|
||||
case Tag::Element:
|
||||
return true;
|
||||
case eStyleImageType_Image: {
|
||||
case Tag::Url:
|
||||
case Tag::Rect: {
|
||||
if (!IsResolved()) {
|
||||
return false;
|
||||
}
|
||||
imgRequestProxy* req = GetImageData();
|
||||
imgRequestProxy* req = GetImageRequest();
|
||||
if (!req) {
|
||||
return false;
|
||||
}
|
||||
@ -1834,15 +1729,17 @@ bool nsStyleImage::IsComplete() const {
|
||||
}
|
||||
}
|
||||
|
||||
bool nsStyleImage::IsSizeAvailable() const {
|
||||
switch (mType) {
|
||||
case eStyleImageType_Null:
|
||||
template <>
|
||||
bool StyleImage::IsSizeAvailable() const {
|
||||
switch (tag) {
|
||||
case Tag::None:
|
||||
return false;
|
||||
case eStyleImageType_Gradient:
|
||||
case eStyleImageType_Element:
|
||||
case Tag::Gradient:
|
||||
case Tag::Element:
|
||||
return true;
|
||||
case eStyleImageType_Image: {
|
||||
imgRequestProxy* req = GetImageData();
|
||||
case Tag::Url:
|
||||
case Tag::Rect: {
|
||||
imgRequestProxy* req = GetImageRequest();
|
||||
if (!req) {
|
||||
return false;
|
||||
}
|
||||
@ -1857,47 +1754,16 @@ bool nsStyleImage::IsSizeAvailable() const {
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool EqualRects(const nsStyleImage::CropRect* aRect1,
|
||||
const nsStyleImage::CropRect* aRect2) {
|
||||
return aRect1 == aRect2 || /* handles null== null, and optimize */
|
||||
(aRect1 && aRect2 && *aRect1 == *aRect2);
|
||||
}
|
||||
|
||||
bool nsStyleImage::operator==(const nsStyleImage& aOther) const {
|
||||
if (mType != aOther.mType) {
|
||||
return false;
|
||||
template <>
|
||||
void StyleImage::ResolveImage(Document& aDoc, const StyleImage* aOld) {
|
||||
if (IsResolved()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EqualRects(mCropRect.get(), aOther.mCropRect.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mType == eStyleImageType_Image) {
|
||||
return mImage == aOther.mImage;
|
||||
}
|
||||
|
||||
if (mType == eStyleImageType_Gradient) {
|
||||
return *mGradient == *aOther.mGradient;
|
||||
}
|
||||
|
||||
if (mType == eStyleImageType_Element) {
|
||||
return mElementId == aOther.mElementId;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI> nsStyleImage::GetImageURI() const {
|
||||
if (mType != eStyleImageType_Image) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri = mImage.GetURI();
|
||||
return uri.forget();
|
||||
}
|
||||
|
||||
const StyleComputedImageUrl* nsStyleImage::GetURLValue() const {
|
||||
return mType == eStyleImageType_Image ? &mImage : nullptr;
|
||||
auto* old = aOld ? aOld->GetImageRequestURLValue() : nullptr;
|
||||
auto* url = GetImageRequestURLValue();
|
||||
// We could avoid this const_cast generating more code but it's not really
|
||||
// worth it.
|
||||
const_cast<StyleComputedImageUrl*>(url)->ResolveImage(aDoc, old);
|
||||
}
|
||||
|
||||
// --------------------
|
||||
@ -1986,13 +1852,9 @@ nsStyleImageLayers::nsStyleImageLayers(const nsStyleImageLayers& aSource)
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsElementImage(const nsStyleImageLayers::Layer& aLayer) {
|
||||
return aLayer.mImage.GetType() == eStyleImageType_Element;
|
||||
}
|
||||
|
||||
static bool AnyLayerIsElementImage(const nsStyleImageLayers& aLayers) {
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, aLayers) {
|
||||
if (IsElementImage(aLayers.mLayers[i])) {
|
||||
if (aLayers.mLayers[i].mImage.IsElement()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2025,8 +1887,8 @@ nsChangeHint nsStyleImageLayers::CalcDifference(
|
||||
const Layer& lessLayersLayer = lessLayers.mLayers[i];
|
||||
nsChangeHint layerDifference =
|
||||
moreLayersLayer.CalcDifference(lessLayersLayer);
|
||||
if (layerDifference && (IsElementImage(moreLayersLayer) ||
|
||||
IsElementImage(lessLayersLayer))) {
|
||||
if (layerDifference && (moreLayersLayer.mImage.IsElement() ||
|
||||
lessLayersLayer.mImage.IsElement())) {
|
||||
layerDifference |=
|
||||
nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
|
||||
}
|
||||
@ -2044,8 +1906,8 @@ nsChangeHint nsStyleImageLayers::CalcDifference(
|
||||
}
|
||||
|
||||
const Layer& lessLayersLayer = lessLayers.mLayers[i];
|
||||
MOZ_ASSERT(moreLayersLayer.mImage.GetType() == eStyleImageType_Null);
|
||||
MOZ_ASSERT(lessLayersLayer.mImage.GetType() == eStyleImageType_Null);
|
||||
MOZ_ASSERT(moreLayersLayer.mImage.IsNone());
|
||||
MOZ_ASSERT(lessLayersLayer.mImage.IsNone());
|
||||
if (moreLayersLayer.CalcDifference(lessLayersLayer)) {
|
||||
// We don't care about the difference returned, we know it's not visible,
|
||||
// but if something changed, then we need to return the neutral change.
|
||||
@ -2182,9 +2044,8 @@ bool nsStyleImageLayers::IsInitialPositionForLayerType(Position aPosition,
|
||||
}
|
||||
|
||||
static bool SizeDependsOnPositioningAreaSize(const StyleBackgroundSize& aSize,
|
||||
const nsStyleImage& aImage) {
|
||||
MOZ_ASSERT(aImage.GetType() != eStyleImageType_Null,
|
||||
"caller should have handled this");
|
||||
const StyleImage& aImage) {
|
||||
MOZ_ASSERT(!aImage.IsNone(), "caller should have handled this");
|
||||
|
||||
// Contain and cover straightforwardly depend on frame size.
|
||||
if (aSize.IsCover() || aSize.IsContain()) {
|
||||
@ -2205,27 +2066,24 @@ static bool SizeDependsOnPositioningAreaSize(const StyleBackgroundSize& aSize,
|
||||
return false;
|
||||
}
|
||||
|
||||
nsStyleImageType type = aImage.GetType();
|
||||
|
||||
// Gradient rendering depends on frame size when auto is involved because
|
||||
// gradients have no intrinsic ratio or dimensions, and therefore the relevant
|
||||
// dimension is "treat[ed] as 100%".
|
||||
if (type == eStyleImageType_Gradient) {
|
||||
if (aImage.IsGradient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// XXX Element rendering for auto or fixed length doesn't depend on frame size
|
||||
// according to the spec. However, we don't implement the spec yet, so
|
||||
// for now we bail and say element() plus auto affects ultimate size.
|
||||
if (type == eStyleImageType_Element) {
|
||||
if (aImage.IsElement()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == eStyleImageType_Image) {
|
||||
MOZ_ASSERT(aImage.IsImageRequestType(), "Missed some image");
|
||||
if (auto* request = aImage.GetImageRequest()) {
|
||||
nsCOMPtr<imgIContainer> imgContainer;
|
||||
if (imgRequestProxy* req = aImage.GetImageData()) {
|
||||
req->GetImage(getter_AddRefs(imgContainer));
|
||||
}
|
||||
request->GetImage(getter_AddRefs(imgContainer));
|
||||
if (imgContainer) {
|
||||
CSSIntSize imageSize;
|
||||
AspectRatio imageRatio;
|
||||
@ -2250,8 +2108,6 @@ static bool SizeDependsOnPositioningAreaSize(const StyleBackgroundSize& aSize,
|
||||
return !(hasWidth && size.width.IsLengthPercentage()) &&
|
||||
!(hasHeight && size.height.IsLengthPercentage());
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("missed an enum value");
|
||||
}
|
||||
|
||||
// Passed the gauntlet: no dependency.
|
||||
@ -2259,14 +2115,15 @@ static bool SizeDependsOnPositioningAreaSize(const StyleBackgroundSize& aSize,
|
||||
}
|
||||
|
||||
nsStyleImageLayers::Layer::Layer()
|
||||
: mSize(StyleBackgroundSize::ExplicitSize(LengthPercentageOrAuto::Auto(),
|
||||
: mImage(StyleImage::None()),
|
||||
mSize(StyleBackgroundSize::ExplicitSize(LengthPercentageOrAuto::Auto(),
|
||||
LengthPercentageOrAuto::Auto())),
|
||||
|
||||
mClip(StyleGeometryBox::BorderBox),
|
||||
mAttachment(StyleImageLayerAttachment::Scroll),
|
||||
mBlendMode(NS_STYLE_BLEND_NORMAL),
|
||||
mComposite(NS_STYLE_MASK_COMPOSITE_ADD),
|
||||
mMaskMode(StyleMaskMode::MatchSource) {
|
||||
mImage.SetNull();
|
||||
}
|
||||
|
||||
nsStyleImageLayers::Layer::~Layer() {}
|
||||
@ -2288,7 +2145,7 @@ void nsStyleImageLayers::Layer::Initialize(
|
||||
bool nsStyleImageLayers::Layer::
|
||||
RenderingMightDependOnPositioningAreaSizeChange() const {
|
||||
// Do we even have an image?
|
||||
if (mImage.IsEmpty()) {
|
||||
if (mImage.IsNone()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2352,10 +2209,10 @@ void nsStyleImageLayers::FillAllLayers(uint32_t aMaxItemCount) {
|
||||
FillImageLayerList(mLayers, &Layer::mComposite, mCompositeCount, fillCount);
|
||||
}
|
||||
|
||||
static bool UrlValuesEqual(const nsStyleImage& aImage,
|
||||
const nsStyleImage& aOtherImage) {
|
||||
auto* url = aImage.GetURLValue();
|
||||
auto* other = aOtherImage.GetURLValue();
|
||||
static bool UrlValuesEqual(const StyleImage& aImage,
|
||||
const StyleImage& aOtherImage) {
|
||||
auto* url = aImage.GetImageRequestURLValue();
|
||||
auto* other = aOtherImage.GetImageRequestURLValue();
|
||||
return url == other || (url && other && *url == *other);
|
||||
}
|
||||
|
||||
@ -2419,7 +2276,7 @@ bool nsStyleBackground::HasFixedBackground(nsIFrame* aFrame) const {
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mImage) {
|
||||
const nsStyleImageLayers::Layer& layer = mImage.mLayers[i];
|
||||
if (layer.mAttachment == StyleImageLayerAttachment::Fixed &&
|
||||
!layer.mImage.IsEmpty() && !nsLayoutUtils::IsTransformed(aFrame)) {
|
||||
!layer.mImage.IsNone() && !nsLayoutUtils::IsTransformed(aFrame)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2439,7 +2296,7 @@ bool nsStyleBackground::IsTransparent(const nsIFrame* aFrame) const {
|
||||
}
|
||||
|
||||
bool nsStyleBackground::IsTransparent(mozilla::ComputedStyle* aStyle) const {
|
||||
return BottomLayer().mImage.IsEmpty() && mImage.mImageCount == 1 &&
|
||||
return BottomLayer().mImage.IsNone() && mImage.mImageCount == 1 &&
|
||||
NS_GET_A(BackgroundColor(aStyle)) == 0;
|
||||
}
|
||||
|
||||
|
@ -132,13 +132,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont {
|
||||
RefPtr<nsAtom> mLanguage;
|
||||
};
|
||||
|
||||
enum nsStyleImageType {
|
||||
eStyleImageType_Null,
|
||||
eStyleImageType_Image,
|
||||
eStyleImageType_Gradient,
|
||||
eStyleImageType_Element,
|
||||
};
|
||||
|
||||
// TODO(emilio, bug 1564526): Evaluate whether this is still needed.
|
||||
struct CachedBorderImageData {
|
||||
~CachedBorderImageData() { PurgeCachedImages(); }
|
||||
@ -177,144 +170,6 @@ struct CachedBorderImageData {
|
||||
nsTArray<RefPtr<imgIContainer>> mSubImages;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a paintable image of one of the following types.
|
||||
* (1) A real image loaded from an external source.
|
||||
* (2) A CSS linear or radial gradient.
|
||||
* (3) An element within a document, or an <img>, <video>, or <canvas> element
|
||||
* not in a document.
|
||||
* (*) Optionally a crop rect can be set to paint a partial (rectangular)
|
||||
* region of an image. (Currently, this feature is only supported with an
|
||||
* image of type (1)).
|
||||
*/
|
||||
struct nsStyleImage {
|
||||
using CropRect = mozilla::StyleRect<mozilla::StyleNumberOrPercentage>;
|
||||
|
||||
nsStyleImage();
|
||||
~nsStyleImage();
|
||||
nsStyleImage(const nsStyleImage& aOther);
|
||||
nsStyleImage& operator=(const nsStyleImage& aOther);
|
||||
|
||||
void SetNull();
|
||||
void SetImageUrl(const mozilla::StyleComputedImageUrl&);
|
||||
void SetGradientData(mozilla::UniquePtr<mozilla::StyleGradient>);
|
||||
void SetElementId(already_AddRefed<nsAtom> aElementId);
|
||||
void SetCropRect(mozilla::UniquePtr<CropRect> aCropRect);
|
||||
|
||||
void ResolveImage(mozilla::dom::Document& aDocument,
|
||||
const nsStyleImage* aOldImage) {
|
||||
if (mType == eStyleImageType_Image && !mImage.IsImageResolved()) {
|
||||
const auto* oldRequest =
|
||||
(aOldImage && aOldImage->GetType() == eStyleImageType_Image)
|
||||
? &aOldImage->ImageUrl()
|
||||
: nullptr;
|
||||
mImage.ResolveImage(aDocument, oldRequest);
|
||||
}
|
||||
}
|
||||
|
||||
nsStyleImageType GetType() const { return mType; }
|
||||
const mozilla::StyleComputedImageUrl& ImageUrl() const {
|
||||
MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
|
||||
return mImage;
|
||||
}
|
||||
imgRequestProxy* GetImageData() const { return ImageUrl().GetImage(); }
|
||||
const mozilla::StyleGradient& GetGradient() const {
|
||||
NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
|
||||
return *mGradient;
|
||||
}
|
||||
bool IsResolved() const {
|
||||
return mType != eStyleImageType_Image || ImageUrl().IsImageResolved();
|
||||
}
|
||||
const nsAtom* GetElementId() const {
|
||||
NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
|
||||
return mElementId;
|
||||
}
|
||||
const CropRect* GetCropRect() const {
|
||||
NS_ASSERTION(mType == eStyleImageType_Image,
|
||||
"Only image data can have a crop rect");
|
||||
return mCropRect.get();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI> GetImageURI() const;
|
||||
|
||||
const mozilla::StyleComputedImageUrl* GetURLValue() const;
|
||||
|
||||
/**
|
||||
* Compute the actual crop rect in pixels, using the source image bounds.
|
||||
* The computation involves converting percentage unit to pixel unit and
|
||||
* clamping each side value to fit in the source image bounds.
|
||||
* @param aActualCropRect the computed actual crop rect.
|
||||
* @param aIsEntireImage true iff |aActualCropRect| is identical to the
|
||||
* source image bounds.
|
||||
* @return true iff |aActualCropRect| holds a meaningful value.
|
||||
*/
|
||||
bool ComputeActualCropRect(nsIntRect& aActualCropRect,
|
||||
bool* aIsEntireImage = nullptr) const;
|
||||
|
||||
/**
|
||||
* Starts the decoding of a image. Returns true if the current frame of the
|
||||
* image is complete. The return value is intended to be used instead of
|
||||
* IsComplete because IsComplete may not be up to date if notifications
|
||||
* from decoding are pending because they are being sent async.
|
||||
*/
|
||||
bool StartDecoding() const;
|
||||
/**
|
||||
* @return true if the item is definitely opaque --- i.e., paints every
|
||||
* pixel within its bounds opaquely, and the bounds contains at least a pixel.
|
||||
*/
|
||||
bool IsOpaque() const;
|
||||
/**
|
||||
* @return true if this image is fully loaded, and its size is calculated;
|
||||
* always returns true if |mType| is |eStyleImageType_Gradient| or
|
||||
* |eStyleImageType_Element|.
|
||||
*/
|
||||
bool IsComplete() const;
|
||||
/**
|
||||
* @return true if this image has an available size, and hasn't errored.
|
||||
* always returns true if |mType| is |eStyleImageType_Gradient| or
|
||||
* |eStyleImageType_Element|.
|
||||
*/
|
||||
bool IsSizeAvailable() const;
|
||||
/**
|
||||
* @return true if it is 100% confident that this image contains no pixel
|
||||
* to draw.
|
||||
*/
|
||||
bool IsEmpty() const {
|
||||
// There are some other cases when the image will be empty, for example
|
||||
// when the crop rect is empty. However, checking the emptiness of crop
|
||||
// rect is non-trivial since each side value can be specified with
|
||||
// percentage unit, which can not be evaluated until the source image size
|
||||
// is available. Therefore, we currently postpone the evaluation of crop
|
||||
// rect until the actual rendering time --- alternatively until
|
||||
// GetOpaqueRegion() is called.
|
||||
return mType == eStyleImageType_Null;
|
||||
}
|
||||
|
||||
bool operator==(const nsStyleImage& aOther) const;
|
||||
bool operator!=(const nsStyleImage& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
bool ImageDataEquals(const nsStyleImage& aOther) const {
|
||||
return GetType() == eStyleImageType_Image &&
|
||||
aOther.GetType() == eStyleImageType_Image &&
|
||||
GetImageData() == aOther.GetImageData();
|
||||
}
|
||||
|
||||
private:
|
||||
void DoCopy(const nsStyleImage& aOther);
|
||||
|
||||
// This is _currently_ used only in conjunction with eStyleImageType_Image.
|
||||
mozilla::UniquePtr<CropRect> mCropRect;
|
||||
|
||||
nsStyleImageType mType;
|
||||
union {
|
||||
mozilla::StyleComputedImageUrl mImage;
|
||||
mozilla::StyleGradient* mGradient;
|
||||
nsAtom* mElementId;
|
||||
};
|
||||
};
|
||||
|
||||
struct nsStyleImageLayers {
|
||||
// Indices into kBackgroundLayerTable and kMaskLayerTable
|
||||
enum {
|
||||
@ -374,7 +229,7 @@ struct nsStyleImageLayers {
|
||||
typedef mozilla::StyleImageLayerAttachment StyleImageLayerAttachment;
|
||||
typedef mozilla::StyleBackgroundSize StyleBackgroundSize;
|
||||
|
||||
nsStyleImage mImage;
|
||||
mozilla::StyleImage mImage;
|
||||
mozilla::Position mPosition;
|
||||
StyleBackgroundSize mSize;
|
||||
StyleGeometryBox mClip;
|
||||
@ -653,7 +508,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder {
|
||||
|
||||
bool HasBorder() const {
|
||||
return mComputedBorder != nsMargin(0, 0, 0, 0) ||
|
||||
!mBorderImageSource.IsEmpty();
|
||||
!mBorderImageSource.IsNone();
|
||||
}
|
||||
|
||||
// Get the actual border width for a particular side, in appunits. Note that
|
||||
@ -683,15 +538,12 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder {
|
||||
nsMargin GetImageOutset() const;
|
||||
|
||||
imgIRequest* GetBorderImageRequest() const {
|
||||
if (mBorderImageSource.GetType() == eStyleImageType_Image) {
|
||||
return mBorderImageSource.GetImageData();
|
||||
}
|
||||
return nullptr;
|
||||
return mBorderImageSource.GetImageRequest();
|
||||
}
|
||||
|
||||
public:
|
||||
mozilla::StyleBorderRadius mBorderRadius; // coord, percent
|
||||
nsStyleImage mBorderImageSource;
|
||||
mozilla::StyleImage mBorderImageSource;
|
||||
mozilla::StyleBorderImageWidth mBorderImageWidth;
|
||||
mozilla::StyleNonNegativeLengthOrNumberRect mBorderImageOutset;
|
||||
mozilla::StyleBorderImageSlice mBorderImageSlice; // factor, percent
|
||||
@ -1317,7 +1169,7 @@ struct StyleShapeSource final {
|
||||
|
||||
StyleShapeSourceType GetType() const { return mType; }
|
||||
|
||||
const nsStyleImage& ShapeImage() const {
|
||||
const StyleImage& ShapeImage() const {
|
||||
MOZ_ASSERT(mType == StyleShapeSourceType::Image,
|
||||
"Wrong shape source type!");
|
||||
MOZ_ASSERT(mShapeImage);
|
||||
@ -1329,9 +1181,9 @@ struct StyleShapeSource final {
|
||||
// null.
|
||||
imgIRequest* GetShapeImageData() const;
|
||||
|
||||
void SetShapeImage(UniquePtr<nsStyleImage> aShapeImage);
|
||||
void SetShapeImage(UniquePtr<StyleImage> aShapeImage);
|
||||
|
||||
const mozilla::StyleBasicShape& BasicShape() const {
|
||||
const StyleBasicShape& BasicShape() const {
|
||||
MOZ_ASSERT(mType == StyleShapeSourceType::Shape,
|
||||
"Wrong shape source type!");
|
||||
MOZ_ASSERT(mBasicShape);
|
||||
@ -1367,9 +1219,9 @@ struct StyleShapeSource final {
|
||||
void DoDestroy();
|
||||
|
||||
union {
|
||||
mozilla::UniquePtr<mozilla::StyleBasicShape> mBasicShape;
|
||||
mozilla::UniquePtr<nsStyleImage> mShapeImage;
|
||||
mozilla::UniquePtr<StyleSVGPath> mSVGPath;
|
||||
UniquePtr<StyleBasicShape> mBasicShape;
|
||||
UniquePtr<StyleImage> mShapeImage;
|
||||
UniquePtr<StyleSVGPath> mSVGPath;
|
||||
// TODO: Bug 1480665, implement ray() function.
|
||||
};
|
||||
StyleShapeSourceType mType = StyleShapeSourceType::None;
|
||||
|
@ -199,7 +199,7 @@ mozilla::StylePointerEvents nsStyleUI::GetEffectivePointerEvents(
|
||||
bool nsStyleBackground::HasLocalBackground() const {
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mImage) {
|
||||
const nsStyleImageLayers::Layer& layer = mImage.mLayers[i];
|
||||
if (!layer.mImage.IsEmpty() &&
|
||||
if (!layer.mImage.IsNone() &&
|
||||
layer.mAttachment == mozilla::StyleImageLayerAttachment::Local) {
|
||||
return true;
|
||||
}
|
||||
|
@ -849,7 +849,7 @@ SVGMaskObserverList::SVGMaskObserverList(nsIFrame* aFrame) : mFrame(aFrame) {
|
||||
|
||||
for (uint32_t i = 0; i < svgReset->mMask.mImageCount; i++) {
|
||||
const StyleComputedImageUrl* data =
|
||||
svgReset->mMask.mLayers[i].mImage.GetURLValue();
|
||||
svgReset->mMask.mLayers[i].mImage.GetImageRequestURLValue();
|
||||
RefPtr<URLAndReferrerInfo> maskUri;
|
||||
if (data) {
|
||||
maskUri = ResolveURLUsingLocalRef(aFrame, *data);
|
||||
@ -876,17 +876,16 @@ void SVGMaskObserverList::ResolveImage(uint32_t aIndex) {
|
||||
const nsStyleSVGReset* svgReset = mFrame->StyleSVGReset();
|
||||
MOZ_ASSERT(aIndex < svgReset->mMask.mImageCount);
|
||||
|
||||
auto& image =
|
||||
const_cast<nsStyleImage&>(svgReset->mMask.mLayers[aIndex].mImage);
|
||||
|
||||
if (!image.IsResolved()) {
|
||||
MOZ_ASSERT(image.GetType() == nsStyleImageType::eStyleImageType_Image);
|
||||
image.ResolveImage(*mFrame->PresContext()->Document(), nullptr);
|
||||
|
||||
Document* doc = mFrame->PresContext()->Document();
|
||||
if (imgRequestProxy* req = image.GetImageData()) {
|
||||
doc->StyleImageLoader()->AssociateRequestToFrame(req, mFrame, 0);
|
||||
}
|
||||
auto& image = const_cast<StyleImage&>(svgReset->mMask.mLayers[aIndex].mImage);
|
||||
if (image.IsResolved()) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(image.IsImageRequestType());
|
||||
Document* doc = mFrame->PresContext()->Document();
|
||||
image.ResolveImage(*doc, nullptr);
|
||||
if (imgRequestProxy* req = image.GetImageRequest()) {
|
||||
// FIXME(emilio): What disassociates this request?
|
||||
doc->StyleImageLoader()->AssociateRequestToFrame(req, mFrame, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1265,8 +1264,9 @@ static nsSVGPaintingProperty* GetOrCreateClipPathObserver(
|
||||
if (svgStyleReset->mClipPath.GetType() != StyleShapeSourceType::Image) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto* url = svgStyleReset->mClipPath.ShapeImage().GetURLValue();
|
||||
MOZ_ASSERT(url);
|
||||
const auto* url =
|
||||
svgStyleReset->mClipPath.ShapeImage().GetImageRequestURLValue();
|
||||
MOZ_ASSERT(url, "Clip-path only supports url() images");
|
||||
RefPtr<URLAndReferrerInfo> pathURI =
|
||||
ResolveURLUsingLocalRef(aClippedFrame, *url);
|
||||
return GetPaintingProperty(pathURI, aClippedFrame, ClipPathProperty());
|
||||
|
@ -10,87 +10,10 @@
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use crate::gecko_bindings::bindings;
|
||||
use crate::gecko_bindings::structs::{self, Matrix4x4Components};
|
||||
use crate::gecko_bindings::structs::{nsStyleImage, nsresult};
|
||||
use crate::gecko_bindings::structs::{self, Matrix4x4Components, nsresult};
|
||||
use crate::stylesheets::RulesMutateError;
|
||||
use crate::values::computed::transform::Matrix3D;
|
||||
use crate::values::computed::{Gradient, Image, TextAlign};
|
||||
use crate::values::generics::image::GenericImage;
|
||||
use crate::values::generics::rect::Rect;
|
||||
|
||||
impl nsStyleImage {
|
||||
/// Set a given Servo `Image` value into this `nsStyleImage`.
|
||||
pub fn set(&mut self, image: Image) {
|
||||
match image {
|
||||
GenericImage::None => unsafe {
|
||||
bindings::Gecko_SetNullImageValue(self);
|
||||
},
|
||||
GenericImage::Gradient(boxed_gradient) => self.set_gradient(boxed_gradient),
|
||||
GenericImage::Url(ref url) => unsafe {
|
||||
bindings::Gecko_SetLayerImageImageValue(self, url);
|
||||
},
|
||||
GenericImage::Rect(ref image_rect) => {
|
||||
unsafe {
|
||||
bindings::Gecko_SetLayerImageImageValue(self, &image_rect.url);
|
||||
bindings::Gecko_InitializeImageCropRect(self);
|
||||
|
||||
// Set CropRect
|
||||
let ref mut rect = *self.mCropRect.mPtr;
|
||||
*rect = Rect(
|
||||
image_rect.top,
|
||||
image_rect.right,
|
||||
image_rect.bottom,
|
||||
image_rect.left,
|
||||
);
|
||||
}
|
||||
},
|
||||
GenericImage::Element(ref element) => unsafe {
|
||||
bindings::Gecko_SetImageElement(self, element.as_ptr());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn set_gradient(&mut self, gradient: Box<Gradient>) {
|
||||
unsafe {
|
||||
bindings::Gecko_SetGradientImageValue(self, Box::into_raw(gradient));
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts into Image.
|
||||
pub unsafe fn to_image(&self) -> Image {
|
||||
use crate::gecko_bindings::structs::nsStyleImageType;
|
||||
use crate::values::computed::MozImageRect;
|
||||
|
||||
match self.mType {
|
||||
nsStyleImageType::eStyleImageType_Null => GenericImage::None,
|
||||
nsStyleImageType::eStyleImageType_Image => {
|
||||
let url = self.__bindgen_anon_1.mImage.as_ref().clone();
|
||||
if self.mCropRect.mPtr.is_null() {
|
||||
GenericImage::Url(url)
|
||||
} else {
|
||||
let rect = &*self.mCropRect.mPtr;
|
||||
GenericImage::Rect(Box::new(MozImageRect {
|
||||
url,
|
||||
top: rect.0,
|
||||
right: rect.1,
|
||||
bottom: rect.2,
|
||||
left: rect.3,
|
||||
}))
|
||||
}
|
||||
},
|
||||
nsStyleImageType::eStyleImageType_Gradient => {
|
||||
let gradient: &Gradient = &**self.__bindgen_anon_1.mGradient.as_ref();
|
||||
GenericImage::Gradient(Box::new(gradient.clone()))
|
||||
},
|
||||
nsStyleImageType::eStyleImageType_Element => {
|
||||
use crate::gecko_string_cache::Atom;
|
||||
let atom = bindings::Gecko_GetImageElement(self);
|
||||
GenericImage::Element(Atom::from_raw(atom))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
use crate::values::computed::TextAlign;
|
||||
|
||||
pub mod basic_shape {
|
||||
//! Conversions from and to CSS shape representations.
|
||||
@ -148,9 +71,8 @@ pub mod basic_shape {
|
||||
use crate::values::generics::image::Image as GenericImage;
|
||||
|
||||
let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
|
||||
let image = shape_image.to_image();
|
||||
match image {
|
||||
GenericImage::Url(url) => ShapeSource::ImageOrUrl(url.0),
|
||||
match *shape_image {
|
||||
GenericImage::Url(ref url) => ShapeSource::ImageOrUrl(url.0.clone()),
|
||||
_ => panic!("ClippingShape doesn't support non-url images"),
|
||||
}
|
||||
},
|
||||
@ -166,8 +88,7 @@ pub mod basic_shape {
|
||||
match other.mType {
|
||||
StyleShapeSourceType::Image => unsafe {
|
||||
let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
|
||||
let image = shape_image.to_image();
|
||||
ShapeSource::ImageOrUrl(image)
|
||||
ShapeSource::ImageOrUrl(shape_image.clone())
|
||||
},
|
||||
_ => other
|
||||
.to_shape_source()
|
||||
|
@ -24,11 +24,9 @@ use crate::gecko_bindings::bindings::Gecko_Destroy_${style_struct.gecko_ffi_name
|
||||
use crate::gecko_bindings::bindings::Gecko_CopyCounterStyle;
|
||||
use crate::gecko_bindings::bindings::Gecko_CopyCursorArrayFrom;
|
||||
use crate::gecko_bindings::bindings::Gecko_CopyFontFamilyFrom;
|
||||
use crate::gecko_bindings::bindings::Gecko_CopyImageValueFrom;
|
||||
use crate::gecko_bindings::bindings::Gecko_EnsureImageLayersLength;
|
||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_SetLang;
|
||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom;
|
||||
use crate::gecko_bindings::bindings::Gecko_SetNullImageValue;
|
||||
use crate::gecko_bindings::structs;
|
||||
use crate::gecko_bindings::structs::nsCSSPropertyID;
|
||||
use crate::gecko_bindings::structs::mozilla::PseudoStyleType;
|
||||
@ -777,8 +775,7 @@ fn static_assert() {
|
||||
for x in CORNERS]) %>
|
||||
|
||||
<%self:impl_trait style_struct_name="Border"
|
||||
skip_longhands="${skip_border_longhands} border-image-source
|
||||
border-image-repeat">
|
||||
skip_longhands="${skip_border_longhands} border-image-repeat">
|
||||
% for side in SIDES:
|
||||
pub fn set_border_${side.ident}_style(&mut self, v: BorderStyle) {
|
||||
self.gecko.mBorderStyle[${side.index}] = v;
|
||||
@ -847,25 +844,6 @@ fn static_assert() {
|
||||
corner) %>
|
||||
% endfor
|
||||
|
||||
pub fn set_border_image_source(&mut self, image: longhands::border_image_source::computed_value::T) {
|
||||
self.gecko.mBorderImageSource.set(image);
|
||||
}
|
||||
|
||||
pub fn copy_border_image_source_from(&mut self, other: &Self) {
|
||||
unsafe {
|
||||
Gecko_CopyImageValueFrom(&mut self.gecko.mBorderImageSource,
|
||||
&other.gecko.mBorderImageSource);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_border_image_source(&mut self, other: &Self) {
|
||||
self.copy_border_image_source_from(other)
|
||||
}
|
||||
|
||||
pub fn clone_border_image_source(&self) -> longhands::border_image_source::computed_value::T {
|
||||
unsafe { self.gecko.mBorderImageSource.to_image() }
|
||||
}
|
||||
|
||||
<%
|
||||
border_image_repeat_keywords = ["Stretch", "Repeat", "Round", "Space"]
|
||||
%>
|
||||
@ -1998,7 +1976,7 @@ fn static_assert() {
|
||||
for (layer, other) in self.gecko.${image_layers_field}.mLayers.iter_mut()
|
||||
.zip(other.gecko.${image_layers_field}.mLayers.iter())
|
||||
.take(count as usize) {
|
||||
Gecko_CopyImageValueFrom(&mut layer.mImage, &other.mImage);
|
||||
layer.mImage = other.mImage.clone();
|
||||
}
|
||||
self.gecko.${image_layers_field}.mImageCount = count;
|
||||
}
|
||||
@ -2018,20 +1996,17 @@ fn static_assert() {
|
||||
let images = images.into_iter();
|
||||
|
||||
unsafe {
|
||||
// Prevent leaking of the last elements we did set
|
||||
for image in &mut self.gecko.${image_layers_field}.mLayers {
|
||||
Gecko_SetNullImageValue(&mut image.mImage)
|
||||
}
|
||||
// XXXManishearth clear mSourceURI for masks
|
||||
Gecko_EnsureImageLayersLength(&mut self.gecko.${image_layers_field}, images.len(),
|
||||
LayerType::${shorthand.title()});
|
||||
Gecko_EnsureImageLayersLength(
|
||||
&mut self.gecko.${image_layers_field},
|
||||
images.len(),
|
||||
LayerType::${shorthand.title()},
|
||||
);
|
||||
}
|
||||
|
||||
self.gecko.${image_layers_field}.mImageCount = images.len() as u32;
|
||||
|
||||
for (image, geckoimage) in images.zip(self.gecko.${image_layers_field}
|
||||
.mLayers.iter_mut()) {
|
||||
geckoimage.mImage.set(image)
|
||||
geckoimage.mImage = image;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2039,7 +2014,7 @@ fn static_assert() {
|
||||
longhands::${shorthand}_image::computed_value::List(
|
||||
self.gecko.${image_layers_field}.mLayers.iter()
|
||||
.take(self.gecko.${image_layers_field}.mImageCount as usize)
|
||||
.map(|layer| unsafe { layer.mImage.to_image() })
|
||||
.map(|layer| layer.mImage.clone())
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
@ -2266,7 +2241,7 @@ fn set_style_svg_path(
|
||||
unsafe {
|
||||
bindings::Gecko_NewShapeImage(${ident});
|
||||
let style_image = &mut *${ident}.__bindgen_anon_1.mShapeImage.as_mut().mPtr;
|
||||
style_image.set(image);
|
||||
*style_image = image;
|
||||
}
|
||||
}
|
||||
ShapeSource::Box(reference) => {
|
||||
|
@ -703,31 +703,76 @@ renaming_overrides_prefixing = true
|
||||
"""
|
||||
|
||||
"GenericRotate" = """
|
||||
public:
|
||||
public:
|
||||
// The implementation of IPC LayersMessages needs this to be public.
|
||||
StyleGenericRotate(): tag(Tag::None) {}
|
||||
"""
|
||||
|
||||
"GenericScale" = """
|
||||
public:
|
||||
public:
|
||||
// The implementation of IPC LayersMessages needs this to be public.
|
||||
StyleGenericScale(): tag(Tag::None) {}
|
||||
"""
|
||||
|
||||
"GenericTranslate" = """
|
||||
public:
|
||||
public:
|
||||
// The implementation of IPC LayersMessages needs this to be public.
|
||||
StyleGenericTranslate(): tag(Tag::None) {}
|
||||
"""
|
||||
|
||||
"GenericOffsetPath" = """
|
||||
public:
|
||||
public:
|
||||
// The implementation of IPC LayersMessages needs this to be public.
|
||||
StyleGenericOffsetPath(): tag(Tag::None) {}
|
||||
"""
|
||||
|
||||
"GenericPositionOrAuto" = """
|
||||
public:
|
||||
public:
|
||||
// The implementation of IPC LayersMessages needs this to be public.
|
||||
StyleGenericPositionOrAuto(): tag(Tag::Auto) {}
|
||||
"""
|
||||
|
||||
"GenericImage" = """
|
||||
public:
|
||||
// Whether this image may have an image request associated with it.
|
||||
bool IsImageRequestType() const;
|
||||
|
||||
// Gets the image request URL.
|
||||
const StyleComputedImageUrl* GetImageRequestURLValue() const;
|
||||
|
||||
// Gets the image data of this image if it has any image request.
|
||||
imgRequestProxy* GetImageRequest() const;
|
||||
|
||||
// Returns true if this image is fully loaded, and its size is calculated.
|
||||
// Always returns true if there's no image request involved and this image
|
||||
// is not `none`.
|
||||
bool IsComplete() const;
|
||||
|
||||
// Returns true if this image has an available size and hasn't errored.
|
||||
// Always returns true if there's no image request involved and this image
|
||||
// is not `none`.
|
||||
bool IsSizeAvailable() const;
|
||||
|
||||
// Starts the decoding of a image. Returns true if the current frame of the
|
||||
// image is complete. The return value is intended to be used instead of
|
||||
// IsComplete because IsComplete may not be up to date if notifications
|
||||
// from decoding are pending because they are being sent async.
|
||||
bool StartDecoding() const;
|
||||
|
||||
// Returns true if the item is definitely opaque --- i.e., paints every
|
||||
// pixel within its bounds opaquely, and the bounds contains at least a pixel.
|
||||
bool IsOpaque() const;
|
||||
|
||||
struct ActualCropRect {
|
||||
nsIntRect mRect; // in image pixels
|
||||
bool mIsEntireImage;
|
||||
};
|
||||
|
||||
Maybe<ActualCropRect> ComputeActualCropRect() const;
|
||||
|
||||
// Resolves the underlying image request if any.
|
||||
void ResolveImage(dom::Document&, const StyleGenericImage* aOld);
|
||||
|
||||
// Returns whether this image has been resolved.
|
||||
bool IsResolved() const;
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user