зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 11 changesets (bug 1404222) for static analysis failures on a CLOSED TREE.
Backed out changeset a6a99136300c (bug 1404222) Backed out changeset 7183b8104399 (bug 1404222) Backed out changeset a1e4294c1c59 (bug 1404222) Backed out changeset b79d6e8318db (bug 1404222) Backed out changeset 0450620fdabd (bug 1404222) Backed out changeset 026c74a92d04 (bug 1404222) Backed out changeset 50ac4167f702 (bug 1404222) Backed out changeset 59038f2db68a (bug 1404222) Backed out changeset f6b9096da915 (bug 1404222) Backed out changeset 4e0baffdd79b (bug 1404222) Backed out changeset 57eeb849ab88 (bug 1404222)
This commit is contained in:
Родитель
9a28e89f4e
Коммит
e5ec40f40c
|
@ -1,2 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<div style="float: left; shape-outside: linear-gradient(to top, green 50%, transparent 50%);"></div>
|
|
@ -674,7 +674,6 @@ load 1381134-2.html
|
|||
load 1401420-1.html
|
||||
load 1401709.html
|
||||
load 1401807.html
|
||||
load 1404222-empty-shape.html
|
||||
load 1405443.html
|
||||
load 1415185.html
|
||||
load 1416544.html
|
||||
|
|
|
@ -11,12 +11,10 @@
|
|||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "mozilla/ReflowInput.h"
|
||||
#include "mozilla/ShapeUtils.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsError.h"
|
||||
#include "nsImageRenderer.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsMemory.h"
|
||||
|
||||
|
@ -177,8 +175,9 @@ nsFloatManager::GetFlowArea(WritingMode aWM, nscoord aBCoord, nscoord aBSize,
|
|||
break;
|
||||
}
|
||||
if (fi.IsEmpty(aShapeType)) {
|
||||
// Ignore empty float areas.
|
||||
// https://drafts.csswg.org/css-shapes/#relation-to-box-model-and-float-behavior
|
||||
// For compatibility, ignore floats with empty rects, even though it
|
||||
// disagrees with the spec. (We might want to fix this in the
|
||||
// future, though.)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -581,13 +580,6 @@ public:
|
|||
WritingMode aWM,
|
||||
const nsSize& aContainerSize);
|
||||
|
||||
static UniquePtr<ShapeInfo> CreateImageShape(
|
||||
const UniquePtr<nsStyleImage>& aShapeImage,
|
||||
float aShapeImageThreshold,
|
||||
nsIFrame* const aFrame,
|
||||
WritingMode aWM,
|
||||
const nsSize& aContainerSize);
|
||||
|
||||
protected:
|
||||
// Compute the minimum line-axis difference between the bounding shape
|
||||
// box and its rounded corner within the given band (block-axis region).
|
||||
|
@ -623,7 +615,6 @@ protected:
|
|||
// RoundedBoxShapeInfo
|
||||
//
|
||||
// Implements shape-outside: <shape-box> and shape-outside: inset().
|
||||
//
|
||||
class nsFloatManager::RoundedBoxShapeInfo final : public nsFloatManager::ShapeInfo
|
||||
{
|
||||
public:
|
||||
|
@ -961,246 +952,6 @@ nsFloatManager::PolygonShapeInfo::XInterceptAtY(const nscoord aY,
|
|||
return aP1.x + (aY - aP1.y) * (aP2.x - aP1.x) / (aP2.y - aP1.y);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// ImageShapeInfo
|
||||
//
|
||||
// Implements shape-outside: <image>
|
||||
//
|
||||
class nsFloatManager::ImageShapeInfo final : public nsFloatManager::ShapeInfo
|
||||
{
|
||||
public:
|
||||
ImageShapeInfo(uint8_t* aAlphaPixels,
|
||||
int32_t aStride,
|
||||
const LayoutDeviceIntSize& aImageSize,
|
||||
int32_t aAppUnitsPerDevPixel,
|
||||
float aShapeImageThreshold,
|
||||
const nsRect& aContentRect,
|
||||
WritingMode aWM,
|
||||
const nsSize& aContainerSize);
|
||||
|
||||
nscoord LineLeft(const nscoord aBStart,
|
||||
const nscoord aBEnd) const override;
|
||||
nscoord LineRight(const nscoord aBStart,
|
||||
const nscoord aBEnd) const override;
|
||||
nscoord BStart() const override { return mBStart; }
|
||||
nscoord BEnd() const override { return mBEnd; }
|
||||
bool IsEmpty() const override { return mIntervals.IsEmpty(); }
|
||||
|
||||
void Translate(nscoord aLineLeft, nscoord aBlockStart) override;
|
||||
|
||||
private:
|
||||
size_t MinIntervalIndexContainingY(const nscoord aTargetY) const;
|
||||
nscoord LineEdge(const nscoord aBStart,
|
||||
const nscoord aBEnd,
|
||||
bool aLeft) const;
|
||||
|
||||
// An interval is slice of the float area defined by this ImageShapeInfo.
|
||||
// Each interval is a rectangle that is one pixel deep in the block
|
||||
// axis. The values are stored as block edges in the y coordinates,
|
||||
// and inline edges as the x coordinates.
|
||||
|
||||
// The intervals are stored in ascending order on y.
|
||||
nsTArray<nsRect> mIntervals;
|
||||
|
||||
nscoord mBStart = nscoord_MAX;
|
||||
nscoord mBEnd = nscoord_MIN;
|
||||
};
|
||||
|
||||
nsFloatManager::ImageShapeInfo::ImageShapeInfo(
|
||||
uint8_t* aAlphaPixels,
|
||||
int32_t aStride,
|
||||
const LayoutDeviceIntSize& aImageSize,
|
||||
int32_t aAppUnitsPerDevPixel,
|
||||
float aShapeImageThreshold,
|
||||
const nsRect& aContentRect,
|
||||
WritingMode aWM,
|
||||
const nsSize& aContainerSize)
|
||||
{
|
||||
MOZ_ASSERT(aShapeImageThreshold >=0.0 && aShapeImageThreshold <=1.0,
|
||||
"The computed value of shape-image-threshold is wrong!");
|
||||
|
||||
const uint8_t threshold = NSToIntFloor(aShapeImageThreshold * 255);
|
||||
const int32_t w = aImageSize.width;
|
||||
const int32_t h = aImageSize.height;
|
||||
|
||||
// Scan the pixels in a double loop. For horizontal writing modes, we do
|
||||
// this row by row, from top to bottom. For vertical writing modes, we do
|
||||
// column by column, from left to right. We define the two loops
|
||||
// generically, then figure out the rows and cols within the i loop.
|
||||
const int32_t bSize = aWM.IsVertical() ? w : h;
|
||||
const int32_t iSize = aWM.IsVertical() ? h : w;
|
||||
for (int32_t b = 0; b < bSize; ++b) {
|
||||
// iMin and iMax store the start and end of the float area for the row
|
||||
// or column represented by this iteration of the b loop.
|
||||
int32_t iMin = -1;
|
||||
int32_t iMax = -1;
|
||||
|
||||
for (int32_t i = 0; i < iSize; ++i) {
|
||||
const int32_t col = aWM.IsVertical() ? b : i;
|
||||
const int32_t row = aWM.IsVertical() ? i : b;
|
||||
|
||||
// Determine if the alpha pixel at this row and column has a value
|
||||
// greater than the threshold. If it does, update our iMin and iMax values
|
||||
// to track the edges of the float area for this row or column.
|
||||
// https://drafts.csswg.org/css-shapes-1/#valdef-shape-image-threshold-number
|
||||
const uint8_t alpha = aAlphaPixels[col + row * aStride];
|
||||
if (alpha > threshold) {
|
||||
if (iMin == -1) {
|
||||
iMin = i;
|
||||
}
|
||||
MOZ_ASSERT(iMax < i);
|
||||
iMax = i;
|
||||
}
|
||||
}
|
||||
|
||||
// At the end of a row or column; did we find something?
|
||||
if (iMin != -1) {
|
||||
// Store an interval as an nsRect with our inline axis values stored in x
|
||||
// and our block axis values stored in y. The position is dependent on
|
||||
// the writing mode, but the size is the same for all writing modes.
|
||||
|
||||
// Size is the difference in inline axis edges stored as x, and one
|
||||
// block axis pixel stored as y. For the inline axis, we add 1 to iMax
|
||||
// because we want to capture the far edge of the last pixel.
|
||||
nsSize size(((iMax + 1) - iMin) * aAppUnitsPerDevPixel,
|
||||
aAppUnitsPerDevPixel);
|
||||
|
||||
// Since we started our scanning of the image pixels from the top left,
|
||||
// the interval position starts from the origin of the content rect,
|
||||
// converted to logical coordinates.
|
||||
nsPoint origin = ConvertToFloatLogical(aContentRect.TopLeft(), aWM,
|
||||
aContainerSize);
|
||||
|
||||
// Depending on the writing mode, we now move the origin.
|
||||
if (aWM.IsVerticalRL()) {
|
||||
// vertical-rl or sideways-rl.
|
||||
// These writing modes proceed from the top right, and each interval
|
||||
// moves in a positive inline direction and negative block direction.
|
||||
// That means that the intervals will be reversed after all have been
|
||||
// constructed. We add 1 to b to capture the end of the block axis pixel.
|
||||
origin.MoveBy(iMin * aAppUnitsPerDevPixel, (b + 1) * -aAppUnitsPerDevPixel);
|
||||
} else if (aWM.IsVerticalLR() && aWM.IsSideways()) {
|
||||
// sideways-lr.
|
||||
// These writing modes proceed from the bottom left, and each interval
|
||||
// moves in a negative inline direction and a positive block direction.
|
||||
// We add 1 to iMax to capture the end of the inline axis pixel.
|
||||
origin.MoveBy((iMax + 1) * -aAppUnitsPerDevPixel, b * aAppUnitsPerDevPixel);
|
||||
} else {
|
||||
// horizontal-tb or vertical-lr.
|
||||
// These writing modes proceed from the top left and each interval
|
||||
// moves in a positive step in both inline and block directions.
|
||||
origin.MoveBy(iMin * aAppUnitsPerDevPixel, b * aAppUnitsPerDevPixel);
|
||||
}
|
||||
|
||||
mIntervals.AppendElement(nsRect(origin, size));
|
||||
}
|
||||
}
|
||||
|
||||
if (aWM.IsVerticalRL()) {
|
||||
// vertical-rl or sideways-rl.
|
||||
// Because we scan the columns from left to right, we need to reverse
|
||||
// the array so that it's sorted (in ascending order) on the block
|
||||
// direction.
|
||||
mIntervals.Reverse();
|
||||
}
|
||||
|
||||
if (!mIntervals.IsEmpty()) {
|
||||
mBStart = mIntervals[0].Y();
|
||||
mBEnd = mIntervals.LastElement().YMost();
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
nsFloatManager::ImageShapeInfo::MinIntervalIndexContainingY(
|
||||
const nscoord aTargetY) const
|
||||
{
|
||||
// Perform a binary search to find the minimum index of an interval
|
||||
// that contains aTargetY. If no such interval exists, return a value
|
||||
// equal to the number of intervals.
|
||||
size_t startIdx = 0;
|
||||
size_t endIdx = mIntervals.Length();
|
||||
while (startIdx < endIdx) {
|
||||
size_t midIdx = startIdx + (endIdx - startIdx) / 2;
|
||||
if (mIntervals[midIdx].ContainsY(aTargetY)) {
|
||||
return midIdx;
|
||||
}
|
||||
nscoord midY = mIntervals[midIdx].Y();
|
||||
if (midY < aTargetY) {
|
||||
startIdx = midIdx + 1;
|
||||
} else {
|
||||
endIdx = midIdx;
|
||||
}
|
||||
}
|
||||
|
||||
return endIdx;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFloatManager::ImageShapeInfo::LineEdge(const nscoord aBStart,
|
||||
const nscoord aBEnd,
|
||||
bool aLeft) const
|
||||
{
|
||||
MOZ_ASSERT(aBStart <= aBEnd,
|
||||
"The band's block start is greater than its block end?");
|
||||
|
||||
// Find all the intervals whose rects overlap the aBStart to
|
||||
// aBEnd range, and find the most constraining inline edge
|
||||
// depending on the value of aLeft.
|
||||
|
||||
// Since the intervals are stored in block-axis order, we need
|
||||
// to find the first interval that overlaps aBStart and check
|
||||
// succeeding intervals until we get past aBEnd.
|
||||
|
||||
nscoord lineEdge = aLeft ? nscoord_MAX : nscoord_MIN;
|
||||
|
||||
size_t intervalCount = mIntervals.Length();
|
||||
for (size_t i = MinIntervalIndexContainingY(aBStart);
|
||||
i < intervalCount; ++i) {
|
||||
// We can always get the bCoord from the intervals' mLineLeft,
|
||||
// since the y() coordinate is duplicated in both points in the
|
||||
// interval.
|
||||
auto& interval = mIntervals[i];
|
||||
nscoord bCoord = interval.Y();
|
||||
if (bCoord > aBEnd) {
|
||||
break;
|
||||
}
|
||||
// Get the edge from the interval point indicated by aLeft.
|
||||
if (aLeft) {
|
||||
lineEdge = std::min(lineEdge, interval.X());
|
||||
} else {
|
||||
lineEdge = std::max(lineEdge, interval.XMost());
|
||||
}
|
||||
}
|
||||
|
||||
return lineEdge;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFloatManager::ImageShapeInfo::LineLeft(const nscoord aBStart,
|
||||
const nscoord aBEnd) const
|
||||
{
|
||||
return LineEdge(aBStart, aBEnd, true);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFloatManager::ImageShapeInfo::LineRight(const nscoord aBStart,
|
||||
const nscoord aBEnd) const
|
||||
{
|
||||
return LineEdge(aBStart, aBEnd, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsFloatManager::ImageShapeInfo::Translate(nscoord aLineLeft,
|
||||
nscoord aBlockStart)
|
||||
{
|
||||
for (nsRect& interval : mIntervals) {
|
||||
interval.MoveBy(aLineLeft, aBlockStart);
|
||||
}
|
||||
|
||||
mBStart += aBlockStart;
|
||||
mBEnd += aBlockStart;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FloatInfo
|
||||
|
||||
|
@ -1215,16 +966,6 @@ nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame,
|
|||
{
|
||||
MOZ_COUNT_CTOR(nsFloatManager::FloatInfo);
|
||||
|
||||
if (IsEmpty()) {
|
||||
// Per spec, a float area defined by a shape is clipped to the float’s
|
||||
// margin box. Therefore, no need to create a shape info if the float's
|
||||
// margin box is empty, since a float area can only be smaller than the
|
||||
// margin box.
|
||||
|
||||
// https://drafts.csswg.org/css-shapes/#relation-to-box-model-and-float-behavior
|
||||
return;
|
||||
}
|
||||
|
||||
const StyleShapeSource& shapeOutside = mFrame->StyleDisplay()->mShapeOutside;
|
||||
|
||||
switch (shapeOutside.GetType()) {
|
||||
|
@ -1236,20 +977,10 @@ nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame,
|
|||
MOZ_ASSERT_UNREACHABLE("shape-outside doesn't have URL source type!");
|
||||
return;
|
||||
|
||||
case StyleShapeSourceType::Image: {
|
||||
float shapeImageThreshold = mFrame->StyleDisplay()->mShapeImageThreshold;
|
||||
mShapeInfo = ShapeInfo::CreateImageShape(shapeOutside.GetShapeImage(),
|
||||
shapeImageThreshold,
|
||||
mFrame,
|
||||
aWM,
|
||||
aContainerSize);
|
||||
if (!mShapeInfo) {
|
||||
// Image is not ready, or fails to load, etc.
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case StyleShapeSourceType::Image:
|
||||
// Bug 1265343: Implement 'shape-image-threshold'
|
||||
// Bug 1404222: Support shape-outside: <image>
|
||||
return;
|
||||
|
||||
case StyleShapeSourceType::Box: {
|
||||
// Initialize <shape-box>'s reference rect.
|
||||
|
@ -1546,84 +1277,6 @@ nsFloatManager::ShapeInfo::CreatePolygon(
|
|||
return MakeUnique<PolygonShapeInfo>(Move(vertices));
|
||||
}
|
||||
|
||||
/* static */ UniquePtr<nsFloatManager::ShapeInfo>
|
||||
nsFloatManager::ShapeInfo::CreateImageShape(
|
||||
const UniquePtr<nsStyleImage>& aShapeImage,
|
||||
float aShapeImageThreshold,
|
||||
nsIFrame* const aFrame,
|
||||
WritingMode aWM,
|
||||
const nsSize& aContainerSize)
|
||||
{
|
||||
MOZ_ASSERT(aShapeImage ==
|
||||
aFrame->StyleDisplay()->mShapeOutside.GetShapeImage(),
|
||||
"aFrame should be the frame that we got aShapeImage from");
|
||||
|
||||
nsImageRenderer imageRenderer(aFrame, aShapeImage.get(),
|
||||
nsImageRenderer::FLAG_SYNC_DECODE_IMAGES);
|
||||
|
||||
if (!imageRenderer.PrepareImage()) {
|
||||
// The image is not ready yet.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRect contentRect = aFrame->GetContentRect();
|
||||
|
||||
// Create a draw target and draw shape image on it.
|
||||
nsDeviceContext* dc = aFrame->PresContext()->DeviceContext();
|
||||
int32_t appUnitsPerDevPixel = dc->AppUnitsPerDevPixel();
|
||||
LayoutDeviceIntSize contentSizeInDevPixels =
|
||||
LayoutDeviceIntSize::FromAppUnitsRounded(contentRect.Size(),
|
||||
appUnitsPerDevPixel);
|
||||
|
||||
// Use empty CSSSizeOrRatio to force set the preferred size as the frame's
|
||||
// content box size.
|
||||
imageRenderer.SetPreferredSize(CSSSizeOrRatio(), contentRect.Size());
|
||||
|
||||
RefPtr<gfx::DrawTarget> drawTarget =
|
||||
gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(
|
||||
contentSizeInDevPixels.ToUnknownSize(),
|
||||
gfx::SurfaceFormat::A8);
|
||||
if (!drawTarget) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<gfxContext> context = gfxContext::CreateOrNull(drawTarget);
|
||||
MOZ_ASSERT(context); // already checked the target above
|
||||
|
||||
ImgDrawResult result =
|
||||
imageRenderer.DrawShapeImage(aFrame->PresContext(), *context);
|
||||
|
||||
if (result != ImgDrawResult::SUCCESS) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Retrieve the pixel image buffer to create the image shape info.
|
||||
RefPtr<SourceSurface> sourceSurface = drawTarget->Snapshot();
|
||||
RefPtr<DataSourceSurface> dataSourceSurface = sourceSurface->GetDataSurface();
|
||||
DataSourceSurface::ScopedMap map(dataSourceSurface, DataSourceSurface::READ);
|
||||
|
||||
if (!map.IsMapped()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sourceSurface->GetSize() == contentSizeInDevPixels.ToUnknownSize(),
|
||||
"Who changes the size?");
|
||||
|
||||
uint8_t* alphaPixels = map.GetData();
|
||||
int32_t stride = map.GetStride();
|
||||
|
||||
// NOTE: ImageShapeInfo constructor does not keep a persistent copy of
|
||||
// alphaPixels; it's only used during the constructor to compute pixel ranges.
|
||||
return MakeUnique<ImageShapeInfo>(alphaPixels,
|
||||
stride,
|
||||
contentSizeInDevPixels,
|
||||
appUnitsPerDevPixel,
|
||||
aShapeImageThreshold,
|
||||
contentRect,
|
||||
aWM,
|
||||
aContainerSize);
|
||||
}
|
||||
|
||||
/* static */ nscoord
|
||||
nsFloatManager::ShapeInfo::ComputeEllipseLineInterceptDiff(
|
||||
const nscoord aShapeBoxBStart, const nscoord aShapeBoxBEnd,
|
||||
|
|
|
@ -344,7 +344,6 @@ private:
|
|||
class RoundedBoxShapeInfo;
|
||||
class EllipseShapeInfo;
|
||||
class PolygonShapeInfo;
|
||||
class ImageShapeInfo;
|
||||
|
||||
struct FloatInfo {
|
||||
nsIFrame *const mFrame;
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/ServoStyleSet.h"
|
||||
#include "mozilla/css/ImageLoader.h"
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "ActiveLayerTracker.h"
|
||||
|
@ -113,8 +114,6 @@
|
|||
#include "nsITheme.h"
|
||||
#include "nsThemeConstants.h"
|
||||
|
||||
#include "ImageLoader.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::css;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -908,7 +907,7 @@ AddAndRemoveImageAssociations(nsFrame* aFrame,
|
|||
|
||||
CompareLayers(aNewLayers, aOldLayers,
|
||||
[&imageLoader, aFrame](imgRequestProxy* aReq)
|
||||
{ imageLoader->AssociateRequestToFrame(aReq, aFrame, 0); }
|
||||
{ imageLoader->AssociateRequestToFrame(aReq, aFrame); }
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1176,24 +1175,7 @@ nsFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle)
|
|||
imageLoader->DisassociateRequestFromFrame(oldBorderImage, this);
|
||||
}
|
||||
if (newBorderImage) {
|
||||
imageLoader->AssociateRequestToFrame(newBorderImage, this, 0);
|
||||
}
|
||||
}
|
||||
|
||||
imgIRequest* oldShapeImage =
|
||||
aOldComputedStyle
|
||||
? aOldComputedStyle->StyleDisplay()->mShapeOutside.GetShapeImageData()
|
||||
: nullptr;
|
||||
imgIRequest* newShapeImage =
|
||||
StyleDisplay()->mShapeOutside.GetShapeImageData();
|
||||
|
||||
if (oldShapeImage != newShapeImage) {
|
||||
if (oldShapeImage && HasImageRequest()) {
|
||||
imageLoader->DisassociateRequestFromFrame(oldShapeImage, this);
|
||||
}
|
||||
if (newShapeImage) {
|
||||
imageLoader->AssociateRequestToFrame(newShapeImage, this,
|
||||
ImageLoader::REQUEST_REQUIRES_REFLOW);
|
||||
imageLoader->AssociateRequestToFrame(newBorderImage, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5238,8 +5220,7 @@ nsIFrame::ContentOffsets nsFrame::CalcContentOffsetsFromFramePoint(const nsPoint
|
|||
}
|
||||
|
||||
void
|
||||
nsIFrame::AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext,
|
||||
uint32_t aImageLoaderFlags)
|
||||
nsIFrame::AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext)
|
||||
{
|
||||
if (aImage.GetType() != eStyleImageType_Image) {
|
||||
return;
|
||||
|
@ -5249,11 +5230,12 @@ nsIFrame::AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext
|
|||
if (!req) {
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::css::ImageLoader* loader =
|
||||
aPresContext->Document()->StyleImageLoader();
|
||||
|
||||
// If this fails there's not much we can do ...
|
||||
loader->AssociateRequestToFrame(req, this, aImageLoaderFlags);
|
||||
loader->AssociateRequestToFrame(req, this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -1955,8 +1955,7 @@ public:
|
|||
* Ensure that aImage gets notifed when the underlying image request loads
|
||||
* or animates.
|
||||
*/
|
||||
void AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext,
|
||||
uint32_t aImageLoaderFlags);
|
||||
void AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext);
|
||||
|
||||
/**
|
||||
* This structure holds information about a cursor. mContainer represents a
|
||||
|
|
|
@ -2745,7 +2745,7 @@ nsCSSRendering::PaintStyleImageLayerWithSC(const PaintBGParams& aParams,
|
|||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT_WITH_RANGE(i, layers, startLayer,
|
||||
count) {
|
||||
aParams.frame->AssociateImage(layers.mLayers[i].mImage,
|
||||
&aParams.presCtx, 0);
|
||||
&aParams.presCtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3486,7 +3486,7 @@ nsCSSBorderImageRenderer::CreateBorderImageRenderer(nsPresContext* aPresContext,
|
|||
// XXX We shouldn't really... since if anybody is passing in a
|
||||
// different style, they'll potentially have the wrong size for the
|
||||
// border too.
|
||||
aForFrame->AssociateImage(aStyleBorder.mBorderImageSource, aPresContext, 0);
|
||||
aForFrame->AssociateImage(aStyleBorder.mBorderImageSource, aPresContext);
|
||||
|
||||
nsCSSBorderImageRenderer renderer(aForFrame, aBorderArea,
|
||||
aStyleBorder, aSkipSides, imgRenderer);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* utility code for drawing images as CSS borders, backgrounds, and shapes. */
|
||||
/* utility functions for drawing borders and backgrounds */
|
||||
|
||||
#include "nsImageRenderer.h"
|
||||
|
||||
|
@ -13,13 +13,11 @@
|
|||
#include "gfxContext.h"
|
||||
#include "gfxDrawable.h"
|
||||
#include "ImageOps.h"
|
||||
#include "ImageRegion.h"
|
||||
#include "mozilla/layers/StackingContextHelper.h"
|
||||
#include "mozilla/layers/WebRenderLayerManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsCSSRenderingGradients.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsStyleStructInlines.h"
|
||||
#include "nsSVGDisplayableFrame.h"
|
||||
|
@ -948,72 +946,10 @@ nsImageRenderer::DrawBorderImageComponent(nsPresContext* aPresContext,
|
|||
nsRect destTile = RequiresScaling(fillRect, aHFill, aVFill, aUnitSize)
|
||||
? ComputeTile(fillRect, aHFill, aVFill, aUnitSize, repeatSize)
|
||||
: fillRect;
|
||||
|
||||
return Draw(aPresContext, aRenderingContext, aDirtyRect, destTile,
|
||||
fillRect, destTile.TopLeft(), repeatSize, aSrc);
|
||||
}
|
||||
|
||||
ImgDrawResult
|
||||
nsImageRenderer::DrawShapeImage(nsPresContext* aPresContext,
|
||||
gfxContext& aRenderingContext)
|
||||
{
|
||||
if (!IsReady()) {
|
||||
NS_NOTREACHED("Ensure PrepareImage() has returned true before calling me");
|
||||
return ImgDrawResult::NOT_READY;
|
||||
}
|
||||
|
||||
if (mSize.width <= 0 || mSize.height <= 0) {
|
||||
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.
|
||||
nsLayoutUtils::DrawSingleImage(aRenderingContext, aPresContext,
|
||||
mImageContainer, SamplingFilter::POINT,
|
||||
dest, dest, Nothing(),
|
||||
drawFlags,
|
||||
nullptr, nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
case eStyleImageType_Gradient: {
|
||||
nsCSSGradientRenderer renderer =
|
||||
nsCSSGradientRenderer::Create(aPresContext, 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;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
nsImageRenderer::IsRasterImage()
|
||||
{
|
||||
|
|
|
@ -254,14 +254,6 @@ public:
|
|||
const mozilla::Maybe<nsSize>& aSVGViewportSize,
|
||||
const bool aHasIntrinsicRatio);
|
||||
|
||||
/**
|
||||
* Draw the image to aRenderingContext which can be used to define the
|
||||
* float area in the presence of "shape-outside: <image>".
|
||||
*/
|
||||
ImgDrawResult
|
||||
DrawShapeImage(nsPresContext* aPresContext,
|
||||
gfxContext& aRenderingContext);
|
||||
|
||||
bool IsRasterImage();
|
||||
bool IsAnimatedImage();
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "nsLayoutUtils.h"
|
||||
#include "nsError.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsIFrameInlines.h"
|
||||
#include "FrameLayerBuilder.h"
|
||||
#include "SVGObserverUtils.h"
|
||||
#include "imgIContainer.h"
|
||||
|
@ -48,8 +47,7 @@ ImageLoader::DropDocumentReference()
|
|||
|
||||
void
|
||||
ImageLoader::AssociateRequestToFrame(imgIRequest* aRequest,
|
||||
nsIFrame* aFrame,
|
||||
FrameFlags aFlags)
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
nsCOMPtr<imgINotificationObserver> observer;
|
||||
aRequest->GetNotificationObserver(getter_AddRefs(observer));
|
||||
|
@ -78,63 +76,15 @@ ImageLoader::AssociateRequestToFrame(imgIRequest* aRequest,
|
|||
return new RequestSet();
|
||||
});
|
||||
|
||||
// Add frame to the frameSet, and handle any special processing the
|
||||
// frame might require.
|
||||
FrameWithFlags fwf(aFrame);
|
||||
FrameWithFlags* fwfToModify(&fwf);
|
||||
|
||||
// See if the frameSet already has this frame.
|
||||
uint32_t i = frameSet->IndexOfFirstElementGt(fwf, FrameOnlyComparator());
|
||||
if (i > 0 && aFrame == frameSet->ElementAt(i-1).mFrame) {
|
||||
// We're already tracking this frame, so prepare to modify the
|
||||
// existing FrameWithFlags object.
|
||||
fwfToModify = &frameSet->ElementAt(i-1);
|
||||
// Add these to the sets, but only if they're not already there.
|
||||
uint32_t i = frameSet->IndexOfFirstElementGt(aFrame);
|
||||
if (i == 0 || aFrame != frameSet->ElementAt(i-1)) {
|
||||
frameSet->InsertElementAt(i, aFrame);
|
||||
}
|
||||
|
||||
// Check if the frame requires special processing.
|
||||
if (aFlags & REQUEST_REQUIRES_REFLOW) {
|
||||
fwfToModify->mFlags |= REQUEST_REQUIRES_REFLOW;
|
||||
|
||||
// If we weren't already blocking onload, do that now.
|
||||
if ((fwfToModify->mFlags & REQUEST_HAS_BLOCKED_ONLOAD) == 0) {
|
||||
fwfToModify->mFlags |= REQUEST_HAS_BLOCKED_ONLOAD;
|
||||
|
||||
// Block document onload until we either remove the frame in
|
||||
// RemoveRequestToFrameMapping or complete a reflow.
|
||||
mDocument->BlockOnload();
|
||||
|
||||
// We need to stay blocked until we get a reflow. If the first frame
|
||||
// is not yet decoded, we'll trigger that reflow from onFrameComplete.
|
||||
// But if the first frame is already decoded, we need to trigger that
|
||||
// reflow now, because we'll never get a call to onFrameComplete.
|
||||
uint32_t status = 0;
|
||||
if(NS_SUCCEEDED(aRequest->GetImageStatus(&status)) &&
|
||||
status & imgIRequest::STATUS_FRAME_COMPLETE) {
|
||||
RequestReflowOnFrame(aFrame, aRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do some sanity checking to ensure that we only add to one mapping
|
||||
// iff we also add to the other mapping.
|
||||
DebugOnly<bool> didAddToFrameSet(false);
|
||||
DebugOnly<bool> didAddToRequestSet(false);
|
||||
|
||||
// If we weren't already tracking this frame, add it to the frameSet.
|
||||
if (i == 0 || aFrame != frameSet->ElementAt(i-1).mFrame) {
|
||||
frameSet->InsertElementAt(i, fwf);
|
||||
didAddToFrameSet = true;
|
||||
}
|
||||
|
||||
// Add request to the request set if it wasn't already there.
|
||||
i = requestSet->IndexOfFirstElementGt(aRequest);
|
||||
if (i == 0 || aRequest != requestSet->ElementAt(i-1)) {
|
||||
requestSet->InsertElementAt(i, aRequest);
|
||||
didAddToRequestSet = true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(didAddToFrameSet == didAddToRequestSet,
|
||||
"We should only add to one map iff we also add to the other map.");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -189,21 +139,7 @@ ImageLoader::RemoveRequestToFrameMapping(imgIRequest* aRequest,
|
|||
if (auto entry = mRequestToFrameMap.Lookup(aRequest)) {
|
||||
FrameSet* frameSet = entry.Data();
|
||||
MOZ_ASSERT(frameSet, "This should never be null");
|
||||
|
||||
// Before we remove aFrame from the frameSet, unblock onload if needed.
|
||||
uint32_t i = frameSet->IndexOfFirstElementGt(FrameWithFlags(aFrame),
|
||||
FrameOnlyComparator());
|
||||
|
||||
if (i > 0 && aFrame == frameSet->ElementAt(i-1).mFrame) {
|
||||
FrameWithFlags& fwf = frameSet->ElementAt(i-1);
|
||||
if (fwf.mFlags & REQUEST_HAS_BLOCKED_ONLOAD) {
|
||||
mDocument->UnblockOnload(false);
|
||||
// We're about to remove fwf from the frameSet, so we don't bother
|
||||
// updating the flag.
|
||||
}
|
||||
frameSet->RemoveElementAt(i-1);
|
||||
}
|
||||
|
||||
frameSet->RemoveElementSorted(aFrame);
|
||||
if (frameSet->IsEmpty()) {
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
if (presContext) {
|
||||
|
@ -426,8 +362,7 @@ ImageLoader::DoRedraw(FrameSet* aFrameSet, bool aForcePaint)
|
|||
NS_ASSERTION(aFrameSet, "Must have a frame set");
|
||||
NS_ASSERTION(mDocument, "Should have returned earlier!");
|
||||
|
||||
for (FrameWithFlags& fwf : *aFrameSet) {
|
||||
nsIFrame* frame = fwf.mFrame;
|
||||
for (nsIFrame* frame : *aFrameSet) {
|
||||
if (frame->StyleVisibility()->IsVisible()) {
|
||||
if (frame->IsFrameOfType(nsIFrame::eTablePart)) {
|
||||
// Tables don't necessarily build border/background display items
|
||||
|
@ -452,59 +387,6 @@ ImageLoader::DoRedraw(FrameSet* aFrameSet, bool aForcePaint)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImageLoader::UnblockOnloadIfNeeded(nsIFrame* aFrame, imgIRequest* aRequest)
|
||||
{
|
||||
MOZ_ASSERT(aFrame);
|
||||
MOZ_ASSERT(aRequest);
|
||||
|
||||
FrameSet* frameSet = mRequestToFrameMap.Get(aRequest);
|
||||
if (!frameSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = frameSet->BinaryIndexOf(FrameWithFlags(aFrame),
|
||||
FrameOnlyComparator());
|
||||
if (i != FrameSet::NoIndex) {
|
||||
FrameWithFlags& fwf = frameSet->ElementAt(i);
|
||||
if (fwf.mFlags & REQUEST_HAS_BLOCKED_ONLOAD) {
|
||||
mDocument->UnblockOnload(false);
|
||||
fwf.mFlags &= ~REQUEST_HAS_BLOCKED_ONLOAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImageLoader::RequestReflowIfNeeded(FrameSet* aFrameSet, imgIRequest* aRequest)
|
||||
{
|
||||
MOZ_ASSERT(aFrameSet);
|
||||
|
||||
for (FrameWithFlags& fwf : *aFrameSet) {
|
||||
nsIFrame* frame = fwf.mFrame;
|
||||
if (fwf.mFlags & REQUEST_REQUIRES_REFLOW) {
|
||||
// Tell the container of the float to reflow because the
|
||||
// shape-outside: <image> has finished decoding its first frame.
|
||||
RequestReflowOnFrame(frame, aRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImageLoader::RequestReflowOnFrame(nsIFrame* aFrame, imgIRequest* aRequest)
|
||||
{
|
||||
// Actually request the reflow.
|
||||
nsIFrame* floatContainer = aFrame->GetInFlowParent();
|
||||
floatContainer->PresShell()->FrameNeedsReflow(
|
||||
floatContainer, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
|
||||
|
||||
// We'll respond to the reflow events by unblocking onload, regardless
|
||||
// of whether the reflow was completed or cancelled. The callback will
|
||||
// also delete itself when it is called.
|
||||
ImageReflowCallback* unblocker = new ImageReflowCallback(this, aFrame,
|
||||
aRequest);
|
||||
floatContainer->PresShell()->PostReflowCallback(unblocker);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(ImageLoader)
|
||||
NS_IMPL_RELEASE(ImageLoader)
|
||||
|
||||
|
@ -572,8 +454,7 @@ ImageLoader::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
for (FrameWithFlags& fwf : *frameSet) {
|
||||
nsIFrame* frame = fwf.mFrame;
|
||||
for (nsIFrame* frame : *frameSet) {
|
||||
if (frame->StyleVisibility()->IsVisible()) {
|
||||
frame->MarkNeedsDisplayItemRebuild();
|
||||
}
|
||||
|
@ -618,9 +499,6 @@ ImageLoader::OnFrameComplete(imgIRequest* aRequest)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// We may need reflow (for example if the image is from shape-outside).
|
||||
RequestReflowIfNeeded(frameSet, aRequest);
|
||||
|
||||
// Since we just finished decoding a frame, we always want to paint, in case
|
||||
// we're now able to paint an image that we couldn't paint before (and hence
|
||||
// that we don't have retained data for).
|
||||
|
@ -663,36 +541,5 @@ ImageLoader::FlushUseCounters()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ImageLoader::ImageReflowCallback::ReflowFinished()
|
||||
{
|
||||
// Check that the frame is still valid. If it isn't, then onload was
|
||||
// unblocked when the frame was removed from the FrameSet in
|
||||
// RemoveRequestToFrameMapping.
|
||||
if (mFrame.IsAlive()) {
|
||||
mLoader->UnblockOnloadIfNeeded(mFrame, mRequest);
|
||||
}
|
||||
|
||||
// Get rid of this callback object.
|
||||
delete this;
|
||||
|
||||
// We don't need to trigger layout.
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ImageLoader::ImageReflowCallback::ReflowCallbackCanceled()
|
||||
{
|
||||
// Check that the frame is still valid. If it isn't, then onload was
|
||||
// unblocked when the frame was removed from the FrameSet in
|
||||
// RemoveRequestToFrameMapping.
|
||||
if (mFrame.IsAlive()) {
|
||||
mLoader->UnblockOnloadIfNeeded(mFrame, mRequest);
|
||||
}
|
||||
|
||||
// Get rid of this callback object.
|
||||
delete this;
|
||||
}
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -10,11 +10,9 @@
|
|||
#ifndef mozilla_css_ImageLoader_h___
|
||||
#define mozilla_css_ImageLoader_h___
|
||||
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "CORSMode.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIReflowCallback.h"
|
||||
#include "nsTArray.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "imgINotificationObserver.h"
|
||||
|
@ -35,14 +33,6 @@ struct ImageValue;
|
|||
class ImageLoader final : public imgINotificationObserver
|
||||
{
|
||||
public:
|
||||
// We also associate flags alongside frames in the request-to-frames hashmap.
|
||||
// These are used for special handling of events for requests.
|
||||
typedef uint32_t FrameFlags;
|
||||
enum {
|
||||
REQUEST_REQUIRES_REFLOW = 1u << 0,
|
||||
REQUEST_HAS_BLOCKED_ONLOAD = 1u << 1
|
||||
};
|
||||
|
||||
typedef mozilla::css::ImageValue Image;
|
||||
|
||||
explicit ImageLoader(nsIDocument* aDocument)
|
||||
|
@ -61,8 +51,7 @@ public:
|
|||
void DeregisterCSSImage(Image* aImage);
|
||||
|
||||
void AssociateRequestToFrame(imgIRequest* aRequest,
|
||||
nsIFrame* aFrame,
|
||||
FrameFlags aFlags);
|
||||
nsIFrame* aFrame);
|
||||
|
||||
void DisassociateRequestFromFrame(imgIRequest* aRequest,
|
||||
nsIFrame* aFrame);
|
||||
|
@ -84,26 +73,6 @@ public:
|
|||
void FlushUseCounters();
|
||||
|
||||
private:
|
||||
// This callback is used to unblock document onload after a reflow
|
||||
// triggered from an image load.
|
||||
struct ImageReflowCallback final : public nsIReflowCallback
|
||||
{
|
||||
RefPtr<ImageLoader> mLoader;
|
||||
WeakFrame mFrame;
|
||||
nsCOMPtr<imgIRequest> const mRequest;
|
||||
|
||||
ImageReflowCallback(ImageLoader* aLoader,
|
||||
nsIFrame* aFrame,
|
||||
imgIRequest* aRequest)
|
||||
: mLoader(aLoader)
|
||||
, mFrame(aFrame)
|
||||
, mRequest(aRequest)
|
||||
{}
|
||||
|
||||
bool ReflowFinished() override;
|
||||
void ReflowCallbackCanceled() override;
|
||||
};
|
||||
|
||||
~ImageLoader() {}
|
||||
|
||||
// We need to be able to look up the frames associated with a request (for
|
||||
|
@ -111,31 +80,7 @@ private:
|
|||
// the frame goes away). Thus we maintain hashtables going both ways. These
|
||||
// should always be in sync.
|
||||
|
||||
struct FrameWithFlags {
|
||||
explicit FrameWithFlags(nsIFrame* aFrame)
|
||||
: mFrame(aFrame),
|
||||
mFlags(0)
|
||||
{
|
||||
MOZ_ASSERT(mFrame);
|
||||
}
|
||||
nsIFrame* const mFrame;
|
||||
FrameFlags mFlags;
|
||||
};
|
||||
|
||||
// A helper class to compare FrameWithFlags by comparing mFrame and
|
||||
// ignoring mFlags.
|
||||
class FrameOnlyComparator {
|
||||
public:
|
||||
bool Equals(const FrameWithFlags& aElem1,
|
||||
const FrameWithFlags& aElem2) const
|
||||
{ return aElem1.mFrame == aElem2.mFrame; }
|
||||
|
||||
bool LessThan(const FrameWithFlags& aElem1,
|
||||
const FrameWithFlags& aElem2) const
|
||||
{ return aElem1.mFrame < aElem2.mFrame; }
|
||||
};
|
||||
|
||||
typedef nsTArray<FrameWithFlags> FrameSet;
|
||||
typedef nsTArray<nsIFrame*> FrameSet;
|
||||
typedef nsTArray<nsCOMPtr<imgIRequest> > RequestSet;
|
||||
typedef nsTHashtable<nsPtrHashKey<Image> > ImageHashSet;
|
||||
typedef nsClassHashtable<nsISupportsHashKey,
|
||||
|
@ -149,9 +94,6 @@ private:
|
|||
nsPresContext* GetPresContext();
|
||||
|
||||
void DoRedraw(FrameSet* aFrameSet, bool aForcePaint);
|
||||
void UnblockOnloadIfNeeded(nsIFrame* aFrame, imgIRequest* aRequest);
|
||||
void RequestReflowIfNeeded(FrameSet* aFrameSet, imgIRequest* aRequest);
|
||||
void RequestReflowOnFrame(nsIFrame* aFrame, imgIRequest* aRequest);
|
||||
|
||||
nsresult OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage);
|
||||
nsresult OnFrameComplete(imgIRequest* aRequest);
|
||||
|
|
|
@ -1069,18 +1069,6 @@ StyleShapeSource::SetShapeImage(UniquePtr<nsStyleImage> aShapeImage)
|
|||
mType = StyleShapeSourceType::Image;
|
||||
}
|
||||
|
||||
imgIRequest*
|
||||
StyleShapeSource::GetShapeImageData() const
|
||||
{
|
||||
if (mType != StyleShapeSourceType::Image) {
|
||||
return nullptr;
|
||||
}
|
||||
if (mShapeImage->GetType() != eStyleImageType_Image) {
|
||||
return nullptr;
|
||||
}
|
||||
return mShapeImage->GetImageData();
|
||||
}
|
||||
|
||||
void
|
||||
StyleShapeSource::SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
|
||||
StyleGeometryBox aReferenceBox)
|
||||
|
|
|
@ -2145,11 +2145,6 @@ struct StyleShapeSource final
|
|||
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<nsStyleImage> aShapeImage);
|
||||
|
||||
const UniquePtr<StyleBasicShape>& GetBasicShape() const
|
||||
|
|
|
@ -33,6 +33,7 @@ function sendResults() {
|
|||
window.parent.postMessage({
|
||||
"result": (divAllowSib.getBoundingClientRect().left == divAllow.getBoundingClientRect().left),
|
||||
"message": "Test 1: Sibling is at same left offset as div (shape-outside was allowed).",
|
||||
"todo": true,
|
||||
},
|
||||
DOMAIN);
|
||||
|
||||
|
|
|
@ -423,7 +423,7 @@ nsSVGMaskProperty::ResolveImage(uint32_t aIndex)
|
|||
mozilla::css::ImageLoader* imageLoader =
|
||||
mFrame->PresContext()->Document()->StyleImageLoader();
|
||||
if (imgRequestProxy* req = image.GetImageData()) {
|
||||
imageLoader->AssociateRequestToFrame(req, mFrame, 0);
|
||||
imageLoader->AssociateRequestToFrame(req, mFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125727,54 +125727,6 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-005.html": [
|
||||
[
|
||||
"/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-005.html",
|
||||
[
|
||||
[
|
||||
"/css/css-shapes/shape-outside/shape-image/gradients/reference/shape-outside-linear-gradient-001-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-006.html": [
|
||||
[
|
||||
"/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-006.html",
|
||||
[
|
||||
[
|
||||
"/css/css-shapes/shape-outside/shape-image/gradients/reference/shape-outside-linear-gradient-001-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-007.html": [
|
||||
[
|
||||
"/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-007.html",
|
||||
[
|
||||
[
|
||||
"/css/css-shapes/shape-outside/shape-image/gradients/reference/shape-outside-linear-gradient-001-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-008.html": [
|
||||
[
|
||||
"/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-008.html",
|
||||
[
|
||||
[
|
||||
"/css/css-shapes/shape-outside/shape-image/gradients/reference/shape-outside-linear-gradient-001-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/shape-image-000.html": [
|
||||
[
|
||||
"/css/css-shapes/shape-outside/shape-image/shape-image-000.html",
|
||||
|
@ -506910,22 +506862,6 @@
|
|||
"1e5377c120916557dc1525b38c9cf7eb86ae0151",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-005.html": [
|
||||
"dfbf4ad61f18ad05e243e58a2458b5b776ecf3fb",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-006.html": [
|
||||
"da35426f9ffc53101a053a61512c6928d140adff",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-007.html": [
|
||||
"03752707f61fbf16290b9733c280b79e00440b96",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-008.html": [
|
||||
"2ce6445aed0987c0ab7b83f614e9ceb8186fff7b",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-001.html": [
|
||||
"b13df2df3be12ac74a7933794d91558c416b412c",
|
||||
"testharness"
|
||||
|
@ -506939,7 +506875,7 @@
|
|||
"testharness"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-004.html": [
|
||||
"fc47f277737dce4f7c6b08d0181355a810107c7b",
|
||||
"67c3b8ea983da6b7d9b6b7e252b6415ebc7d1f9d",
|
||||
"testharness"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/reference/shape-image-000-ref.html": [
|
||||
|
@ -507011,11 +506947,11 @@
|
|||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/shape-image-001.html": [
|
||||
"f69cd2483ed81b496fb5d1c0024b6a16df7375b1",
|
||||
"d97482f9149c68fff971e383ffb72f1371e898ef",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/shape-image-002.html": [
|
||||
"299635765004bd1cf9cff8a0888678a2331d7b19",
|
||||
"1f3ace2827629f37439108e43f6528d8d728e5a2",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/shape-image-003.html": [
|
||||
|
@ -507027,7 +506963,7 @@
|
|||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/shape-image-005.html": [
|
||||
"38883b770a73cc4eac3170a356b272edb6a5c483",
|
||||
"274932a778268e3fda90b289e7f5ca22ee0f9adc",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-shapes/shape-outside/shape-image/shape-image-006.html": [
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[shape-outside-linear-gradient-001.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-outside-linear-gradient-002.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-outside-linear-gradient-003.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-outside-linear-gradient-004.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,4 @@
|
|||
[shape-outside-radial-gradient-001.html]
|
||||
[CSS Test: Left float with radial gradient]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-000.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-001.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-002.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-003.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-004.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-005.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-012.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-013.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-014.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-015.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-016.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-017.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[shape-image-025.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,4 @@
|
|||
[shape-outside-010.html]
|
||||
[CSS Test: Shape from image - url(), alpha channel, opacity 0]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[shape-outside-011.html]
|
||||
[CSS Test: Shape from image - url(), alpha channel, opacity > 0]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[shape-outside-012.html]
|
||||
[CSS Test: Shape from image - shape-image-threshold - 0.9]
|
||||
expected: FAIL
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Test float with linear gradient under writing-mode: vertical-rl</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="mailto:aethanyc@gmail.com"/>
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-shapes-1/#shapes-from-image"/>
|
||||
<link rel="help" href="http://www.w3.org/TR/css-shapes-1/#shape-outside-property"/>
|
||||
<link rel="match" href="reference/shape-outside-linear-gradient-001-ref.html"/>
|
||||
<meta name="flags" content="ahem"/>
|
||||
<meta name="assert" content="This test verifies that shape-outside respects a simple linear gradient under vertical-rl."/>
|
||||
<style type="text/css">
|
||||
.container {
|
||||
writing-mode: vertical-rl;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background-color: red;
|
||||
font-family: Ahem;
|
||||
font-size: 50px;
|
||||
line-height: 1;
|
||||
}
|
||||
#test {
|
||||
color: green;
|
||||
}
|
||||
#float-left {
|
||||
/* Note: In .container's writing-mode, "float: left" actually floats
|
||||
us towards the top. */
|
||||
float: left;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background: linear-gradient(to bottom, green 50%, transparent 50%);
|
||||
shape-outside: linear-gradient(to bottom, green 50%, transparent 50%);
|
||||
}
|
||||
#float-right {
|
||||
/* Note: In .container's writing-mode, "float: right" actually floats
|
||||
us towards the bottom. */
|
||||
float: right;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background: linear-gradient(to top, green 50%, transparent 50%);
|
||||
shape-outside: linear-gradient(to top, green 50%, transparent 50%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
The test passes if you see a green square. There should be no red.
|
||||
</p>
|
||||
<div id="test" class="container">
|
||||
<div id="float-left"></div>
|
||||
x x x x
|
||||
</div>
|
||||
<div id="test" class="container" style="direction: rtl;">
|
||||
<div id="float-right"></div>
|
||||
x x x x
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,58 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Test float with linear gradient under writing-mode: vertical-lr</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="mailto:aethanyc@gmail.com"/>
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-shapes-1/#shapes-from-image"/>
|
||||
<link rel="help" href="http://www.w3.org/TR/css-shapes-1/#shape-outside-property"/>
|
||||
<link rel="match" href="reference/shape-outside-linear-gradient-001-ref.html"/>
|
||||
<meta name="flags" content="ahem"/>
|
||||
<meta name="assert" content="This test verifies that shape-outside respects a simple linear gradient under vertical-lr."/>
|
||||
<style type="text/css">
|
||||
.container {
|
||||
writing-mode: vertical-lr;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background-color: red;
|
||||
font-family: Ahem;
|
||||
font-size: 50px;
|
||||
line-height: 1;
|
||||
}
|
||||
#test {
|
||||
color: green;
|
||||
}
|
||||
#float-left {
|
||||
/* Note: In .container's writing-mode, "float: left" actually floats
|
||||
us towards the top. */
|
||||
float: left;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background: linear-gradient(to bottom, green 50%, transparent 50%);
|
||||
shape-outside: linear-gradient(to bottom, green 50%, transparent 50%);
|
||||
}
|
||||
#float-right {
|
||||
/* Note: In .container's writing-mode, "float: right" actually floats
|
||||
us towards the bottom. */
|
||||
float: right;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background: linear-gradient(to top, green 50%, transparent 50%);
|
||||
shape-outside: linear-gradient(to top, green 50%, transparent 50%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
The test passes if you see a green square. There should be no red.
|
||||
</p>
|
||||
<div id="test" class="container">
|
||||
<div id="float-left"></div>
|
||||
x x x x
|
||||
</div>
|
||||
<div id="test" class="container" style="direction: rtl;">
|
||||
<div id="float-right"></div>
|
||||
x x x x
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,58 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Test float with linear gradient under writing-mode: sideways-rl</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="mailto:aethanyc@gmail.com"/>
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-shapes-1/#shapes-from-image"/>
|
||||
<link rel="help" href="http://www.w3.org/TR/css-shapes-1/#shape-outside-property"/>
|
||||
<link rel="match" href="reference/shape-outside-linear-gradient-001-ref.html"/>
|
||||
<meta name="flags" content="ahem"/>
|
||||
<meta name="assert" content="This test verifies that shape-outside respects a simple linear gradient under sideways-rl."/>
|
||||
<style type="text/css">
|
||||
.container {
|
||||
writing-mode: sideways-rl;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background-color: red;
|
||||
font-family: Ahem;
|
||||
font-size: 50px;
|
||||
line-height: 1;
|
||||
}
|
||||
#test {
|
||||
color: green;
|
||||
}
|
||||
#float-left {
|
||||
/* Note: In .container's writing-mode, "float: left" actually floats
|
||||
us towards the top. */
|
||||
float: left;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background: linear-gradient(to bottom, green 50%, transparent 50%);
|
||||
shape-outside: linear-gradient(to bottom, green 50%, transparent 50%);
|
||||
}
|
||||
#float-right {
|
||||
/* Note: In .container's writing-mode, "float: right" actually floats
|
||||
us towards the bottom. */
|
||||
float: right;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background: linear-gradient(to top, green 50%, transparent 50%);
|
||||
shape-outside: linear-gradient(to top, green 50%, transparent 50%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
The test passes if you see a green square. There should be no red.
|
||||
</p>
|
||||
<div id="test" class="container">
|
||||
<div id="float-left"></div>
|
||||
x x x x
|
||||
</div>
|
||||
<div id="test" class="container" style="direction: rtl;">
|
||||
<div id="float-right"></div>
|
||||
x x x x
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,58 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Test float with linear gradient under writing-mode: sideways-lr</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="mailto:aethanyc@gmail.com"/>
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-shapes-1/#shapes-from-image"/>
|
||||
<link rel="help" href="http://www.w3.org/TR/css-shapes-1/#shape-outside-property"/>
|
||||
<link rel="match" href="reference/shape-outside-linear-gradient-001-ref.html"/>
|
||||
<meta name="flags" content="ahem"/>
|
||||
<meta name="assert" content="This test verifies that shape-outside respects a simple linear gradient under sideways-lr."/>
|
||||
<style type="text/css">
|
||||
.container {
|
||||
writing-mode: sideways-lr;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background-color: red;
|
||||
font-family: Ahem;
|
||||
font-size: 50px;
|
||||
line-height: 1;
|
||||
}
|
||||
#test {
|
||||
color: green;
|
||||
}
|
||||
#float-left {
|
||||
/* Note: In .container's writing-mode, "float: left" actually floats
|
||||
us towards the bottom. */
|
||||
float: left;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background: linear-gradient(to top, green 50%, transparent 50%);
|
||||
shape-outside: linear-gradient(to top, green 50%, transparent 50%);
|
||||
}
|
||||
#float-right {
|
||||
/* Note: In .container's writing-mode, "float: right" actually floats
|
||||
us towards the top. */
|
||||
float: right;
|
||||
inline-size: 100px;
|
||||
block-size: 200px;
|
||||
background: linear-gradient(to bottom, green 50%, transparent 50%);
|
||||
shape-outside: linear-gradient(to bottom, green 50%, transparent 50%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
The test passes if you see a green square. There should be no red.
|
||||
</p>
|
||||
<div id="test" class="container">
|
||||
<div id="float-left"></div>
|
||||
x x x x
|
||||
</div>
|
||||
<div id="test" class="container" style="direction: rtl;">
|
||||
<div id="float-right"></div>
|
||||
x x x x
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -22,7 +22,7 @@
|
|||
}
|
||||
#image {
|
||||
float: left;
|
||||
width: 100px;
|
||||
width: 150px;
|
||||
height: 100px;
|
||||
shape-outside: url("support/left-half-rectangle-70.png");
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
}
|
||||
#image {
|
||||
float: left;
|
||||
shape-outside: url('data:image/svg+xml;utf8,<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="%23006400" d=" M 0.00 0.00 L 50.00 0.00 C 50.00 33.33 50.00 66.67 50.00 100.00 L 0.00 100.00 L 0.00 0.00 Z" /></svg>');
|
||||
shape-outside: url('data:image/svg+xml;utf8,<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#006400" d=" M 0.00 0.00 L 50.00 0.00 C 50.00 33.33 50.00 66.67 50.00 100.00 L 0.00 100.00 L 0.00 0.00 Z" /></svg>');
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -31,7 +31,7 @@
|
|||
The test passes if you see a solid green square. There should be no red.
|
||||
</p>
|
||||
<div id="test" class="container">
|
||||
<img id="image" src='data:image/svg+xml;utf8,<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="%23006400" d=" M 0.00 0.00 L 50.00 0.00 C 50.00 33.33 50.00 66.67 50.00 100.00 L 0.00 100.00 L 0.00 0.00 Z" /></svg>'/>
|
||||
<img id="image" src='data:image/svg+xml;utf8,<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#006400" d=" M 0.00 0.00 L 50.00 0.00 C 50.00 33.33 50.00 66.67 50.00 100.00 L 0.00 100.00 L 0.00 0.00 Z" /></svg>'/>
|
||||
X
|
||||
X
|
||||
</div>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
}
|
||||
#image {
|
||||
float: left;
|
||||
shape-outside: url('data:image/svg+xml;utf8,<svg width="100px" height="100px" style="background-color: rgba(0,0,0,0.7)" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="%23006400" d=" M 0.00 0.00 L 50.00 0.00 C 50.00 33.33 50.00 66.67 50.00 100.00 L 0.00 100.00 L 0.00 0.00 Z" /></svg>');
|
||||
shape-outside: url('data:image/svg+xml;utf8,<svg width="100px" height="100px" style="background-color: rgba(0,0,0,0.7)" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#006400" d=" M 0.00 0.00 L 50.00 0.00 C 50.00 33.33 50.00 66.67 50.00 100.00 L 0.00 100.00 L 0.00 0.00 Z" /></svg>');
|
||||
shape-image-threshold: 0.8;
|
||||
}
|
||||
</style>
|
||||
|
@ -32,7 +32,7 @@
|
|||
The test passes if you see a solid green square. There should be no red.
|
||||
</p>
|
||||
<div id="test" class="container">
|
||||
<img id="image" src='data:image/svg+xml;utf8,<svg width="100px" height="100px" style="background-color: rgba(0,0,0,0.7)" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="%23006400" d=" M 0.00 0.00 L 50.00 0.00 C 50.00 33.33 50.00 66.67 50.00 100.00 L 0.00 100.00 L 0.00 0.00 Z" /></svg>'/>
|
||||
<img id="image" src='data:image/svg+xml;utf8,<svg width="100px" height="100px" style="background-color: rgba(0,0,0,0.7)" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#006400" d=" M 0.00 0.00 L 50.00 0.00 C 50.00 33.33 50.00 66.67 50.00 100.00 L 0.00 100.00 L 0.00 0.00 Z" /></svg>'/>
|
||||
X
|
||||
X
|
||||
</div>
|
||||
|
|
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 867 B После Ширина: | Высота: | Размер: 1.8 KiB |
Загрузка…
Ссылка в новой задаче