зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset e12fa325e112 (bug 1359527) for Win8 masking reftest failures
MozReview-Commit-ID: 5ecOfTu606d
This commit is contained in:
Родитель
fe139bbf07
Коммит
16b90e808a
|
@ -894,11 +894,6 @@ public:
|
|||
* normally return the same SourceSurface object.
|
||||
*/
|
||||
virtual already_AddRefed<SourceSurface> Snapshot() = 0;
|
||||
|
||||
// Snapshots the contents and returns an alpha mask
|
||||
// based on the RGB values.
|
||||
virtual already_AddRefed<SourceSurface> IntoLuminanceSource(LuminanceType aLuminanceType,
|
||||
float aOpacity);
|
||||
virtual IntSize GetSize() = 0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,172 +9,9 @@
|
|||
|
||||
#include "DrawTargetCapture.h"
|
||||
|
||||
#ifdef BUILD_ARM_NEON
|
||||
#include "mozilla/arm.h"
|
||||
#include "LuminanceNEON.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
/**
|
||||
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
|
||||
*/
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
#define GFX_ARGB32_OFFSET_A 0
|
||||
#define GFX_ARGB32_OFFSET_R 1
|
||||
#define GFX_ARGB32_OFFSET_G 2
|
||||
#define GFX_ARGB32_OFFSET_B 3
|
||||
#else
|
||||
#define GFX_ARGB32_OFFSET_A 3
|
||||
#define GFX_ARGB32_OFFSET_R 2
|
||||
#define GFX_ARGB32_OFFSET_G 1
|
||||
#define GFX_ARGB32_OFFSET_B 0
|
||||
#endif
|
||||
|
||||
// c = n / 255
|
||||
// c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4)) * 255 + 0.5
|
||||
static const uint8_t gsRGBToLinearRGBMap[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 4, 5, 5, 5,
|
||||
5, 6, 6, 6, 6, 7, 7, 7,
|
||||
8, 8, 8, 8, 9, 9, 9, 10,
|
||||
10, 10, 11, 11, 12, 12, 12, 13,
|
||||
13, 13, 14, 14, 15, 15, 16, 16,
|
||||
17, 17, 17, 18, 18, 19, 19, 20,
|
||||
20, 21, 22, 22, 23, 23, 24, 24,
|
||||
25, 25, 26, 27, 27, 28, 29, 29,
|
||||
30, 30, 31, 32, 32, 33, 34, 35,
|
||||
35, 36, 37, 37, 38, 39, 40, 41,
|
||||
41, 42, 43, 44, 45, 45, 46, 47,
|
||||
48, 49, 50, 51, 51, 52, 53, 54,
|
||||
55, 56, 57, 58, 59, 60, 61, 62,
|
||||
63, 64, 65, 66, 67, 68, 69, 70,
|
||||
71, 72, 73, 74, 76, 77, 78, 79,
|
||||
80, 81, 82, 84, 85, 86, 87, 88,
|
||||
90, 91, 92, 93, 95, 96, 97, 99,
|
||||
100, 101, 103, 104, 105, 107, 108, 109,
|
||||
111, 112, 114, 115, 116, 118, 119, 121,
|
||||
122, 124, 125, 127, 128, 130, 131, 133,
|
||||
134, 136, 138, 139, 141, 142, 144, 146,
|
||||
147, 149, 151, 152, 154, 156, 157, 159,
|
||||
161, 163, 164, 166, 168, 170, 171, 173,
|
||||
175, 177, 179, 181, 183, 184, 186, 188,
|
||||
190, 192, 194, 196, 198, 200, 202, 204,
|
||||
206, 208, 210, 212, 214, 216, 218, 220,
|
||||
222, 224, 226, 229, 231, 233, 235, 237,
|
||||
239, 242, 244, 246, 248, 250, 253, 255
|
||||
};
|
||||
|
||||
static void
|
||||
ComputesRGBLuminanceMask(const uint8_t *aSourceData,
|
||||
int32_t aSourceStride,
|
||||
uint8_t *aDestData,
|
||||
int32_t aDestStride,
|
||||
const IntSize &aSize,
|
||||
float aOpacity)
|
||||
{
|
||||
#ifdef BUILD_ARM_NEON
|
||||
if (mozilla::supports_neon()) {
|
||||
ComputesRGBLuminanceMask_NEON(aSourceData, aSourceStride,
|
||||
aDestData, aDestStride,
|
||||
aSize, aOpacity);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity
|
||||
int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity
|
||||
int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721
|
||||
int32_t sourceOffset = aSourceStride - 4 * aSize.width;
|
||||
const uint8_t *sourcePixel = aSourceData;
|
||||
int32_t destOffset = aDestStride - aSize.width;
|
||||
uint8_t *destPixel = aDestData;
|
||||
|
||||
for (int32_t y = 0; y < aSize.height; y++) {
|
||||
for (int32_t x = 0; x < aSize.width; x++) {
|
||||
uint8_t a = sourcePixel[GFX_ARGB32_OFFSET_A];
|
||||
|
||||
if (a) {
|
||||
*destPixel = (redFactor * sourcePixel[GFX_ARGB32_OFFSET_R] +
|
||||
greenFactor * sourcePixel[GFX_ARGB32_OFFSET_G] +
|
||||
blueFactor * sourcePixel[GFX_ARGB32_OFFSET_B]) >> 8;
|
||||
} else {
|
||||
*destPixel = 0;
|
||||
}
|
||||
sourcePixel += 4;
|
||||
destPixel++;
|
||||
}
|
||||
sourcePixel += sourceOffset;
|
||||
destPixel += destOffset;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ComputeLinearRGBLuminanceMask(const uint8_t *aSourceData,
|
||||
int32_t aSourceStride,
|
||||
uint8_t *aDestData,
|
||||
int32_t aDestStride,
|
||||
const IntSize &aSize,
|
||||
float aOpacity)
|
||||
{
|
||||
int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity
|
||||
int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity
|
||||
int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721
|
||||
int32_t sourceOffset = aSourceStride - 4 * aSize.width;
|
||||
const uint8_t *sourcePixel = aSourceData;
|
||||
int32_t destOffset = aDestStride - aSize.width;
|
||||
uint8_t *destPixel = aDestData;
|
||||
|
||||
for (int32_t y = 0; y < aSize.height; y++) {
|
||||
for (int32_t x = 0; x < aSize.width; x++) {
|
||||
uint8_t a = sourcePixel[GFX_ARGB32_OFFSET_A];
|
||||
|
||||
// unpremultiply
|
||||
if (a) {
|
||||
if (a == 255) {
|
||||
/* sRGB -> linearRGB -> intensity */
|
||||
*destPixel =
|
||||
static_cast<uint8_t>
|
||||
((gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_R]] *
|
||||
redFactor +
|
||||
gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_G]] *
|
||||
greenFactor +
|
||||
gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_B]] *
|
||||
blueFactor) >> 8);
|
||||
} else {
|
||||
uint8_t tempPixel[4];
|
||||
tempPixel[GFX_ARGB32_OFFSET_B] =
|
||||
(255 * sourcePixel[GFX_ARGB32_OFFSET_B]) / a;
|
||||
tempPixel[GFX_ARGB32_OFFSET_G] =
|
||||
(255 * sourcePixel[GFX_ARGB32_OFFSET_G]) / a;
|
||||
tempPixel[GFX_ARGB32_OFFSET_R] =
|
||||
(255 * sourcePixel[GFX_ARGB32_OFFSET_R]) / a;
|
||||
|
||||
/* sRGB -> linearRGB -> intensity */
|
||||
*destPixel =
|
||||
static_cast<uint8_t>
|
||||
(((gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_R]] *
|
||||
redFactor +
|
||||
gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_G]] *
|
||||
greenFactor +
|
||||
gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_B]] *
|
||||
blueFactor) >> 8) * (a / 255.0f));
|
||||
}
|
||||
} else {
|
||||
*destPixel = 0;
|
||||
}
|
||||
sourcePixel += 4;
|
||||
destPixel++;
|
||||
}
|
||||
sourcePixel += sourceOffset;
|
||||
destPixel += destOffset;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<DrawTargetCapture>
|
||||
DrawTarget::CreateCaptureDT(const IntSize& aSize)
|
||||
{
|
||||
|
@ -227,51 +64,6 @@ DrawTarget::StrokeGlyphs(ScaledFont* aFont,
|
|||
Stroke(path, aPattern, aStrokeOptions, aOptions);
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
DrawTarget::IntoLuminanceSource(LuminanceType aMaskType, float aOpacity)
|
||||
{
|
||||
RefPtr<SourceSurface> surface = Snapshot();
|
||||
IntSize size = surface->GetSize();
|
||||
|
||||
RefPtr<DataSourceSurface> maskSurface = surface->GetDataSurface();
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create alpha channel mask for output
|
||||
RefPtr<DataSourceSurface> destMaskSurface =
|
||||
Factory::CreateDataSourceSurface(size, SurfaceFormat::A8);
|
||||
if (!destMaskSurface) {
|
||||
return nullptr;
|
||||
}
|
||||
DataSourceSurface::MappedSurface destMap;
|
||||
if (!destMaskSurface->Map(DataSourceSurface::MapType::WRITE, &destMap)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (aMaskType) {
|
||||
case LuminanceType::LUMINANCE:
|
||||
{
|
||||
ComputesRGBLuminanceMask(map.mData, map.mStride,
|
||||
destMap.mData, destMap.mStride,
|
||||
size, aOpacity);
|
||||
break;
|
||||
}
|
||||
case LuminanceType::LINEARRGB:
|
||||
{
|
||||
ComputeLinearRGBLuminanceMask(map.mData, map.mStride,
|
||||
destMap.mData, destMap.mStride,
|
||||
size, aOpacity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
maskSurface->Unmap();
|
||||
destMaskSurface->Unmap();
|
||||
|
||||
return destMaskSurface.forget();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -99,37 +99,6 @@ DrawTargetD2D1::Snapshot()
|
|||
return snapshot.forget();
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetD2D1::EnsureLuminanceEffect()
|
||||
{
|
||||
if (mLuminanceEffect.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT hr = mDC->CreateEffect(CLSID_D2D1LuminanceToAlpha,
|
||||
getter_AddRefs(mLuminanceEffect));
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to create luminance effect. Code: " << hexa(hr);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
DrawTargetD2D1::IntoLuminanceSource(LuminanceType aLuminanceType, float aOpacity)
|
||||
{
|
||||
if (aLuminanceType != LuminanceType::LUMINANCE) {
|
||||
return DrawTarget::IntoLuminanceSource(aLuminanceType, aOpacity);
|
||||
}
|
||||
|
||||
// Create the luminance effect
|
||||
EnsureLuminanceEffect();
|
||||
mLuminanceEffect->SetInput(0, mBitmap);
|
||||
|
||||
RefPtr<ID2D1Image> luminanceOutput;
|
||||
mLuminanceEffect->GetOutput(getter_AddRefs(luminanceOutput));
|
||||
|
||||
return MakeAndAddRef<SourceSurfaceD2D1>(luminanceOutput, mDC, SurfaceFormat::A8, mSize);
|
||||
}
|
||||
|
||||
// Command lists are kept around by device contexts until EndDraw is called,
|
||||
// this can cause issues with memory usage (see bug 1238328). EndDraw/BeginDraw
|
||||
// are expensive though, especially relatively when little work is done, so
|
||||
|
@ -851,27 +820,26 @@ DrawTargetD2D1::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
|||
options |= D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
|
||||
}
|
||||
|
||||
RefPtr<ID2D1ImageBrush> mask;
|
||||
Matrix maskTransform = aMaskTransform;
|
||||
RefPtr<ID2D1PathGeometry> clip;
|
||||
RefPtr<ID2D1BitmapBrush> mask;
|
||||
|
||||
Matrix maskTransform = aMaskTransform;
|
||||
|
||||
RefPtr<ID2D1PathGeometry> clip;
|
||||
if (aMask) {
|
||||
RefPtr<ID2D1Image> image = GetImageForSurface(aMask, maskTransform, ExtendMode::CLAMP);
|
||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||
mTransformDirty = true;
|
||||
|
||||
RefPtr<ID2D1Image> image = GetImageForSurface(aMask, maskTransform, ExtendMode::CLAMP);
|
||||
|
||||
// The mask is given in user space. Our layer will apply it in device space.
|
||||
maskTransform = maskTransform * mTransform;
|
||||
|
||||
if (image) {
|
||||
IntSize maskSize = aMask->GetSize();
|
||||
HRESULT hr = mDC->CreateImageBrush(image,
|
||||
D2D1::ImageBrushProperties(D2D1::RectF(0, 0, maskSize.width, maskSize.height)),
|
||||
D2D1::BrushProperties(1.0f, D2DMatrix(maskTransform)),
|
||||
getter_AddRefs(mask));
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() <<"[D2D1.1] Failed to create a ImageBrush, code: " << hexa(hr);
|
||||
}
|
||||
RefPtr<ID2D1Bitmap> bitmap;
|
||||
image->QueryInterface((ID2D1Bitmap**)getter_AddRefs(bitmap));
|
||||
|
||||
mDC->CreateBitmapBrush(bitmap, D2D1::BitmapBrushProperties(), D2D1::BrushProperties(1.0f, D2DMatrix(maskTransform)), getter_AddRefs(mask));
|
||||
MOZ_ASSERT(bitmap); // This should always be true since it was created for a surface.
|
||||
|
||||
factory()->CreatePathGeometry(getter_AddRefs(clip));
|
||||
RefPtr<ID2D1GeometrySink> sink;
|
||||
|
@ -1901,6 +1869,7 @@ DrawTargetD2D1::GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTrans
|
|||
bool aUserSpace)
|
||||
{
|
||||
RefPtr<ID2D1Image> image;
|
||||
|
||||
switch (aSurface->GetType()) {
|
||||
case SurfaceType::D2D1_1_IMAGE:
|
||||
{
|
||||
|
|
|
@ -36,8 +36,6 @@ public:
|
|||
virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; }
|
||||
virtual BackendType GetBackendType() const override { return BackendType::DIRECT2D1_1; }
|
||||
virtual already_AddRefed<SourceSurface> Snapshot() override;
|
||||
virtual already_AddRefed<SourceSurface> IntoLuminanceSource(LuminanceType aLuminanceType,
|
||||
float aOpacity) override;
|
||||
virtual IntSize GetSize() override { return mSize; }
|
||||
|
||||
virtual void Flush() override;
|
||||
|
@ -297,10 +295,6 @@ private:
|
|||
static IDWriteFactory *mDWriteFactory;
|
||||
// This value is uesed to verify if the DrawTarget is created by a stale device.
|
||||
uint32_t mDeviceSeq;
|
||||
|
||||
// List of effects we use
|
||||
void EnsureLuminanceEffect();
|
||||
RefPtr<ID2D1Effect> mLuminanceEffect;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -278,12 +278,6 @@ enum class SamplingBounds : int8_t {
|
|||
BOUNDED
|
||||
};
|
||||
|
||||
// Moz2d version for SVG mask types
|
||||
enum class LuminanceType : int8_t {
|
||||
LUMINANCE,
|
||||
LINEARRGB,
|
||||
};
|
||||
|
||||
/* Color is stored in non-premultiplied form */
|
||||
struct Color
|
||||
{
|
||||
|
|
|
@ -220,11 +220,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
|||
if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
|
||||
SOURCES += [
|
||||
'BlurNEON.cpp',
|
||||
'LuminanceNEON.cpp',
|
||||
'SwizzleNEON.cpp',
|
||||
]
|
||||
SOURCES['BlurNEON.cpp'].flags += CONFIG['NEON_FLAGS']
|
||||
SOURCES['LuminanceNEON.cpp'].flags += CONFIG['NEON_FLAGS']
|
||||
SOURCES['SwizzleNEON.cpp'].flags += CONFIG['NEON_FLAGS']
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -66,6 +66,10 @@ UNIFIED_SOURCES += [
|
|||
'SVGViewFrame.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
|
||||
SOURCES += ['nsSVGMaskFrameNEON.cpp']
|
||||
SOURCES['nsSVGMaskFrameNEON.cpp'].flags += CONFIG['NEON_FLAGS']
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'../../widget',
|
||||
|
|
|
@ -14,12 +14,159 @@
|
|||
#include "mozilla/RefPtr.h"
|
||||
#include "nsSVGEffects.h"
|
||||
#include "mozilla/dom/SVGMaskElement.h"
|
||||
#ifdef BUILD_ARM_NEON
|
||||
#include "mozilla/arm.h"
|
||||
#include "nsSVGMaskFrameNEON.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
// c = n / 255
|
||||
// c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4)) * 255 + 0.5
|
||||
static const uint8_t gsRGBToLinearRGBMap[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 4, 5, 5, 5,
|
||||
5, 6, 6, 6, 6, 7, 7, 7,
|
||||
8, 8, 8, 8, 9, 9, 9, 10,
|
||||
10, 10, 11, 11, 12, 12, 12, 13,
|
||||
13, 13, 14, 14, 15, 15, 16, 16,
|
||||
17, 17, 17, 18, 18, 19, 19, 20,
|
||||
20, 21, 22, 22, 23, 23, 24, 24,
|
||||
25, 25, 26, 27, 27, 28, 29, 29,
|
||||
30, 30, 31, 32, 32, 33, 34, 35,
|
||||
35, 36, 37, 37, 38, 39, 40, 41,
|
||||
41, 42, 43, 44, 45, 45, 46, 47,
|
||||
48, 49, 50, 51, 51, 52, 53, 54,
|
||||
55, 56, 57, 58, 59, 60, 61, 62,
|
||||
63, 64, 65, 66, 67, 68, 69, 70,
|
||||
71, 72, 73, 74, 76, 77, 78, 79,
|
||||
80, 81, 82, 84, 85, 86, 87, 88,
|
||||
90, 91, 92, 93, 95, 96, 97, 99,
|
||||
100, 101, 103, 104, 105, 107, 108, 109,
|
||||
111, 112, 114, 115, 116, 118, 119, 121,
|
||||
122, 124, 125, 127, 128, 130, 131, 133,
|
||||
134, 136, 138, 139, 141, 142, 144, 146,
|
||||
147, 149, 151, 152, 154, 156, 157, 159,
|
||||
161, 163, 164, 166, 168, 170, 171, 173,
|
||||
175, 177, 179, 181, 183, 184, 186, 188,
|
||||
190, 192, 194, 196, 198, 200, 202, 204,
|
||||
206, 208, 210, 212, 214, 216, 218, 220,
|
||||
222, 224, 226, 229, 231, 233, 235, 237,
|
||||
239, 242, 244, 246, 248, 250, 253, 255
|
||||
};
|
||||
|
||||
static void
|
||||
ComputesRGBLuminanceMask(const uint8_t *aSourceData,
|
||||
int32_t aSourceStride,
|
||||
uint8_t *aDestData,
|
||||
int32_t aDestStride,
|
||||
const IntSize &aSize,
|
||||
float aOpacity)
|
||||
{
|
||||
#ifdef BUILD_ARM_NEON
|
||||
if (mozilla::supports_neon()) {
|
||||
ComputesRGBLuminanceMask_NEON(aSourceData, aSourceStride,
|
||||
aDestData, aDestStride,
|
||||
aSize, aOpacity);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity
|
||||
int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity
|
||||
int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721
|
||||
int32_t sourceOffset = aSourceStride - 4 * aSize.width;
|
||||
const uint8_t *sourcePixel = aSourceData;
|
||||
int32_t destOffset = aDestStride - aSize.width;
|
||||
uint8_t *destPixel = aDestData;
|
||||
|
||||
for (int32_t y = 0; y < aSize.height; y++) {
|
||||
for (int32_t x = 0; x < aSize.width; x++) {
|
||||
uint8_t a = sourcePixel[GFX_ARGB32_OFFSET_A];
|
||||
|
||||
if (a) {
|
||||
*destPixel = (redFactor * sourcePixel[GFX_ARGB32_OFFSET_R] +
|
||||
greenFactor * sourcePixel[GFX_ARGB32_OFFSET_G] +
|
||||
blueFactor * sourcePixel[GFX_ARGB32_OFFSET_B]) >> 8;
|
||||
} else {
|
||||
*destPixel = 0;
|
||||
}
|
||||
sourcePixel += 4;
|
||||
destPixel++;
|
||||
}
|
||||
sourcePixel += sourceOffset;
|
||||
destPixel += destOffset;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ComputeLinearRGBLuminanceMask(const uint8_t *aSourceData,
|
||||
int32_t aSourceStride,
|
||||
uint8_t *aDestData,
|
||||
int32_t aDestStride,
|
||||
const IntSize &aSize,
|
||||
float aOpacity)
|
||||
{
|
||||
int32_t redFactor = 55 * aOpacity; // 255 * 0.2125 * opacity
|
||||
int32_t greenFactor = 183 * aOpacity; // 255 * 0.7154 * opacity
|
||||
int32_t blueFactor = 18 * aOpacity; // 255 * 0.0721
|
||||
int32_t sourceOffset = aSourceStride - 4 * aSize.width;
|
||||
const uint8_t *sourcePixel = aSourceData;
|
||||
int32_t destOffset = aDestStride - aSize.width;
|
||||
uint8_t *destPixel = aDestData;
|
||||
|
||||
for (int32_t y = 0; y < aSize.height; y++) {
|
||||
for (int32_t x = 0; x < aSize.width; x++) {
|
||||
uint8_t a = sourcePixel[GFX_ARGB32_OFFSET_A];
|
||||
|
||||
// unpremultiply
|
||||
if (a) {
|
||||
if (a == 255) {
|
||||
/* sRGB -> linearRGB -> intensity */
|
||||
*destPixel =
|
||||
static_cast<uint8_t>
|
||||
((gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_R]] *
|
||||
redFactor +
|
||||
gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_G]] *
|
||||
greenFactor +
|
||||
gsRGBToLinearRGBMap[sourcePixel[GFX_ARGB32_OFFSET_B]] *
|
||||
blueFactor) >> 8);
|
||||
} else {
|
||||
uint8_t tempPixel[4];
|
||||
tempPixel[GFX_ARGB32_OFFSET_B] =
|
||||
(255 * sourcePixel[GFX_ARGB32_OFFSET_B]) / a;
|
||||
tempPixel[GFX_ARGB32_OFFSET_G] =
|
||||
(255 * sourcePixel[GFX_ARGB32_OFFSET_G]) / a;
|
||||
tempPixel[GFX_ARGB32_OFFSET_R] =
|
||||
(255 * sourcePixel[GFX_ARGB32_OFFSET_R]) / a;
|
||||
|
||||
/* sRGB -> linearRGB -> intensity */
|
||||
*destPixel =
|
||||
static_cast<uint8_t>
|
||||
(((gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_R]] *
|
||||
redFactor +
|
||||
gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_G]] *
|
||||
greenFactor +
|
||||
gsRGBToLinearRGBMap[tempPixel[GFX_ARGB32_OFFSET_B]] *
|
||||
blueFactor) >> 8) * (a / 255.0f));
|
||||
}
|
||||
} else {
|
||||
*destPixel = 0;
|
||||
}
|
||||
sourcePixel += 4;
|
||||
destPixel++;
|
||||
}
|
||||
sourcePixel += sourceOffset;
|
||||
destPixel += destOffset;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
|
||||
|
@ -31,22 +178,6 @@ NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
|||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsSVGMaskFrame)
|
||||
|
||||
static LuminanceType
|
||||
GetLuminanceType(uint8_t aNSMaskType)
|
||||
{
|
||||
switch (aNSMaskType) {
|
||||
case NS_STYLE_MASK_TYPE_LUMINANCE:
|
||||
return LuminanceType::LUMINANCE;
|
||||
case NS_STYLE_COLOR_INTERPOLATION_LINEARRGB:
|
||||
return LuminanceType::LINEARRGB;
|
||||
default:
|
||||
{
|
||||
NS_WARNING("Unknown SVG mask type, defaulting to luminance");
|
||||
return LuminanceType::LUMINANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams)
|
||||
{
|
||||
|
@ -129,18 +260,42 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams)
|
|||
|
||||
RefPtr<SourceSurface> surface;
|
||||
if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
|
||||
if (StyleSVG()->mColorInterpolation ==
|
||||
NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
|
||||
maskType = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> maskSnapshot =
|
||||
maskDT->IntoLuminanceSource(GetLuminanceType(maskType), aParams.opacity);
|
||||
RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
|
||||
if (!maskSnapshot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface = maskSnapshot.forget();
|
||||
RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface();
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create alpha channel mask for output
|
||||
RefPtr<DataSourceSurface> destMaskSurface =
|
||||
Factory::CreateDataSourceSurface(maskSurfaceSize, SurfaceFormat::A8);
|
||||
if (!destMaskSurface) {
|
||||
return nullptr;
|
||||
}
|
||||
DataSourceSurface::MappedSurface destMap;
|
||||
if (!destMaskSurface->Map(DataSourceSurface::MapType::WRITE, &destMap)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (StyleSVG()->mColorInterpolation ==
|
||||
NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
|
||||
ComputeLinearRGBLuminanceMask(map.mData, map.mStride,
|
||||
destMap.mData, destMap.mStride,
|
||||
maskSurfaceSize, aParams.opacity);
|
||||
} else {
|
||||
ComputesRGBLuminanceMask(map.mData, map.mStride,
|
||||
destMap.mData, destMap.mStride,
|
||||
maskSurfaceSize, aParams.opacity);
|
||||
}
|
||||
|
||||
maskSurface->Unmap();
|
||||
destMaskSurface->Unmap();
|
||||
surface = destMaskSurface.forget();
|
||||
} else {
|
||||
maskDT->SetTransform(Matrix());
|
||||
maskDT->FillRect(Rect(0, 0, maskSurfaceSize.width, maskSurfaceSize.height), ColorPattern(Color(1.0f, 1.0f, 1.0f, aParams.opacity)), DrawOptions(1, CompositionOp::OP_IN));
|
||||
|
|
|
@ -16,6 +16,21 @@
|
|||
|
||||
class gfxContext;
|
||||
|
||||
/**
|
||||
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
|
||||
*/
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
#define GFX_ARGB32_OFFSET_A 0
|
||||
#define GFX_ARGB32_OFFSET_R 1
|
||||
#define GFX_ARGB32_OFFSET_G 2
|
||||
#define GFX_ARGB32_OFFSET_B 3
|
||||
#else
|
||||
#define GFX_ARGB32_OFFSET_A 3
|
||||
#define GFX_ARGB32_OFFSET_R 2
|
||||
#define GFX_ARGB32_OFFSET_G 1
|
||||
#define GFX_ARGB32_OFFSET_B 0
|
||||
#endif
|
||||
|
||||
class nsSVGMaskFrame final : public nsSVGContainerFrame
|
||||
{
|
||||
friend nsIFrame*
|
||||
|
|
|
@ -3,27 +3,12 @@
|
|||
* 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 "nsSVGMaskFrameNEON.h"
|
||||
#include "nsSVGMaskFrame.h"
|
||||
#include <arm_neon.h>
|
||||
#include "LuminanceNEON.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
/**
|
||||
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
|
||||
*/
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
#define GFX_ARGB32_OFFSET_A 0
|
||||
#define GFX_ARGB32_OFFSET_R 1
|
||||
#define GFX_ARGB32_OFFSET_G 2
|
||||
#define GFX_ARGB32_OFFSET_B 3
|
||||
#else
|
||||
#define GFX_ARGB32_OFFSET_A 3
|
||||
#define GFX_ARGB32_OFFSET_R 2
|
||||
#define GFX_ARGB32_OFFSET_G 1
|
||||
#define GFX_ARGB32_OFFSET_B 0
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData,
|
||||
int32_t aSourceStride,
|
|
@ -3,8 +3,8 @@
|
|||
* 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/. */
|
||||
|
||||
#ifndef __LUMINANCENEON_H__
|
||||
#define __LUMINANCENEON_H__
|
||||
#ifndef __NS_SVGMASKFRAMENEON_H__
|
||||
#define __NS_SVGMASKFRAMENEON_H__
|
||||
|
||||
#include "mozilla/gfx/Point.h"
|
||||
|
||||
|
@ -16,4 +16,4 @@ ComputesRGBLuminanceMask_NEON(const uint8_t *aSourceData,
|
|||
const mozilla::gfx::IntSize &aSize,
|
||||
float aOpacity);
|
||||
|
||||
#endif /* __LUMINANCENEON_H__ */
|
||||
#endif /* __NS_SVGMASKFRAMENEON_H__ */
|
Загрузка…
Ссылка в новой задаче