Merge mozilla-inbound to mozilla-central. a=merge
@@ -59,6 +59,25 @@ AutoInitializeImageLib::AutoInitializeImageLib() {
|
|||||||
SpinPendingEvents();
|
SpinPendingEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageBenchmarkBase::SetUp() {
|
||||||
|
nsCOMPtr<nsIInputStream> inputStream = LoadFile(mTestCase.mPath);
|
||||||
|
ASSERT_TRUE(inputStream != nullptr);
|
||||||
|
|
||||||
|
// Figure out how much data we have.
|
||||||
|
uint64_t length;
|
||||||
|
nsresult rv = inputStream->Available(&length);
|
||||||
|
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||||
|
|
||||||
|
// Write the data into a SourceBuffer.
|
||||||
|
mSourceBuffer = new SourceBuffer();
|
||||||
|
mSourceBuffer->ExpectLength(length);
|
||||||
|
rv = mSourceBuffer->AppendFromInputStream(inputStream, length);
|
||||||
|
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||||
|
mSourceBuffer->Complete(NS_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageBenchmarkBase::TearDown() {}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// General Helpers
|
// General Helpers
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -732,5 +751,59 @@ ImageTestCase GreenMultipleSizesICOTestCase() {
|
|||||||
IntSize(256, 256));
|
IntSize(256, 256));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfGrayJPGTestCase() {
|
||||||
|
return ImageTestCase("perf_gray.jpg", "image/jpeg", IntSize(1000, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfCmykJPGTestCase() {
|
||||||
|
return ImageTestCase("perf_cmyk.jpg", "image/jpeg", IntSize(1000, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfYCbCrJPGTestCase() {
|
||||||
|
return ImageTestCase("perf_ycbcr.jpg", "image/jpeg", IntSize(1000, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfRgbPNGTestCase() {
|
||||||
|
return ImageTestCase("perf_srgb.png", "image/png", IntSize(1000, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfRgbAlphaPNGTestCase() {
|
||||||
|
return ImageTestCase("perf_srgb_alpha.png", "image/png", IntSize(1000, 1000),
|
||||||
|
TEST_CASE_IS_TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfGrayPNGTestCase() {
|
||||||
|
return ImageTestCase("perf_gray.png", "image/png", IntSize(1000, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfGrayAlphaPNGTestCase() {
|
||||||
|
return ImageTestCase("perf_gray_alpha.png", "image/png", IntSize(1000, 1000),
|
||||||
|
TEST_CASE_IS_TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfRgbLosslessWebPTestCase() {
|
||||||
|
return ImageTestCase("perf_srgb_lossless.webp", "image/webp",
|
||||||
|
IntSize(1000, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfRgbAlphaLosslessWebPTestCase() {
|
||||||
|
return ImageTestCase("perf_srgb_alpha_lossless.webp", "image/webp",
|
||||||
|
IntSize(1000, 1000), TEST_CASE_IS_TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfRgbLossyWebPTestCase() {
|
||||||
|
return ImageTestCase("perf_srgb_lossy.webp", "image/webp",
|
||||||
|
IntSize(1000, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfRgbAlphaLossyWebPTestCase() {
|
||||||
|
return ImageTestCase("perf_srgb_alpha_lossy.webp", "image/webp",
|
||||||
|
IntSize(1000, 1000), TEST_CASE_IS_TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTestCase PerfRgbGIFTestCase() {
|
||||||
|
return ImageTestCase("perf_srgb.gif", "image/gif", IntSize(1000, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace image
|
} // namespace image
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "gfxColor.h"
|
#include "gfxColor.h"
|
||||||
#include "imgITools.h"
|
#include "imgITools.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
#include "SurfaceFlags.h"
|
||||||
#include "SurfacePipe.h"
|
#include "SurfacePipe.h"
|
||||||
#include "SurfacePipeFactory.h"
|
#include "SurfacePipeFactory.h"
|
||||||
|
|
||||||
@@ -86,6 +87,7 @@ struct ImageTestCase {
|
|||||||
mSize(aSize),
|
mSize(aSize),
|
||||||
mOutputSize(aSize),
|
mOutputSize(aSize),
|
||||||
mFlags(aFlags),
|
mFlags(aFlags),
|
||||||
|
mSurfaceFlags(DefaultSurfaceFlags()),
|
||||||
mColor(BGRAColor::Green()) {}
|
mColor(BGRAColor::Green()) {}
|
||||||
|
|
||||||
ImageTestCase(const char* aPath, const char* aMimeType, gfx::IntSize aSize,
|
ImageTestCase(const char* aPath, const char* aMimeType, gfx::IntSize aSize,
|
||||||
@@ -96,6 +98,7 @@ struct ImageTestCase {
|
|||||||
mSize(aSize),
|
mSize(aSize),
|
||||||
mOutputSize(aOutputSize),
|
mOutputSize(aOutputSize),
|
||||||
mFlags(aFlags),
|
mFlags(aFlags),
|
||||||
|
mSurfaceFlags(DefaultSurfaceFlags()),
|
||||||
mColor(BGRAColor::Green()) {}
|
mColor(BGRAColor::Green()) {}
|
||||||
|
|
||||||
const char* mPath;
|
const char* mPath;
|
||||||
@@ -103,6 +106,7 @@ struct ImageTestCase {
|
|||||||
gfx::IntSize mSize;
|
gfx::IntSize mSize;
|
||||||
gfx::IntSize mOutputSize;
|
gfx::IntSize mOutputSize;
|
||||||
uint32_t mFlags;
|
uint32_t mFlags;
|
||||||
|
SurfaceFlags mSurfaceFlags;
|
||||||
BGRAColor mColor;
|
BGRAColor mColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -122,6 +126,22 @@ class AutoInitializeImageLib {
|
|||||||
AutoInitializeImageLib();
|
AutoInitializeImageLib();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test fixture class used for benchmark tests. It preloads the image data
|
||||||
|
* from disk to avoid including that in the timing.
|
||||||
|
*/
|
||||||
|
class ImageBenchmarkBase : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
ImageBenchmarkBase(const ImageTestCase& aTestCase) : mTestCase(aTestCase) {}
|
||||||
|
|
||||||
|
void SetUp() override;
|
||||||
|
void TearDown() override;
|
||||||
|
|
||||||
|
AutoInitializeImageLib mInit;
|
||||||
|
ImageTestCase mTestCase;
|
||||||
|
RefPtr<SourceBuffer> mSourceBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
/// Spins on the main thread to process any pending events.
|
/// Spins on the main thread to process any pending events.
|
||||||
void SpinPendingEvents();
|
void SpinPendingEvents();
|
||||||
|
|
||||||
@@ -465,6 +485,19 @@ ImageTestCase LargeICOWithBMPTestCase();
|
|||||||
ImageTestCase LargeICOWithPNGTestCase();
|
ImageTestCase LargeICOWithPNGTestCase();
|
||||||
ImageTestCase GreenMultipleSizesICOTestCase();
|
ImageTestCase GreenMultipleSizesICOTestCase();
|
||||||
|
|
||||||
|
ImageTestCase PerfGrayJPGTestCase();
|
||||||
|
ImageTestCase PerfCmykJPGTestCase();
|
||||||
|
ImageTestCase PerfYCbCrJPGTestCase();
|
||||||
|
ImageTestCase PerfRgbPNGTestCase();
|
||||||
|
ImageTestCase PerfRgbAlphaPNGTestCase();
|
||||||
|
ImageTestCase PerfGrayPNGTestCase();
|
||||||
|
ImageTestCase PerfGrayAlphaPNGTestCase();
|
||||||
|
ImageTestCase PerfRgbLosslessWebPTestCase();
|
||||||
|
ImageTestCase PerfRgbAlphaLosslessWebPTestCase();
|
||||||
|
ImageTestCase PerfRgbLossyWebPTestCase();
|
||||||
|
ImageTestCase PerfRgbAlphaLossyWebPTestCase();
|
||||||
|
ImageTestCase PerfRgbGIFTestCase();
|
||||||
|
|
||||||
} // namespace image
|
} // namespace image
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|||||||
158
image/test/gtest/TestDecodersPerf.cpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "gtest/MozGTestBench.h"
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Decoder.h"
|
||||||
|
#include "DecoderFactory.h"
|
||||||
|
#include "IDecodingTask.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "ProgressTracker.h"
|
||||||
|
#include "SourceBuffer.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::gfx;
|
||||||
|
using namespace mozilla::image;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static void CheckDecoderState(const ImageTestCase& aTestCase, Decoder* aDecoder,
|
||||||
|
const IntSize& aOutputSize) {
|
||||||
|
// Decoder should match what we asked for in the MIME type.
|
||||||
|
EXPECT_NE(aDecoder->GetType(), DecoderType::UNKNOWN);
|
||||||
|
EXPECT_EQ(aDecoder->GetType(),
|
||||||
|
DecoderFactory::GetDecoderType(aTestCase.mMimeType));
|
||||||
|
|
||||||
|
EXPECT_TRUE(aDecoder->GetDecodeDone());
|
||||||
|
EXPECT_FALSE(aDecoder->HasError());
|
||||||
|
|
||||||
|
// Verify that the decoder made the expected progress.
|
||||||
|
Progress progress = aDecoder->TakeProgress();
|
||||||
|
EXPECT_FALSE(bool(progress & FLAG_HAS_ERROR));
|
||||||
|
EXPECT_FALSE(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR));
|
||||||
|
|
||||||
|
EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE));
|
||||||
|
EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE));
|
||||||
|
EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE));
|
||||||
|
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT),
|
||||||
|
bool(progress & FLAG_HAS_TRANSPARENCY));
|
||||||
|
EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
|
||||||
|
bool(progress & FLAG_IS_ANIMATED));
|
||||||
|
|
||||||
|
// The decoder should get the correct size.
|
||||||
|
IntSize size = aDecoder->Size();
|
||||||
|
EXPECT_EQ(aTestCase.mSize.width, size.width);
|
||||||
|
EXPECT_EQ(aTestCase.mSize.height, size.height);
|
||||||
|
|
||||||
|
// Get the current frame, which is always the first frame of the image
|
||||||
|
// because CreateAnonymousDecoder() forces a first-frame-only decode.
|
||||||
|
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||||
|
RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
|
||||||
|
|
||||||
|
// Verify that the resulting surfaces matches our expectations.
|
||||||
|
EXPECT_TRUE(surface->IsDataSourceSurface());
|
||||||
|
EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
|
||||||
|
surface->GetFormat() == SurfaceFormat::B8G8R8A8);
|
||||||
|
EXPECT_EQ(aOutputSize, surface->GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
static void WithSingleChunkDecode(const ImageTestCase& aTestCase,
|
||||||
|
SourceBuffer* aSourceBuffer,
|
||||||
|
const Maybe<IntSize>& aOutputSize,
|
||||||
|
Func aResultChecker) {
|
||||||
|
auto sourceBuffer = WrapNotNull(RefPtr<SourceBuffer>(aSourceBuffer));
|
||||||
|
|
||||||
|
// Create a decoder.
|
||||||
|
DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
|
||||||
|
RefPtr<Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
|
||||||
|
decoderType, sourceBuffer, aOutputSize, DecoderFlags::FIRST_FRAME_ONLY,
|
||||||
|
aTestCase.mSurfaceFlags);
|
||||||
|
ASSERT_TRUE(decoder != nullptr);
|
||||||
|
RefPtr<IDecodingTask> task =
|
||||||
|
new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false);
|
||||||
|
|
||||||
|
// Run the full decoder synchronously.
|
||||||
|
task->Run();
|
||||||
|
|
||||||
|
// Call the lambda to verify the expected results.
|
||||||
|
aResultChecker(decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CheckDecode(const ImageTestCase& aTestCase,
|
||||||
|
SourceBuffer* aSourceBuffer) {
|
||||||
|
WithSingleChunkDecode(
|
||||||
|
aTestCase, aSourceBuffer, Nothing(), [&](Decoder* aDecoder) {
|
||||||
|
CheckDecoderState(aTestCase, aDecoder, aTestCase.mSize);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CheckDownscaleDuringDecode(const ImageTestCase& aTestCase,
|
||||||
|
SourceBuffer* aSourceBuffer) {
|
||||||
|
IntSize outputSize(20, 20);
|
||||||
|
WithSingleChunkDecode(aTestCase, aSourceBuffer, Some(outputSize),
|
||||||
|
[&](Decoder* aDecoder) {
|
||||||
|
CheckDecoderState(aTestCase, aDecoder, outputSize);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IMAGE_GTEST_BENCH_FIXTURE(test_fixture, test_case) \
|
||||||
|
class test_fixture : public ImageBenchmarkBase { \
|
||||||
|
protected: \
|
||||||
|
test_fixture() : ImageBenchmarkBase(test_case()) {} \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IMAGE_GTEST_NATIVE_BENCH_F(test_fixture) \
|
||||||
|
MOZ_GTEST_BENCH_F(test_fixture, Native, \
|
||||||
|
[this] { CheckDecode(mTestCase, mSourceBuffer); });
|
||||||
|
|
||||||
|
#define IMAGE_GTEST_DOWNSCALE_BENCH_F(test_fixture) \
|
||||||
|
MOZ_GTEST_BENCH_F(test_fixture, Downscale, [this] { \
|
||||||
|
CheckDownscaleDuringDecode(mTestCase, mSourceBuffer); \
|
||||||
|
});
|
||||||
|
|
||||||
|
#define IMAGE_GTEST_NO_COLOR_MANAGEMENT_BENCH_F(test_fixture) \
|
||||||
|
MOZ_GTEST_BENCH_F(test_fixture, NoColorManagement, [this] { \
|
||||||
|
ImageTestCase testCase = mTestCase; \
|
||||||
|
testCase.mSurfaceFlags |= SurfaceFlags::NO_COLORSPACE_CONVERSION; \
|
||||||
|
CheckDecode(testCase, mSourceBuffer); \
|
||||||
|
});
|
||||||
|
|
||||||
|
#define IMAGE_GTEST_NO_PREMULTIPLY_BENCH_F(test_fixture) \
|
||||||
|
MOZ_GTEST_BENCH_F(test_fixture, NoPremultiplyAlpha, [this] { \
|
||||||
|
ImageTestCase testCase = mTestCase; \
|
||||||
|
testCase.mSurfaceFlags |= SurfaceFlags::NO_PREMULTIPLY_ALPHA; \
|
||||||
|
CheckDecode(testCase, mSourceBuffer); \
|
||||||
|
});
|
||||||
|
|
||||||
|
#define IMAGE_GTEST_BENCH_F(type, test) \
|
||||||
|
IMAGE_GTEST_BENCH_FIXTURE(ImageDecodersPerf_##type##_##test, \
|
||||||
|
Perf##test##type##TestCase) \
|
||||||
|
IMAGE_GTEST_NATIVE_BENCH_F(ImageDecodersPerf_##type##_##test) \
|
||||||
|
IMAGE_GTEST_DOWNSCALE_BENCH_F(ImageDecodersPerf_##type##_##test) \
|
||||||
|
IMAGE_GTEST_NO_COLOR_MANAGEMENT_BENCH_F(ImageDecodersPerf_##type##_##test)
|
||||||
|
|
||||||
|
#define IMAGE_GTEST_BENCH_ALPHA_F(type, test) \
|
||||||
|
IMAGE_GTEST_BENCH_F(type, test) \
|
||||||
|
IMAGE_GTEST_NO_PREMULTIPLY_BENCH_F(ImageDecodersPerf_##type##_##test)
|
||||||
|
|
||||||
|
IMAGE_GTEST_BENCH_F(JPG, YCbCr)
|
||||||
|
IMAGE_GTEST_BENCH_F(JPG, Cmyk)
|
||||||
|
IMAGE_GTEST_BENCH_F(JPG, Gray)
|
||||||
|
|
||||||
|
IMAGE_GTEST_BENCH_F(PNG, Rgb)
|
||||||
|
IMAGE_GTEST_BENCH_F(PNG, Gray)
|
||||||
|
IMAGE_GTEST_BENCH_ALPHA_F(PNG, RgbAlpha)
|
||||||
|
IMAGE_GTEST_BENCH_ALPHA_F(PNG, GrayAlpha)
|
||||||
|
|
||||||
|
IMAGE_GTEST_BENCH_F(WebP, RgbLossless)
|
||||||
|
IMAGE_GTEST_BENCH_F(WebP, RgbLossy)
|
||||||
|
IMAGE_GTEST_BENCH_ALPHA_F(WebP, RgbAlphaLossless)
|
||||||
|
IMAGE_GTEST_BENCH_ALPHA_F(WebP, RgbAlphaLossy)
|
||||||
|
|
||||||
|
IMAGE_GTEST_BENCH_F(GIF, Rgb)
|
||||||
|
|
||||||
|
} // namespace
|
||||||
@@ -25,6 +25,7 @@ UNIFIED_SOURCES = [
|
|||||||
if not(CONFIG['OS_TARGET'] == 'WINNT' and CONFIG['CPU_ARCH'] == 'aarch64'):
|
if not(CONFIG['OS_TARGET'] == 'WINNT' and CONFIG['CPU_ARCH'] == 'aarch64'):
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'TestDecoders.cpp',
|
'TestDecoders.cpp',
|
||||||
|
'TestDecodersPerf.cpp',
|
||||||
'TestDecodeToSurface.cpp',
|
'TestDecodeToSurface.cpp',
|
||||||
'TestMetadata.cpp',
|
'TestMetadata.cpp',
|
||||||
'TestSourceBuffer.cpp',
|
'TestSourceBuffer.cpp',
|
||||||
@@ -77,6 +78,18 @@ TEST_HARNESS_FILES.gtest += [
|
|||||||
'invalid-truncated-metadata.bmp',
|
'invalid-truncated-metadata.bmp',
|
||||||
'large.webp',
|
'large.webp',
|
||||||
'no-frame-delay.gif',
|
'no-frame-delay.gif',
|
||||||
|
'perf_cmyk.jpg',
|
||||||
|
'perf_gray.jpg',
|
||||||
|
'perf_gray.png',
|
||||||
|
'perf_gray_alpha.png',
|
||||||
|
'perf_srgb.gif',
|
||||||
|
'perf_srgb.png',
|
||||||
|
'perf_srgb_alpha.png',
|
||||||
|
'perf_srgb_alpha_lossless.webp',
|
||||||
|
'perf_srgb_alpha_lossy.webp',
|
||||||
|
'perf_srgb_lossless.webp',
|
||||||
|
'perf_srgb_lossy.webp',
|
||||||
|
'perf_ycbcr.jpg',
|
||||||
'rle4.bmp',
|
'rle4.bmp',
|
||||||
'rle8.bmp',
|
'rle8.bmp',
|
||||||
'transparent-ico-with-and-mask.ico',
|
'transparent-ico-with-and-mask.ico',
|
||||||
|
|||||||
BIN
image/test/gtest/perf_cmyk.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
image/test/gtest/perf_gray.jpg
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
image/test/gtest/perf_gray.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
image/test/gtest/perf_gray_alpha.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
image/test/gtest/perf_srgb.gif
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
image/test/gtest/perf_srgb.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
image/test/gtest/perf_srgb_alpha.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
image/test/gtest/perf_srgb_alpha_lossless.webp
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
image/test/gtest/perf_srgb_alpha_lossy.webp
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
image/test/gtest/perf_srgb_lossless.webp
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
image/test/gtest/perf_srgb_lossy.webp
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
image/test/gtest/perf_ycbcr.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
@@ -536,6 +536,9 @@ already_AddRefed<nsIContentViewer> NS_NewContentViewer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nsDocumentViewer::PrepareToStartLoad() {
|
void nsDocumentViewer::PrepareToStartLoad() {
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!GetIsPrintPreview(),
|
||||||
|
"Print preview tab should never navigate");
|
||||||
|
|
||||||
mStopped = false;
|
mStopped = false;
|
||||||
mLoaded = false;
|
mLoaded = false;
|
||||||
mAttachedToParent = false;
|
mAttachedToParent = false;
|
||||||
@@ -550,9 +553,6 @@ void nsDocumentViewer::PrepareToStartLoad() {
|
|||||||
if (mPrintJob) {
|
if (mPrintJob) {
|
||||||
mPrintJob->Destroy();
|
mPrintJob->Destroy();
|
||||||
mPrintJob = nullptr;
|
mPrintJob = nullptr;
|
||||||
# ifdef NS_PRINT_PREVIEW
|
|
||||||
SetIsPrintPreview(false);
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NS_PRINTING
|
#endif // NS_PRINTING
|
||||||
|
|||||||
@@ -16,10 +16,6 @@
|
|||||||
#include "gfxTypes.h"
|
#include "gfxTypes.h"
|
||||||
#include "gfxUtils.h"
|
#include "gfxUtils.h"
|
||||||
#include "LookAndFeel.h"
|
#include "LookAndFeel.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
|
||||||
#include "mozilla/gfx/PatternHelpers.h"
|
|
||||||
#include "mozilla/Likely.h"
|
|
||||||
#include "mozilla/PresShell.h"
|
|
||||||
#include "nsAlgorithm.h"
|
#include "nsAlgorithm.h"
|
||||||
#include "nsBidiPresUtils.h"
|
#include "nsBidiPresUtils.h"
|
||||||
#include "nsBlockFrame.h"
|
#include "nsBlockFrame.h"
|
||||||
@@ -30,14 +26,10 @@
|
|||||||
#include "SVGObserverUtils.h"
|
#include "SVGObserverUtils.h"
|
||||||
#include "nsSVGOuterSVGFrame.h"
|
#include "nsSVGOuterSVGFrame.h"
|
||||||
#include "nsSVGPaintServerFrame.h"
|
#include "nsSVGPaintServerFrame.h"
|
||||||
#include "mozilla/dom/Selection.h"
|
|
||||||
#include "mozilla/dom/SVGRect.h"
|
|
||||||
#include "mozilla/dom/SVGTextContentElementBinding.h"
|
|
||||||
#include "nsSVGIntegrationUtils.h"
|
#include "nsSVGIntegrationUtils.h"
|
||||||
#include "nsSVGUtils.h"
|
#include "nsSVGUtils.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsTextFrame.h"
|
#include "nsTextFrame.h"
|
||||||
#include "nsTextNode.h"
|
|
||||||
#include "SVGAnimatedNumberList.h"
|
#include "SVGAnimatedNumberList.h"
|
||||||
#include "SVGContentUtils.h"
|
#include "SVGContentUtils.h"
|
||||||
#include "SVGContextPaint.h"
|
#include "SVGContextPaint.h"
|
||||||
@@ -48,6 +40,14 @@
|
|||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsFrameSelection.h"
|
#include "nsFrameSelection.h"
|
||||||
#include "nsStyleStructInlines.h"
|
#include "nsStyleStructInlines.h"
|
||||||
|
#include "mozilla/Likely.h"
|
||||||
|
#include "mozilla/PresShell.h"
|
||||||
|
#include "mozilla/dom/Selection.h"
|
||||||
|
#include "mozilla/dom/SVGRect.h"
|
||||||
|
#include "mozilla/dom/SVGTextContentElementBinding.h"
|
||||||
|
#include "mozilla/dom/Text.h"
|
||||||
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/gfx/PatternHelpers.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -234,16 +234,16 @@ static bool IsNonEmptyTextFrame(nsIFrame* aFrame) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes an nsIFrame and if it is a text frame that has some text content,
|
* Takes an nsIFrame and if it is a text frame that has some text content,
|
||||||
* returns it as an nsTextFrame and its corresponding nsTextNode.
|
* returns it as an nsTextFrame and its corresponding Text.
|
||||||
*
|
*
|
||||||
* @param aFrame The frame to look at.
|
* @param aFrame The frame to look at.
|
||||||
* @param aTextFrame aFrame as an nsTextFrame (output).
|
* @param aTextFrame aFrame as an nsTextFrame (output).
|
||||||
* @param aTextNode The nsTextNode content of aFrame (output).
|
* @param aTextNode The Text content of aFrame (output).
|
||||||
* @return true if aFrame is a non-empty text frame, false otherwise.
|
* @return true if aFrame is a non-empty text frame, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool GetNonEmptyTextFrameAndNode(nsIFrame* aFrame,
|
static bool GetNonEmptyTextFrameAndNode(nsIFrame* aFrame,
|
||||||
nsTextFrame*& aTextFrame,
|
nsTextFrame*& aTextFrame,
|
||||||
nsTextNode*& aTextNode) {
|
Text*& aTextNode) {
|
||||||
nsTextFrame* text = do_QueryFrame(aFrame);
|
nsTextFrame* text = do_QueryFrame(aFrame);
|
||||||
bool isNonEmptyTextFrame = text && text->GetContentLength() != 0;
|
bool isNonEmptyTextFrame = text && text->GetContentLength() != 0;
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ static bool GetNonEmptyTextFrameAndNode(nsIFrame* aFrame,
|
|||||||
NS_ASSERTION(content && content->IsText(),
|
NS_ASSERTION(content && content->IsText(),
|
||||||
"unexpected content type for nsTextFrame");
|
"unexpected content type for nsTextFrame");
|
||||||
|
|
||||||
nsTextNode* node = static_cast<nsTextNode*>(content);
|
Text* node = content->AsText();
|
||||||
MOZ_ASSERT(node->TextLength() != 0,
|
MOZ_ASSERT(node->TextLength() != 0,
|
||||||
"frame's GetContentLength() should be 0 if the text node "
|
"frame's GetContentLength() should be 0 if the text node "
|
||||||
"has no content");
|
"has no content");
|
||||||
@@ -724,7 +724,7 @@ struct TextRenderedRun {
|
|||||||
nscoord mBaseline;
|
nscoord mBaseline;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The offset and length in mFrame's content nsTextNode that corresponds to
|
* The offset and length in mFrame's content Text that corresponds to
|
||||||
* this text rendered run. These are original char indexes.
|
* this text rendered run. These are original char indexes.
|
||||||
*/
|
*/
|
||||||
uint32_t mTextFrameContentOffset;
|
uint32_t mTextFrameContentOffset;
|
||||||
@@ -1092,7 +1092,7 @@ int32_t TextRenderedRun::GetCharNumAtPosition(nsPresContext* aContext,
|
|||||||
enum SubtreePosition { eBeforeSubtree, eWithinSubtree, eAfterSubtree };
|
enum SubtreePosition { eBeforeSubtree, eWithinSubtree, eAfterSubtree };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An iterator class for nsTextNodes that are descendants of a given node, the
|
* An iterator class for Text that are descendants of a given node, the
|
||||||
* root. Nodes are iterated in document order. An optional subtree can be
|
* root. Nodes are iterated in document order. An optional subtree can be
|
||||||
* specified, in which case the iterator will track whether the current state of
|
* specified, in which case the iterator will track whether the current state of
|
||||||
* the traversal over the tree is within that subtree or is past that subtree.
|
* the traversal over the tree is within that subtree or is past that subtree.
|
||||||
@@ -1115,15 +1115,15 @@ class TextNodeIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current nsTextNode, or null if the iterator has finished.
|
* Returns the current Text, or null if the iterator has finished.
|
||||||
*/
|
*/
|
||||||
nsTextNode* Current() const { return static_cast<nsTextNode*>(mCurrent); }
|
Text* Current() const { return mCurrent ? mCurrent->AsText() : nullptr; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Advances to the next nsTextNode and returns it, or null if the end of
|
* Advances to the next Text and returns it, or null if the end of
|
||||||
* iteration has been reached.
|
* iteration has been reached.
|
||||||
*/
|
*/
|
||||||
nsTextNode* Next();
|
Text* Next();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the iterator is currently within the subtree rooted
|
* Returns whether the iterator is currently within the subtree rooted
|
||||||
@@ -1140,7 +1140,7 @@ class TextNodeIterator {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* The root under which all nsTextNodes will be iterated over.
|
* The root under which all Text will be iterated over.
|
||||||
*/
|
*/
|
||||||
nsIContent* mRoot;
|
nsIContent* mRoot;
|
||||||
|
|
||||||
@@ -1160,9 +1160,9 @@ class TextNodeIterator {
|
|||||||
SubtreePosition mSubtreePosition;
|
SubtreePosition mSubtreePosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
nsTextNode* TextNodeIterator::Next() {
|
Text* TextNodeIterator::Next() {
|
||||||
// Starting from mCurrent, we do a non-recursive traversal to the next
|
// Starting from mCurrent, we do a non-recursive traversal to the next
|
||||||
// nsTextNode beneath mRoot, updating mSubtreePosition appropriately if we
|
// Text beneath mRoot, updating mSubtreePosition appropriately if we
|
||||||
// encounter mSubtree.
|
// encounter mSubtree.
|
||||||
if (mCurrent) {
|
if (mCurrent) {
|
||||||
do {
|
do {
|
||||||
@@ -1199,7 +1199,7 @@ nsTextNode* TextNodeIterator::Next() {
|
|||||||
} while (mCurrent && !mCurrent->IsText());
|
} while (mCurrent && !mCurrent->IsText());
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<nsTextNode*>(mCurrent);
|
return mCurrent ? mCurrent->AsText() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -1248,7 +1248,7 @@ static uint32_t GetUndisplayedCharactersBeforeFrame(nsTextFrame* aFrame) {
|
|||||||
* Traverses the nsTextFrames for an SVGTextFrame and records a
|
* Traverses the nsTextFrames for an SVGTextFrame and records a
|
||||||
* TextNodeCorrespondenceProperty on each for the number of undisplayed DOM
|
* TextNodeCorrespondenceProperty on each for the number of undisplayed DOM
|
||||||
* characters between each frame. This is done by iterating simultaneously
|
* characters between each frame. This is done by iterating simultaneously
|
||||||
* over the nsTextNodes and nsTextFrames and noting when nsTextNodes (or
|
* over the Text and nsTextFrames and noting when Text (or
|
||||||
* parts of them) are skipped when finding the next nsTextFrame.
|
* parts of them) are skipped when finding the next nsTextFrame.
|
||||||
*/
|
*/
|
||||||
class TextNodeCorrespondenceRecorder {
|
class TextNodeCorrespondenceRecorder {
|
||||||
@@ -1268,23 +1268,23 @@ class TextNodeCorrespondenceRecorder {
|
|||||||
void TraverseAndRecord(nsIFrame* aFrame);
|
void TraverseAndRecord(nsIFrame* aFrame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the next non-empty nsTextNode.
|
* Returns the next non-empty Text.
|
||||||
*/
|
*/
|
||||||
nsTextNode* NextNode();
|
Text* NextNode();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The iterator over the nsTextNodes that we use as we simultaneously
|
* The iterator over the Text that we use as we simultaneously
|
||||||
* iterate over the nsTextFrames.
|
* iterate over the nsTextFrames.
|
||||||
*/
|
*/
|
||||||
TextNodeIterator mNodeIterator;
|
TextNodeIterator mNodeIterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The previous nsTextNode we iterated over.
|
* The previous Text we iterated over.
|
||||||
*/
|
*/
|
||||||
nsTextNode* mPreviousNode;
|
Text* mPreviousNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The index into the current nsTextNode's character content.
|
* The index into the current Text's character content.
|
||||||
*/
|
*/
|
||||||
uint32_t mNodeCharIndex;
|
uint32_t mNodeCharIndex;
|
||||||
};
|
};
|
||||||
@@ -1302,7 +1302,7 @@ void TextNodeCorrespondenceRecorder::RecordCorrespondence(SVGTextFrame* aRoot) {
|
|||||||
|
|
||||||
void TextNodeCorrespondenceRecorder::Record(SVGTextFrame* aRoot) {
|
void TextNodeCorrespondenceRecorder::Record(SVGTextFrame* aRoot) {
|
||||||
if (!mNodeIterator.Current()) {
|
if (!mNodeIterator.Current()) {
|
||||||
// If there are no nsTextNodes then there is nothing to do.
|
// If there are no Text nodes then there is nothing to do.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1314,15 +1314,15 @@ void TextNodeCorrespondenceRecorder::Record(SVGTextFrame* aRoot) {
|
|||||||
uint32_t undisplayed = 0;
|
uint32_t undisplayed = 0;
|
||||||
if (mNodeIterator.Current()) {
|
if (mNodeIterator.Current()) {
|
||||||
if (mPreviousNode && mPreviousNode->TextLength() != mNodeCharIndex) {
|
if (mPreviousNode && mPreviousNode->TextLength() != mNodeCharIndex) {
|
||||||
// The last nsTextFrame ended part way through an nsTextNode. The
|
// The last nsTextFrame ended part way through a Text node. The
|
||||||
// remaining characters count as undisplayed.
|
// remaining characters count as undisplayed.
|
||||||
NS_ASSERTION(mNodeCharIndex < mPreviousNode->TextLength(),
|
NS_ASSERTION(mNodeCharIndex < mPreviousNode->TextLength(),
|
||||||
"incorrect tracking of undisplayed characters in "
|
"incorrect tracking of undisplayed characters in "
|
||||||
"text nodes");
|
"text nodes");
|
||||||
undisplayed += mPreviousNode->TextLength() - mNodeCharIndex;
|
undisplayed += mPreviousNode->TextLength() - mNodeCharIndex;
|
||||||
}
|
}
|
||||||
// All the remaining nsTextNodes that we iterate must also be undisplayed.
|
// All the remaining Text that we iterate must also be undisplayed.
|
||||||
for (nsTextNode* textNode = mNodeIterator.Current(); textNode;
|
for (Text* textNode = mNodeIterator.Current(); textNode;
|
||||||
textNode = NextNode()) {
|
textNode = NextNode()) {
|
||||||
undisplayed += textNode->TextLength();
|
undisplayed += textNode->TextLength();
|
||||||
}
|
}
|
||||||
@@ -1333,9 +1333,9 @@ void TextNodeCorrespondenceRecorder::Record(SVGTextFrame* aRoot) {
|
|||||||
aRoot->mTrailingUndisplayedCharacters = undisplayed;
|
aRoot->mTrailingUndisplayedCharacters = undisplayed;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTextNode* TextNodeCorrespondenceRecorder::NextNode() {
|
Text* TextNodeCorrespondenceRecorder::NextNode() {
|
||||||
mPreviousNode = mNodeIterator.Current();
|
mPreviousNode = mNodeIterator.Current();
|
||||||
nsTextNode* next;
|
Text* next;
|
||||||
do {
|
do {
|
||||||
next = mNodeIterator.Next();
|
next = mNodeIterator.Next();
|
||||||
} while (next && next->TextLength() == 0);
|
} while (next && next->TextLength() == 0);
|
||||||
@@ -1353,7 +1353,7 @@ void TextNodeCorrespondenceRecorder::TraverseAndRecord(nsIFrame* aFrame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsTextFrame* frame; // The current text frame.
|
nsTextFrame* frame; // The current text frame.
|
||||||
nsTextNode* node; // The text node for the current text frame.
|
Text* node; // The text node for the current text frame.
|
||||||
if (!GetNonEmptyTextFrameAndNode(aFrame, frame, node)) {
|
if (!GetNonEmptyTextFrameAndNode(aFrame, frame, node)) {
|
||||||
// If this isn't an nsTextFrame, or is empty, nothing to do.
|
// If this isn't an nsTextFrame, or is empty, nothing to do.
|
||||||
return;
|
return;
|
||||||
@@ -1373,7 +1373,7 @@ void TextNodeCorrespondenceRecorder::TraverseAndRecord(nsIFrame* aFrame) {
|
|||||||
"incorrect tracking of correspondence between "
|
"incorrect tracking of correspondence between "
|
||||||
"text frames and text nodes");
|
"text frames and text nodes");
|
||||||
} else {
|
} else {
|
||||||
// Each whole nsTextNode we find before we get to the text node for the
|
// Each whole Text we find before we get to the text node for the
|
||||||
// first text frame must be undisplayed.
|
// first text frame must be undisplayed.
|
||||||
while (mNodeIterator.Current() != node) {
|
while (mNodeIterator.Current() != node) {
|
||||||
undisplayed += mNodeIterator.Current()->TextLength();
|
undisplayed += mNodeIterator.Current()->TextLength();
|
||||||
@@ -1401,11 +1401,11 @@ void TextNodeCorrespondenceRecorder::TraverseAndRecord(nsIFrame* aFrame) {
|
|||||||
NS_ASSERTION(mNodeCharIndex < mPreviousNode->TextLength(),
|
NS_ASSERTION(mNodeCharIndex < mPreviousNode->TextLength(),
|
||||||
"incorrect tracking of undisplayed characters in "
|
"incorrect tracking of undisplayed characters in "
|
||||||
"text nodes");
|
"text nodes");
|
||||||
// Any trailing characters at the end of the previous nsTextNode are
|
// Any trailing characters at the end of the previous Text are
|
||||||
// undisplayed.
|
// undisplayed.
|
||||||
undisplayed = mPreviousNode->TextLength() - mNodeCharIndex;
|
undisplayed = mPreviousNode->TextLength() - mNodeCharIndex;
|
||||||
}
|
}
|
||||||
// Each whole nsTextNode we find before we get to the text node for
|
// Each whole Text we find before we get to the text node for
|
||||||
// the current text frame must be undisplayed.
|
// the current text frame must be undisplayed.
|
||||||
while (mNodeIterator.Current() && mNodeIterator.Current() != node) {
|
while (mNodeIterator.Current() && mNodeIterator.Current() != node) {
|
||||||
undisplayed += mNodeIterator.Current()->TextLength();
|
undisplayed += mNodeIterator.Current()->TextLength();
|
||||||
@@ -1421,7 +1421,7 @@ void TextNodeCorrespondenceRecorder::TraverseAndRecord(nsIFrame* aFrame) {
|
|||||||
frame->SetProperty(TextNodeCorrespondenceProperty(),
|
frame->SetProperty(TextNodeCorrespondenceProperty(),
|
||||||
new TextNodeCorrespondence(undisplayed));
|
new TextNodeCorrespondence(undisplayed));
|
||||||
|
|
||||||
// Remember how far into the current nsTextNode we are.
|
// Remember how far into the current Text we are.
|
||||||
mNodeCharIndex = frame->GetContentEnd();
|
mNodeCharIndex = frame->GetContentEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1859,7 +1859,7 @@ TextRenderedRun TextRenderedRunIterator::Next() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert the global run start/end indexes into an offset/length into the
|
// Convert the global run start/end indexes into an offset/length into the
|
||||||
// current frame's nsTextNode.
|
// current frame's Text.
|
||||||
offset =
|
offset =
|
||||||
frame->GetContentOffset() + runStart - mFrameStartTextElementCharIndex;
|
frame->GetContentOffset() + runStart - mFrameStartTextElementCharIndex;
|
||||||
length = runEnd - runStart;
|
length = runEnd - runStart;
|
||||||
@@ -2112,7 +2112,7 @@ class CharIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the original character offsets within the nsTextNode for the
|
* Gets the original character offsets within the Text for the
|
||||||
* cluster/ligature group the current character is a part of.
|
* cluster/ligature group the current character is a part of.
|
||||||
*
|
*
|
||||||
* @param aOriginalOffset The offset of the start of the cluster/ligature
|
* @param aOriginalOffset The offset of the start of the cluster/ligature
|
||||||
@@ -3582,14 +3582,14 @@ SVGBBox SVGTextFrame::GetBBoxContribution(const Matrix& aToBBoxUserspace,
|
|||||||
// SVGTextFrame SVG DOM methods
|
// SVGTextFrame SVG DOM methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the specified node has any non-empty nsTextNodes
|
* Returns whether the specified node has any non-empty Text
|
||||||
* beneath it.
|
* beneath it.
|
||||||
*/
|
*/
|
||||||
static bool HasTextContent(nsIContent* aContent) {
|
static bool HasTextContent(nsIContent* aContent) {
|
||||||
NS_ASSERTION(aContent, "expected non-null aContent");
|
NS_ASSERTION(aContent, "expected non-null aContent");
|
||||||
|
|
||||||
TextNodeIterator it(aContent);
|
TextNodeIterator it(aContent);
|
||||||
for (nsTextNode* text = it.Current(); text; text = it.Next()) {
|
for (Text* text = it.Current(); text; text = it.Next()) {
|
||||||
if (text->TextLength() != 0) {
|
if (text->TextLength() != 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3605,7 +3605,7 @@ static uint32_t GetTextContentLength(nsIContent* aContent) {
|
|||||||
|
|
||||||
uint32_t length = 0;
|
uint32_t length = 0;
|
||||||
TextNodeIterator it(aContent);
|
TextNodeIterator it(aContent);
|
||||||
for (nsTextNode* text = it.Current(); text; text = it.Next()) {
|
for (Text* text = it.Current(); text; text = it.Next()) {
|
||||||
length += text->TextLength();
|
length += text->TextLength();
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
@@ -3795,7 +3795,7 @@ nsresult SVGTextFrame::GetSubStringLength(nsIContent* aContent,
|
|||||||
frameStartTextElementCharIndex += frit.UndisplayedCharacters();
|
frameStartTextElementCharIndex += frit.UndisplayedCharacters();
|
||||||
textElementCharIndex = frameStartTextElementCharIndex;
|
textElementCharIndex = frameStartTextElementCharIndex;
|
||||||
|
|
||||||
// Offset into frame's nsTextNode:
|
// Offset into frame's Text:
|
||||||
const uint32_t untrimmedOffset = frame->GetContentOffset();
|
const uint32_t untrimmedOffset = frame->GetContentOffset();
|
||||||
const uint32_t untrimmedLength = frame->GetContentEnd() - untrimmedOffset;
|
const uint32_t untrimmedLength = frame->GetContentEnd() - untrimmedOffset;
|
||||||
|
|
||||||
@@ -4169,7 +4169,7 @@ bool SVGTextFrame::ResolvePositionsForNode(nsIContent* aContent,
|
|||||||
nsTArray<gfxPoint>& aDeltas) {
|
nsTArray<gfxPoint>& aDeltas) {
|
||||||
if (aContent->IsText()) {
|
if (aContent->IsText()) {
|
||||||
// We found a text node.
|
// We found a text node.
|
||||||
uint32_t length = static_cast<nsTextNode*>(aContent)->TextLength();
|
uint32_t length = aContent->AsText()->TextLength();
|
||||||
if (length) {
|
if (length) {
|
||||||
uint32_t end = aIndex + length;
|
uint32_t end = aIndex + length;
|
||||||
if (MOZ_UNLIKELY(end > mPositions.Length())) {
|
if (MOZ_UNLIKELY(end > mPositions.Length())) {
|
||||||
|
|||||||