mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Back out bug 746883, bug 764125, bug 761895, bug 746883, bug 748116
This commit is contained in:
parent
5c8c9441ba
commit
e5b55a65ac
@ -549,11 +549,37 @@ PRUint8 (*nsCanvasRenderingContext2DAzure::sPremultiplyTable)[256] = nsnull;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
static bool
|
||||
AzureCanvasEnabledOnPlatform()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() !=
|
||||
gfxWindowsPlatform::RENDER_DIRECT2D ||
|
||||
!gfxWindowsPlatform::GetPlatform()->DWriteEnabled()) {
|
||||
static bool checkedPref = false;
|
||||
static bool preferSkia;
|
||||
if (!checkedPref) {
|
||||
preferSkia = Preferences::GetBool("gfx.canvas.azure.prefer-skia", false);
|
||||
checkedPref = true;
|
||||
}
|
||||
return preferSkia;
|
||||
}
|
||||
#elif !defined(XP_MACOSX) && !defined(ANDROID) && !defined(LINUX)
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AzureCanvasEnabled()
|
||||
{
|
||||
BackendType dontCare;
|
||||
return gfxPlatform::GetPlatform()->SupportsAzureCanvas(dontCare);
|
||||
static bool checkedPref = false;
|
||||
static bool azureEnabled;
|
||||
if (!checkedPref) {
|
||||
azureEnabled = Preferences::GetBool("gfx.canvas.azure.enabled", false);
|
||||
checkedPref = true;
|
||||
}
|
||||
return azureEnabled && AzureCanvasEnabledOnPlatform();
|
||||
}
|
||||
|
||||
}
|
||||
@ -562,9 +588,7 @@ AzureCanvasEnabled()
|
||||
nsresult
|
||||
NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult)
|
||||
{
|
||||
// XXX[nrc] remove this check when Thebes canvas is removed
|
||||
// (because we will always support Azure)
|
||||
if (!AzureCanvasEnabled()) {
|
||||
if (!AzureCanvasEnabledOnPlatform()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
@ -890,12 +914,30 @@ nsCanvasRenderingContext2DAzure::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCanvasRenderingContext2DAzure::Initialize(PRInt32 width, PRInt32 height)
|
||||
nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, PRInt32 width, PRInt32 height)
|
||||
{
|
||||
Reset();
|
||||
|
||||
NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
|
||||
mDocShell = nsnull;
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
if (!mValid) {
|
||||
// This first time this is called on this object is via
|
||||
// nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
|
||||
// non-null, otherwise we'll return an error here and GetContext won't
|
||||
// return this context object and we'll never enter this code again.
|
||||
// All other times this method is called, if target is null then
|
||||
// mTarget won't be changed, i.e. it will remain non-null, or else it
|
||||
// will be set to non-null.
|
||||
// In all cases, any usable canvas context will have non-null mTarget.
|
||||
|
||||
if (target) {
|
||||
mValid = true;
|
||||
mTarget = target;
|
||||
} else {
|
||||
mValid = false;
|
||||
// Create a dummy target in the hopes that it will help us deal with users
|
||||
// calling into us after having changed the size where the size resulted
|
||||
// in an inability to create a correct DrawTarget.
|
||||
@ -927,45 +969,6 @@ nsCanvasRenderingContext2DAzure::Initialize(PRInt32 width, PRInt32 height)
|
||||
return mValid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, PRInt32 width, PRInt32 height)
|
||||
{
|
||||
Reset();
|
||||
|
||||
NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
|
||||
mDocShell = nsnull;
|
||||
|
||||
// This first time this is called on this object is via
|
||||
// nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
|
||||
// non-null, otherwise we'll return an error here and GetContext won't
|
||||
// return this context object and we'll never enter this code again.
|
||||
// All other times this method is called, if target is null then
|
||||
// mTarget won't be changed, i.e. it will remain non-null, or else it
|
||||
// will be set to non-null.
|
||||
// In all cases, any usable canvas context will have non-null mTarget.
|
||||
|
||||
if (target) {
|
||||
mValid = true;
|
||||
mTarget = target;
|
||||
} else {
|
||||
mValid = false;
|
||||
}
|
||||
|
||||
return Initialize(width, height);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
|
||||
{
|
||||
mDocShell = shell;
|
||||
mThebesSurface = surface;
|
||||
|
||||
mTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, IntSize(width, height));
|
||||
mValid = mTarget != nsnull;
|
||||
|
||||
return Initialize(width, height);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::SetIsOpaque(bool isOpaque)
|
||||
{
|
||||
@ -2490,7 +2493,6 @@ nsCanvasRenderingContext2DAzure::EnsureWritablePath()
|
||||
}
|
||||
|
||||
if (!mPath) {
|
||||
NS_ASSERTION(!mPathTransformWillUpdate, "mPathTransformWillUpdate should be false, if all paths are null");
|
||||
mPathBuilder = mTarget->CreatePathBuilder(fillRule);
|
||||
} else if (!mPathTransformWillUpdate) {
|
||||
mPathBuilder = mPath->CopyToBuilder(fillRule);
|
||||
@ -2502,7 +2504,7 @@ nsCanvasRenderingContext2DAzure::EnsureWritablePath()
|
||||
}
|
||||
|
||||
void
|
||||
nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* = true */)
|
||||
nsCanvasRenderingContext2DAzure::EnsureUserSpacePath()
|
||||
{
|
||||
FillRule fillRule = CurrentState().fillRule;
|
||||
|
||||
@ -2515,9 +2517,7 @@ nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* =
|
||||
mPathBuilder = nsnull;
|
||||
}
|
||||
|
||||
if (aCommitTransform &&
|
||||
mPath &&
|
||||
mPathTransformWillUpdate) {
|
||||
if (mPath && mPathTransformWillUpdate) {
|
||||
mDSPathBuilder =
|
||||
mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
|
||||
mPath = nsnull;
|
||||
@ -2531,7 +2531,6 @@ nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* =
|
||||
|
||||
Matrix inverse = mTarget->GetTransform();
|
||||
if (!inverse.Invert()) {
|
||||
NS_WARNING("Could not invert transform");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2545,8 +2544,6 @@ nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* =
|
||||
mPathBuilder = mPath->CopyToBuilder(fillRule);
|
||||
mPath = mPathBuilder->Finish();
|
||||
}
|
||||
|
||||
NS_ASSERTION(mPath, "mPath should exist");
|
||||
}
|
||||
|
||||
void
|
||||
@ -3047,7 +3044,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
|
||||
const gfxTextRun::CompressedGlyph *glyphs = mTextRun->GetCharacterGlyphs();
|
||||
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
gfxPlatform::GetPlatform()->GetScaledFontForFont(mCtx->mTarget, font);
|
||||
gfxPlatform::GetPlatform()->GetScaledFontForFont(font);
|
||||
|
||||
if (!scaledFont) {
|
||||
// This can occur when something switched DirectWrite off.
|
||||
@ -3107,21 +3104,21 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
|
||||
AdjustedTarget(mCtx)->
|
||||
FillGlyphs(scaledFont, buffer,
|
||||
CanvasGeneralPattern().
|
||||
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget),
|
||||
DrawOptions(mState->globalAlpha, mCtx->UsedOperation()));
|
||||
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget),
|
||||
DrawOptions(mState->globalAlpha, mCtx->UsedOperation()));
|
||||
} else if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_STROKE) {
|
||||
RefPtr<Path> path = scaledFont->GetPathForGlyphs(buffer, mCtx->mTarget);
|
||||
|
||||
const ContextState& state = *mState;
|
||||
AdjustedTarget(mCtx)->
|
||||
Stroke(path, CanvasGeneralPattern().
|
||||
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
|
||||
StrokeOptions(state.lineWidth, state.lineJoin,
|
||||
state.lineCap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset),
|
||||
DrawOptions(state.globalAlpha, mCtx->UsedOperation()));
|
||||
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
|
||||
StrokeOptions(state.lineWidth, state.lineJoin,
|
||||
state.lineCap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset),
|
||||
DrawOptions(state.globalAlpha, mCtx->UsedOperation()));
|
||||
|
||||
}
|
||||
}
|
||||
@ -3610,14 +3607,9 @@ nsCanvasRenderingContext2DAzure::IsPointInPath(double x, double y)
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureUserSpacePath(false);
|
||||
if (!mPath) {
|
||||
return false;
|
||||
}
|
||||
if (mPathTransformWillUpdate) {
|
||||
return mPath->ContainsPoint(Point(x, y), mPathToDS);
|
||||
}
|
||||
return mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
|
||||
EnsureUserSpacePath();
|
||||
|
||||
return mPath && mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -3676,14 +3668,12 @@ nsCanvasRenderingContext2DAzure::DrawImage(const HTMLImageOrCanvasOrVideoElement
|
||||
// This might not be an Azure canvas!
|
||||
srcSurf = srcCanvas->GetSurfaceSnapshot();
|
||||
|
||||
if (srcSurf) {
|
||||
if (mCanvasElement) {
|
||||
// Do security check here.
|
||||
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
|
||||
element->NodePrincipal(),
|
||||
canvas->IsWriteOnly(),
|
||||
false);
|
||||
}
|
||||
if (srcSurf && mCanvasElement) {
|
||||
// Do security check here.
|
||||
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
|
||||
element->NodePrincipal(),
|
||||
canvas->IsWriteOnly(),
|
||||
false);
|
||||
imgSize = gfxIntSize(srcSurf->GetSize().width, srcSurf->GetSize().height);
|
||||
}
|
||||
}
|
||||
@ -4265,12 +4255,11 @@ nsCanvasRenderingContext2DAzure::GetImageDataArray(JSContext* aCx,
|
||||
RefPtr<DataSourceSurface> readback;
|
||||
if (!srcReadRect.IsEmpty()) {
|
||||
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
|
||||
if (snapshot) {
|
||||
readback = snapshot->GetDataSurface();
|
||||
|
||||
srcStride = readback->Stride();
|
||||
src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
|
||||
}
|
||||
readback = snapshot->GetDataSurface();
|
||||
|
||||
srcStride = readback->Stride();
|
||||
src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
|
||||
}
|
||||
|
||||
// make sure sUnpremultiplyTable has been created
|
||||
@ -4278,8 +4267,6 @@ nsCanvasRenderingContext2DAzure::GetImageDataArray(JSContext* aCx,
|
||||
|
||||
// NOTE! dst is the same as src, and this relies on reading
|
||||
// from src and advancing that ptr before writing to dst.
|
||||
// NOTE! I'm not sure that it is, I think this comment might have been
|
||||
// inherited from Thebes canvas and is no longer true
|
||||
uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
|
||||
|
||||
for (int32_t j = 0; j < dstWriteRect.height; ++j) {
|
||||
@ -4611,8 +4598,8 @@ static PRUint8 g2DContextLayerUserData;
|
||||
|
||||
already_AddRefed<CanvasLayer>
|
||||
nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
CanvasLayer *aOldLayer,
|
||||
LayerManager *aManager)
|
||||
CanvasLayer *aOldLayer,
|
||||
LayerManager *aManager)
|
||||
{
|
||||
if (!mValid) {
|
||||
return nsnull;
|
||||
@ -4682,9 +4669,3 @@ nsCanvasRenderingContext2DAzure::MarkContextClean()
|
||||
mInvalidateCount = 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsCanvasRenderingContext2DAzure::ShouldForceInactiveLayer(LayerManager *aManager)
|
||||
{
|
||||
return !aManager->CanUseCanvasLayerForSize(gfxIntSize(mWidth, mHeight));
|
||||
}
|
||||
|
@ -464,7 +464,8 @@ public:
|
||||
|
||||
// nsICanvasRenderingContextInternal
|
||||
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height);
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHOD Render(gfxContext *ctx,
|
||||
gfxPattern::GraphicsFilter aFilter,
|
||||
@ -482,7 +483,6 @@ public:
|
||||
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
CanvasLayer *aOldLayer,
|
||||
LayerManager *aManager);
|
||||
virtual bool ShouldForceInactiveLayer(LayerManager *aManager);
|
||||
void MarkContextClean();
|
||||
NS_IMETHOD SetIsIPC(bool isIPC);
|
||||
// this rect is in canvas device space
|
||||
@ -542,11 +542,6 @@ protected:
|
||||
uint32_t aWidth, uint32_t aHeight,
|
||||
JSObject** aRetval);
|
||||
|
||||
/**
|
||||
* Internal method to complete initialisation, expects mTarget to have been set
|
||||
*/
|
||||
nsresult Initialize(PRInt32 width, PRInt32 height);
|
||||
|
||||
nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface,
|
||||
PRInt32 width, PRInt32 height);
|
||||
|
||||
@ -601,14 +596,11 @@ protected:
|
||||
/* This function ensures there is a writable pathbuilder available, this
|
||||
* pathbuilder may be working in user space or in device space or
|
||||
* device space.
|
||||
* After calling this function mPathTransformWillUpdate will be false
|
||||
*/
|
||||
void EnsureWritablePath();
|
||||
|
||||
// Ensures a path in UserSpace is available.
|
||||
// If aCommitTransform is true, then any transform on the context will be
|
||||
// used for the path.
|
||||
void EnsureUserSpacePath(bool aCommitTransform = true);
|
||||
void EnsureUserSpacePath();
|
||||
|
||||
void TransformWillUpdate();
|
||||
|
||||
|
@ -55,7 +55,6 @@ MOCHITEST_FILES = \
|
||||
test_canvas_strokeStyle_getter.html \
|
||||
test_bug613794.html \
|
||||
test_bug753758.html \
|
||||
test_bug764125.html \
|
||||
test_drawImage_edge_cases.html \
|
||||
$(NULL)
|
||||
|
||||
|
@ -1,36 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=764125
|
||||
|
||||
Test the correct behaviour for isPointInPath in the presence of multiple transforms,
|
||||
where only one tranform ought to be applied.
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 764125</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=764125">Mozilla Bug 764125</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script>
|
||||
/** Test for Bug 764125 **/
|
||||
|
||||
var c = document.createElement("canvas");
|
||||
|
||||
var ctx = c.getContext("2d");
|
||||
ctx.translate(50, 0);
|
||||
ctx.rect(50, 0, 20, 20);
|
||||
ctx.translate(0, 50);
|
||||
ok(ctx.isPointInPath(60, 10) === false, "ctx.isPointInPath(60, 10) === false");
|
||||
ok(ctx.isPointInPath(110, 10) === true, "ctx.isPointInPath(110, 10) === true");
|
||||
ok(ctx.isPointInPath(110, 60) === false, "ctx.isPointInPath(110, 60) === false");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -18,10 +18,6 @@ function IsD2DEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
function IsLinux() {
|
||||
return navigator.platform.indexOf("Linux") == 0;
|
||||
}
|
||||
|
||||
function IsMacOSX10_5orOlder() {
|
||||
var is105orOlder = false;
|
||||
|
||||
@ -44,8 +40,7 @@ function IsAzureEnabled() {
|
||||
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
|
||||
enabled = (backend != "none");
|
||||
enabled = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).AzureEnabled;
|
||||
} catch (e) { }
|
||||
|
||||
return enabled;
|
||||
@ -63,18 +58,6 @@ function IsAzureSkia() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
function IsAzureCairo() {
|
||||
var enabled = false;
|
||||
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
|
||||
enabled = (backend == "cairo");
|
||||
} catch (e) { }
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
</script>
|
||||
<!-- Includes all the tests in the content/canvas/tests except for test_bug397524.html -->
|
||||
|
||||
@ -11312,24 +11295,10 @@ isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||
// Fails on Linux with Azure/Cairo only
|
||||
// The arc is drawn badly due to Cairo limitations, the error only becomes
|
||||
// apparent on Linux because of anti-aliasing, probably due to X.
|
||||
// The limitation is that Cairo draws arcs by stroking perpendicular to the arc,
|
||||
// and at very large stroke thicknesses, this becomes a fan. Where exactly the
|
||||
// 'blades' of the fan appear seems to depend on exactly how the arc is defined
|
||||
// and the platform. So if the blades of the fan are where pixels are tested it
|
||||
// passes the test, if the testing pixels fall in between the blades, then we fail.
|
||||
// With Thebes/Cairo, we were rendering wrong, but got lucky with the test, now
|
||||
// we are not so lucky.
|
||||
// Bug 764125
|
||||
if (IsAzureCairo() && IsLinux()) {
|
||||
todo_isPixel(ctx, 20,48, 0,255,0,255, 0);
|
||||
} else {
|
||||
isPixel(ctx, 20,48, 0,255,0,255, 0);
|
||||
}
|
||||
isPixel(ctx, 20,48, 0,255,0,255, 0);
|
||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -14688,14 +14657,9 @@ isPixel(ctx, 0,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 99,25, 0,255,0,255, 0);
|
||||
isPixel(ctx, 0,49, 0,255,0,255, 0);
|
||||
if (IsAzureEnabled() && IsAzureCairo()) {
|
||||
// Bug 764108
|
||||
todo_isPixel(ctx, 50,49, 0,255,0,255, 0);
|
||||
todo_isPixel(ctx, 99,49, 0,255,0,255, 0);
|
||||
} else {
|
||||
isPixel(ctx, 50,49, 0,255,0,255, 0);
|
||||
isPixel(ctx, 99,49, 0,255,0,255, 0);
|
||||
}
|
||||
isPixel(ctx, 50,49, 0,255,0,255, 0);
|
||||
isPixel(ctx, 99,49, 0,255,0,255, 0);
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
@ -802,7 +802,7 @@ class GFX2D_API Factory
|
||||
public:
|
||||
static bool HasSSE2();
|
||||
|
||||
static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize);
|
||||
static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface);
|
||||
|
||||
static TemporaryRef<DrawTarget>
|
||||
CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);
|
||||
|
@ -13,8 +13,6 @@
|
||||
#include "cairo.h"
|
||||
|
||||
#include "Blur.h"
|
||||
#include "Logging.h"
|
||||
#include "Tools.h"
|
||||
|
||||
#ifdef CAIRO_HAS_QUARTZ_SURFACE
|
||||
#include "cairo-quartz.h"
|
||||
@ -118,51 +116,6 @@ PatternIsCompatible(const Pattern& aPattern)
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_user_data_key_t surfaceDataKey;
|
||||
|
||||
void
|
||||
ReleaseData(void* aData)
|
||||
{
|
||||
static_cast<DataSourceSurface*>(aData)->Release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cairo surface for the given SourceSurface.
|
||||
* If possible, it will use the cairo_surface associated with aSurface,
|
||||
* otherwise, it will create a new cairo_surface.
|
||||
* In either case, the caller must call cairo_surface_destroy on the
|
||||
* result when it is done with it.
|
||||
*/
|
||||
cairo_surface_t*
|
||||
GetCairoSurfaceForSourceSurface(SourceSurface *aSurface)
|
||||
{
|
||||
if (aSurface->GetType() == SURFACE_CAIRO) {
|
||||
cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
|
||||
cairo_surface_reference(surf);
|
||||
return surf;
|
||||
}
|
||||
|
||||
if (aSurface->GetType() == SURFACE_CAIRO_IMAGE) {
|
||||
cairo_surface_t* surf =
|
||||
static_cast<const DataSourceSurfaceCairo*>(aSurface)->GetSurface();
|
||||
cairo_surface_reference(surf);
|
||||
return surf;
|
||||
}
|
||||
|
||||
RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
|
||||
cairo_surface_t* surf =
|
||||
cairo_image_surface_create_for_data(data->GetData(),
|
||||
GfxFormatToCairoFormat(data->GetFormat()),
|
||||
data->GetSize().width,
|
||||
data->GetSize().height,
|
||||
data->Stride());
|
||||
cairo_surface_set_user_data(surf,
|
||||
&surfaceDataKey,
|
||||
data.forget().drop(),
|
||||
ReleaseData);
|
||||
return surf;
|
||||
}
|
||||
|
||||
// Never returns NULL. As such, you must always pass in Cairo-compatible
|
||||
// patterns, most notably gradients with a GradientStopCairo.
|
||||
// The pattern returned must have cairo_pattern_destroy() called on it by the
|
||||
@ -187,7 +140,28 @@ GfxPatternToCairoPattern(const Pattern& aPattern, Float aAlpha)
|
||||
case PATTERN_SURFACE:
|
||||
{
|
||||
const SurfacePattern& pattern = static_cast<const SurfacePattern&>(aPattern);
|
||||
cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(pattern.mSurface);
|
||||
cairo_surface_t* surf;
|
||||
|
||||
// After this block, |surf| always has an extra cairo reference to be
|
||||
// destroyed. This makes creating new surfaces or reusing old ones more
|
||||
// uniform.
|
||||
if (pattern.mSurface->GetType() == SURFACE_CAIRO) {
|
||||
const SourceSurfaceCairo* source = static_cast<const SourceSurfaceCairo*>(pattern.mSurface.get());
|
||||
surf = source->GetSurface();
|
||||
cairo_surface_reference(surf);
|
||||
} else if (pattern.mSurface->GetType() == SURFACE_CAIRO_IMAGE) {
|
||||
const DataSourceSurfaceCairo* source =
|
||||
static_cast<const DataSourceSurfaceCairo*>(pattern.mSurface.get());
|
||||
surf = source->GetSurface();
|
||||
cairo_surface_reference(surf);
|
||||
} else {
|
||||
RefPtr<DataSourceSurface> source = pattern.mSurface->GetDataSurface();
|
||||
surf = cairo_image_surface_create_for_data(source->GetData(),
|
||||
GfxFormatToCairoFormat(source->GetFormat()),
|
||||
source->GetSize().width,
|
||||
source->GetSize().height,
|
||||
source->Stride());
|
||||
}
|
||||
|
||||
pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(pattern.mFilter));
|
||||
@ -244,21 +218,6 @@ GfxPatternToCairoPattern(const Pattern& aPattern, Float aAlpha)
|
||||
return pat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff the the given operator should affect areas of the
|
||||
* destination where the source is transparent. Among other things, this
|
||||
* implies that a fully transparent source would still affect the canvas.
|
||||
*/
|
||||
static bool
|
||||
OperatorAffectsUncoveredAreas(CompositionOp op)
|
||||
{
|
||||
return op == OP_IN ||
|
||||
op == OP_OUT ||
|
||||
op == OP_DEST_IN ||
|
||||
op == OP_DEST_ATOP ||
|
||||
op == OP_DEST_OUT;
|
||||
}
|
||||
|
||||
static bool
|
||||
NeedIntermediateSurface(const Pattern& aPattern, const DrawOptions& aOptions)
|
||||
{
|
||||
@ -285,28 +244,29 @@ DrawTargetCairo::~DrawTargetCairo()
|
||||
mPathObserver->ForgetDrawTarget();
|
||||
}
|
||||
cairo_destroy(mContext);
|
||||
if (mSurface) {
|
||||
cairo_surface_destroy(mSurface);
|
||||
}
|
||||
}
|
||||
|
||||
IntSize
|
||||
DrawTargetCairo::GetSize()
|
||||
{
|
||||
return mSize;
|
||||
return IntSize();
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
DrawTargetCairo::Snapshot()
|
||||
{
|
||||
IntSize size = GetSize();
|
||||
cairo_surface_t* csurf = cairo_get_target(mContext);
|
||||
IntSize size;
|
||||
if (GetCairoSurfaceSize(csurf, size)) {
|
||||
cairo_content_t content = cairo_surface_get_content(csurf);
|
||||
RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(csurf, size,
|
||||
CairoContentToGfxFormat(content),
|
||||
this);
|
||||
AppendSnapshot(surf);
|
||||
return surf;
|
||||
}
|
||||
|
||||
cairo_content_t content = cairo_surface_get_content(mSurface);
|
||||
RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(mSurface, size,
|
||||
CairoContentToGfxFormat(content),
|
||||
this);
|
||||
AppendSnapshot(surf);
|
||||
return surf;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@ -335,40 +295,29 @@ DrawTargetCairo::DrawSurface(SourceSurface *aSurface,
|
||||
float sy = aSource.Height() / aDest.Height();
|
||||
|
||||
cairo_matrix_t src_mat;
|
||||
cairo_matrix_init_translate(&src_mat, aSource.X(), aSource.Y());
|
||||
cairo_matrix_scale(&src_mat, sx, sy);
|
||||
cairo_matrix_init_scale(&src_mat, sx, sy);
|
||||
cairo_matrix_translate(&src_mat, aSource.X(), aSource.Y());
|
||||
|
||||
cairo_surface_t* surf = NULL;
|
||||
if (aSurface->GetType() == SURFACE_CAIRO) {
|
||||
surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
|
||||
}
|
||||
|
||||
cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(aSurface);
|
||||
cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_surface_destroy(surf);
|
||||
|
||||
cairo_pattern_set_matrix(pat, &src_mat);
|
||||
cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter));
|
||||
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
|
||||
|
||||
cairo_save(mContext);
|
||||
cairo_translate(mContext, aDest.X(), aDest.Y());
|
||||
|
||||
if (OperatorAffectsUncoveredAreas(aOptions.mCompositionOp) ||
|
||||
aOptions.mCompositionOp == OP_SOURCE) {
|
||||
cairo_push_group(mContext);
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
|
||||
//TODO[nrc] remove comments if test ok
|
||||
//cairo_clip(mContext);
|
||||
cairo_set_source(mContext, pat);
|
||||
//cairo_paint(mContext);
|
||||
cairo_fill(mContext);
|
||||
cairo_pop_group_to_source(mContext);
|
||||
} else {
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
|
||||
cairo_clip(mContext);
|
||||
cairo_set_source(mContext, pat);
|
||||
}
|
||||
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
|
||||
|
||||
cairo_translate(mContext, aDest.X(), aDest.Y());
|
||||
|
||||
cairo_set_source(mContext, pat);
|
||||
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
|
||||
cairo_clip(mContext);
|
||||
cairo_paint_with_alpha(mContext, aOptions.mAlpha);
|
||||
|
||||
cairo_restore(mContext);
|
||||
@ -384,11 +333,13 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
||||
Float aSigma,
|
||||
CompositionOp aOperator)
|
||||
{
|
||||
WillChange();
|
||||
|
||||
if (aSurface->GetType() != SURFACE_CAIRO) {
|
||||
return;
|
||||
}
|
||||
|
||||
WillChange();
|
||||
SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
|
||||
|
||||
Float width = aSurface->GetSize().width;
|
||||
Float height = aSurface->GetSize().height;
|
||||
@ -402,19 +353,16 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
||||
}
|
||||
|
||||
IntSize blursize = blur.GetSize();
|
||||
|
||||
cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(),
|
||||
CAIRO_FORMAT_A8,
|
||||
blursize.width,
|
||||
blursize.height,
|
||||
blur.GetStride());
|
||||
|
||||
ClearSurfaceForUnboundedSource(aOperator);
|
||||
|
||||
// Draw the source surface into the surface we're going to blur.
|
||||
SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
|
||||
cairo_surface_t* surf = source->GetSurface();
|
||||
cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
|
||||
|
||||
cairo_t* ctx = cairo_create(blursurf);
|
||||
|
||||
@ -431,39 +379,26 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
||||
// Blur the result, then use that blurred result as a mask to draw the shadow
|
||||
// colour to the surface.
|
||||
blur.Blur();
|
||||
|
||||
cairo_save(mContext);
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
|
||||
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
|
||||
cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
|
||||
|
||||
cairo_identity_matrix(mContext);
|
||||
cairo_translate(mContext, aDest.x, aDest.y);
|
||||
|
||||
if (OperatorAffectsUncoveredAreas(aOperator) ||
|
||||
aOperator == OP_SOURCE){
|
||||
cairo_push_group(mContext);
|
||||
cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
|
||||
cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
|
||||
cairo_pop_group_to_source(mContext);
|
||||
cairo_paint(mContext);
|
||||
cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
|
||||
|
||||
// Now that the shadow has been drawn, we can draw the surface on top.
|
||||
cairo_push_group(mContext);
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, width, height);
|
||||
//TODO[nrc] remove comments if test ok
|
||||
//cairo_clip(mContext);
|
||||
cairo_set_source(mContext, pat);
|
||||
//cairo_paint(mContext);
|
||||
cairo_fill(mContext);
|
||||
cairo_pop_group_to_source(mContext);
|
||||
} else {
|
||||
cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
|
||||
cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
|
||||
// Now that the shadow has been drawn, we can draw the surface on top.
|
||||
|
||||
// Now that the shadow has been drawn, we can draw the surface on top.
|
||||
cairo_set_source(mContext, pat);
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, width, height);
|
||||
cairo_clip(mContext);
|
||||
}
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
|
||||
|
||||
cairo_set_source(mContext, pat);
|
||||
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, width, height);
|
||||
cairo_clip(mContext);
|
||||
|
||||
cairo_paint(mContext);
|
||||
|
||||
@ -485,12 +420,9 @@ DrawTargetCairo::DrawPattern(const Pattern& aPattern,
|
||||
cairo_pattern_t* pat = GfxPatternToCairoPattern(aPattern, aOptions.mAlpha);
|
||||
cairo_set_source(mContext, pat);
|
||||
|
||||
if (NeedIntermediateSurface(aPattern, aOptions) ||
|
||||
OperatorAffectsUncoveredAreas(aOptions.mCompositionOp)) {
|
||||
if (NeedIntermediateSurface(aPattern, aOptions)) {
|
||||
cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
|
||||
|
||||
// Don't want operators to be applied twice
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
|
||||
|
||||
@ -507,7 +439,6 @@ DrawTargetCairo::DrawPattern(const Pattern& aPattern,
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
|
||||
cairo_paint_with_alpha(mContext, aOptions.mAlpha);
|
||||
} else {
|
||||
ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
|
||||
|
||||
if (aDrawType == DRAW_STROKE) {
|
||||
@ -536,31 +467,10 @@ DrawTargetCairo::FillRect(const Rect &aRect,
|
||||
|
||||
void
|
||||
DrawTargetCairo::CopySurface(SourceSurface *aSurface,
|
||||
const IntRect &aSource,
|
||||
const IntPoint &aDest)
|
||||
const IntRect &aSourceRect,
|
||||
const IntPoint &aDestination)
|
||||
{
|
||||
AutoPrepareForDrawing prep(this, mContext);
|
||||
|
||||
if (!aSurface || aSurface->GetType() != SURFACE_CAIRO) {
|
||||
gfxWarning() << "Unsupported surface type specified";
|
||||
return;
|
||||
}
|
||||
|
||||
cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
|
||||
|
||||
cairo_save(mContext);
|
||||
|
||||
cairo_identity_matrix(mContext);
|
||||
|
||||
cairo_set_source_surface(mContext, surf, aDest.x - aSource.x, aDest.y - aSource.y);
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_SOURCE);
|
||||
|
||||
cairo_reset_clip(mContext);
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, aDest.x, aDest.y, aSource.width, aSource.height);
|
||||
cairo_fill(mContext);
|
||||
|
||||
cairo_restore(mContext);
|
||||
}
|
||||
|
||||
void
|
||||
@ -726,19 +636,6 @@ DrawTargetCairo::CreatePathBuilder(FillRule aFillRule /* = FILL_WINDING */) cons
|
||||
return builder;
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::ClearSurfaceForUnboundedSource(const CompositionOp &aOperator)
|
||||
{
|
||||
if (aOperator != OP_SOURCE)
|
||||
return;
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_CLEAR);
|
||||
// It doesn't really matter what the source is here, since Paint
|
||||
// isn't bounded by the source and the mask covers the entire clip
|
||||
// region.
|
||||
cairo_paint(mContext);
|
||||
}
|
||||
|
||||
|
||||
TemporaryRef<GradientStops>
|
||||
DrawTargetCairo::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
|
||||
{
|
||||
@ -746,40 +643,19 @@ DrawTargetCairo::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, E
|
||||
return stops;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies pixel data from aData into aSurface; aData must have the dimensions
|
||||
* given in aSize, with a stride of aStride bytes and aPixelWidth bytes per pixel
|
||||
*/
|
||||
static void
|
||||
CopyDataToCairoSurface(cairo_surface_t* aSurface,
|
||||
unsigned char *aData,
|
||||
const IntSize &aSize,
|
||||
int32_t aStride,
|
||||
int32_t aPixelWidth)
|
||||
{
|
||||
unsigned char* surfData = cairo_image_surface_get_data(aSurface);
|
||||
for (int32_t y = 0; y < aSize.height; ++y) {
|
||||
memcpy(surfData + y * aSize.width * aPixelWidth,
|
||||
aData + y * aStride,
|
||||
aSize.width * aPixelWidth);
|
||||
}
|
||||
cairo_surface_mark_dirty(aSurface);
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
|
||||
const IntSize &aSize,
|
||||
int32_t aStride,
|
||||
SurfaceFormat aFormat) const
|
||||
{
|
||||
cairo_surface_t* surf = cairo_image_surface_create(GfxFormatToCairoFormat(aFormat),
|
||||
aSize.width,
|
||||
aSize.height);
|
||||
CopyDataToCairoSurface(surf, aData, aSize, aStride, BytesPerPixel(aFormat));
|
||||
|
||||
cairo_surface_t* surf = cairo_image_surface_create_for_data(aData,
|
||||
GfxFormatToCairoFormat(aFormat),
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
aStride);
|
||||
RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo(surf, aSize, aFormat);
|
||||
cairo_surface_destroy(surf);
|
||||
|
||||
return source_surf;
|
||||
}
|
||||
|
||||
@ -814,7 +690,7 @@ DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFo
|
||||
|
||||
if (!cairo_surface_status(similar)) {
|
||||
RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
|
||||
target->Init(similar, aSize);
|
||||
target->Init(similar);
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -822,13 +698,9 @@ DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFo
|
||||
}
|
||||
|
||||
bool
|
||||
DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize)
|
||||
DrawTargetCairo::Init(cairo_surface_t* aSurface)
|
||||
{
|
||||
mContext = cairo_create(aSurface);
|
||||
mSurface = aSurface;
|
||||
cairo_surface_reference(mSurface);
|
||||
mSize = aSize;
|
||||
mFormat = CairoContentToGfxFormat(cairo_surface_get_content(aSurface));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ public:
|
||||
|
||||
virtual void *GetNativeSurface(NativeSurfaceType aType);
|
||||
|
||||
bool Init(cairo_surface_t* aSurface, const IntSize& aSize);
|
||||
bool Init(cairo_surface_t* aSurface);
|
||||
|
||||
void SetPathObserver(CairoPathContext* aPathObserver);
|
||||
|
||||
@ -155,13 +155,8 @@ private: // methods
|
||||
// target; for example, because we're going to be destroyed.
|
||||
void MarkSnapshotsIndependent();
|
||||
|
||||
// If the current operator is "source" then clear the destination before we
|
||||
// draw into it, to simulate the effect of an unbounded source operator.
|
||||
void ClearSurfaceForUnboundedSource(const CompositionOp &aOperator);
|
||||
private: // data
|
||||
cairo_t* mContext;
|
||||
cairo_surface_t* mSurface;
|
||||
IntSize mSize;
|
||||
std::vector<SourceSurfaceCairo*> mSnapshots;
|
||||
mutable RefPtr<CairoPathContext> mPathObserver;
|
||||
};
|
||||
|
@ -239,10 +239,6 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz
|
||||
{
|
||||
return new ScaledFontDWrite(static_cast<IDWriteFontFace*>(aNativeFont.mFont), aSize);
|
||||
}
|
||||
case NATIVE_FONT_GDI_FONT_FACE:
|
||||
{
|
||||
return new ScaledFontWin(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
|
||||
}
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
case NATIVE_FONT_MAC_FONT_FACE:
|
||||
@ -251,6 +247,12 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SKIA
|
||||
#ifdef WIN32
|
||||
case NATIVE_FONT_GDI_FONT_FACE:
|
||||
{
|
||||
return new ScaledFontWin(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_ENABLE_FREETYPE
|
||||
case NATIVE_FONT_SKIA_FONT_FACE:
|
||||
{
|
||||
@ -261,9 +263,7 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz
|
||||
#ifdef USE_CAIRO
|
||||
case NATIVE_FONT_CAIRO_FONT_FACE:
|
||||
{
|
||||
ScaledFontBase* fontBase = new ScaledFontBase(aSize);
|
||||
fontBase->SetCairoScaledFont(static_cast<cairo_scaled_font_t*>(aNativeFont.mFont));
|
||||
return fontBase;
|
||||
return new ScaledFontBase(aSize);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
@ -367,11 +367,11 @@ Factory::GetD2DVRAMUsageSourceSurface()
|
||||
#endif // XP_WIN
|
||||
|
||||
TemporaryRef<DrawTarget>
|
||||
Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize)
|
||||
Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface)
|
||||
{
|
||||
#ifdef USE_CAIRO
|
||||
RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo();
|
||||
if (newTarget->Init(aSurface, aSize)) {
|
||||
if (newTarget->Init(aSurface)) {
|
||||
return newTarget;
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ JoinStyleToSkiaJoin(JoinStyle aJoin)
|
||||
static inline bool
|
||||
StrokeOptionsToPaint(SkPaint& aPaint, const StrokeOptions &aOptions)
|
||||
{
|
||||
// Skia renders 0 width strokes with a width of 1 (and in black),
|
||||
// Skia rendewrs 0 width strokes with a width of 1 (and in black),
|
||||
// so we should just skip the draw call entirely.
|
||||
if (!aOptions.mLineWidth) {
|
||||
return false;
|
||||
|
@ -44,28 +44,6 @@ CairoPathContext::~CairoPathContext()
|
||||
cairo_destroy(mContext);
|
||||
}
|
||||
|
||||
void
|
||||
CairoPathContext::ObserveTarget(DrawTargetCairo* aDrawTarget)
|
||||
{
|
||||
if (!aDrawTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDrawTarget) {
|
||||
mDrawTarget->SetPathObserver(NULL);
|
||||
}
|
||||
mDrawTarget = aDrawTarget;
|
||||
|
||||
// If there is a transform on the path, then we must have a separate context
|
||||
// from the draw target, so we cannot be its observer
|
||||
if (!mTransform.IsIdentity()) {
|
||||
ForgetDrawTarget();
|
||||
return;
|
||||
}
|
||||
|
||||
mDrawTarget->SetPathObserver(this);
|
||||
}
|
||||
|
||||
void
|
||||
CairoPathContext::DuplicateContextAndPath(const Matrix& aMatrix /* = Matrix() */)
|
||||
{
|
||||
@ -342,7 +320,11 @@ PathCairo::CopyPathTo(cairo_t* aContext, DrawTargetCairo* aDrawTarget)
|
||||
|
||||
// Since aDrawTarget wants us to be the current path on its context, we
|
||||
// should also listen to it for updates to that path (as an optimization).
|
||||
mPathContext->ObserveTarget(aDrawTarget);
|
||||
// The easiest way to do this is to just recreate mPathContext, since it
|
||||
// registers with aDrawTarget for updates.
|
||||
mPathContext = new CairoPathContext(aContext, aDrawTarget,
|
||||
mPathContext->GetFillRule(),
|
||||
mPathContext->GetTransform());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,10 +68,6 @@ public:
|
||||
// Returns true if this CairoPathContext represents path.
|
||||
bool ContainsPath(const Path* path);
|
||||
|
||||
// add ourselves as an observer of aDrawTarget, if possible
|
||||
// if we succeed, then mDrawTarget is set to aDrawTarget
|
||||
void ObserveTarget(DrawTargetCairo* aDrawTarget);
|
||||
|
||||
cairo_t* GetContext() const { return mContext; }
|
||||
DrawTargetCairo* GetDrawTarget() const { return mDrawTarget; }
|
||||
Matrix GetTransform() const { return mTransform; }
|
||||
|
@ -103,7 +103,6 @@ SourceSurfaceCairo::DrawTargetWillChange()
|
||||
cairo_set_source(ctx, pat);
|
||||
cairo_paint(ctx);
|
||||
cairo_destroy(ctx);
|
||||
cairo_pattern_destroy(pat);
|
||||
|
||||
// Swap in this new surface.
|
||||
cairo_surface_destroy(mSurface);
|
||||
|
@ -38,7 +38,7 @@ enum SurfaceFormat
|
||||
|
||||
enum BackendType
|
||||
{
|
||||
BACKEND_NONE = 0,
|
||||
BACKEND_NONE,
|
||||
BACKEND_DIRECT2D,
|
||||
BACKEND_COREGRAPHICS,
|
||||
BACKEND_CAIRO,
|
||||
|
@ -484,11 +484,8 @@ TemporaryRef<DrawTarget>
|
||||
LayerManagerD3D10::CreateDrawTarget(const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
BackendType backend;
|
||||
if ((aFormat != FORMAT_B8G8R8A8 &&
|
||||
aFormat != FORMAT_B8G8R8X8) ||
|
||||
!gfxPlatform::GetPlatform()->SupportsAzureCanvas(backend) ||
|
||||
backend != BACKEND_DIRECT2D) {
|
||||
aFormat != FORMAT_B8G8R8X8)) {
|
||||
return LayerManager::CreateDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,6 @@ CanvasLayerD3D9::Initialize(const Data& aData)
|
||||
|
||||
if (aData.mDrawTarget) {
|
||||
mDrawTarget = aData.mDrawTarget;
|
||||
mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
mNeedsYFlip = false;
|
||||
mDataIsPremultiplied = true;
|
||||
} else if (aData.mSurface) {
|
||||
@ -140,11 +139,18 @@ CanvasLayerD3D9::UpdateSurface()
|
||||
D3DLOCKED_RECT lockedRect = textureLock.GetLockRect();
|
||||
|
||||
nsRefPtr<gfxImageSurface> sourceSurface;
|
||||
nsRefPtr<gfxASurface> tempSurface;
|
||||
if (mDrawTarget) {
|
||||
tempSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
}
|
||||
else {
|
||||
tempSurface = mSurface;
|
||||
}
|
||||
|
||||
if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
|
||||
sourceSurface = mSurface->GetAsImageSurface();
|
||||
} else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
|
||||
if (tempSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
|
||||
sourceSurface = tempSurface->GetAsImageSurface();
|
||||
} else if (tempSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
sourceSurface = static_cast<gfxImageSurface*>(tempSurface.get());
|
||||
if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
|
||||
sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
@ -155,7 +161,7 @@ CanvasLayerD3D9::UpdateSurface()
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(mSurface);
|
||||
ctx->SetSource(tempSurface);
|
||||
ctx->Paint();
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,6 @@ CanvasLayerOGL::Initialize(const Data& aData)
|
||||
|
||||
if (aData.mDrawTarget) {
|
||||
mDrawTarget = aData.mDrawTarget;
|
||||
mCanvasSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
mNeedsYFlip = false;
|
||||
} else if (aData.mSurface) {
|
||||
mCanvasSurface = aData.mSurface;
|
||||
@ -163,7 +162,11 @@ CanvasLayerOGL::UpdateSurface()
|
||||
} else {
|
||||
nsRefPtr<gfxASurface> updatedAreaSurface;
|
||||
|
||||
if (mCanvasSurface) {
|
||||
if (mDrawTarget) {
|
||||
// TODO: This is suboptimal - We should have direct handling for the surface types instead of
|
||||
// going via a gfxASurface.
|
||||
updatedAreaSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
} else if (mCanvasSurface) {
|
||||
updatedAreaSurface = mCanvasSurface;
|
||||
} else if (mCanvasGLContext) {
|
||||
gfxIntSize size(mBounds.width, mBounds.height);
|
||||
@ -223,8 +226,13 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
||||
|
||||
drawRect.IntersectRect(drawRect, GetEffectiveVisibleRegion().GetBounds());
|
||||
|
||||
nsRefPtr<gfxASurface> surf = mCanvasSurface;
|
||||
if (mDrawTarget) {
|
||||
surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
|
||||
}
|
||||
|
||||
mLayerProgram =
|
||||
gl()->UploadSurfaceToTexture(mCanvasSurface,
|
||||
gl()->UploadSurfaceToTexture(surf,
|
||||
nsIntRect(0, 0, drawRect.width, drawRect.height),
|
||||
mTexture,
|
||||
true,
|
||||
|
@ -161,19 +161,16 @@ gfxAndroidPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
}
|
||||
|
||||
RefPtr<ScaledFont>
|
||||
gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
|
||||
gfxAndroidPlatform::GetScaledFontForFont(gfxFont *aFont)
|
||||
{
|
||||
NativeFont nativeFont;
|
||||
if (aTarget->GetType() == BACKEND_CAIRO) {
|
||||
nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
|
||||
nativeFont.mFont = NULL;
|
||||
return Factory::CreateScaledFontWithCairo(nativeFont, aFont->GetAdjustedSize(), aFont->GetCairoScaledFont());
|
||||
}
|
||||
|
||||
NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
|
||||
NativeFont nativeFont;
|
||||
nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
|
||||
nativeFont.mFont = static_cast<gfxFT2FontBase*>(aFont)->GetFontOptions();
|
||||
return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
|
||||
|
||||
return scaledFont;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -33,10 +33,12 @@ public:
|
||||
CreateOffscreenSurface(const gfxIntSize& size,
|
||||
gfxASurface::gfxContentType contentType);
|
||||
|
||||
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { aBackend = mozilla::gfx::BACKEND_SKIA; return true; }
|
||||
|
||||
virtual gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
|
||||
|
||||
mozilla::RefPtr<mozilla::gfx::ScaledFont>
|
||||
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
|
||||
GetScaledFontForFont(gfxFont *aFont);
|
||||
|
||||
// to support IPC font list (sharing between chrome and content)
|
||||
void GetFontList(InfallibleTArray<FontListEntry>* retValue);
|
||||
|
@ -1783,7 +1783,7 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
|
||||
} else {
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
gfxPlatform::GetPlatform()->GetScaledFontForFont(dt, this);
|
||||
gfxPlatform::GetPlatform()->GetScaledFontForFont(this);
|
||||
|
||||
if (!scaledFont) {
|
||||
return;
|
||||
|
@ -1547,8 +1547,7 @@ public:
|
||||
FONT_TYPE_GDI,
|
||||
FONT_TYPE_FT2,
|
||||
FONT_TYPE_MAC,
|
||||
FONT_TYPE_OS2,
|
||||
FONT_TYPE_CAIRO
|
||||
FONT_TYPE_OS2
|
||||
} FontType;
|
||||
|
||||
virtual FontType GetType() const = 0;
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsUnicharUtilCIID.h"
|
||||
#include "nsILocaleService.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
@ -76,7 +75,6 @@ using namespace mozilla::layers;
|
||||
|
||||
gfxPlatform *gPlatform = nsnull;
|
||||
static bool gEverInitialized = false;
|
||||
static nsTArray<nsCString>* gBackendList = nsnull;
|
||||
|
||||
// These two may point to the same profile
|
||||
static qcms_profile *gCMSOutputProfile = nsnull;
|
||||
@ -213,7 +211,7 @@ static const char *gPrefLangNames[] = {
|
||||
};
|
||||
|
||||
gfxPlatform::gfxPlatform()
|
||||
: mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureCanvasBackendInfo)
|
||||
: mAzureBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
|
||||
{
|
||||
mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
|
||||
mAllowDownloadableFonts = UNINITIALIZED_VALUE;
|
||||
@ -225,8 +223,11 @@ gfxPlatform::gfxPlatform()
|
||||
#endif
|
||||
mBidiNumeralOption = UNINITIALIZED_VALUE;
|
||||
|
||||
PRUint32 backendMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA);
|
||||
InitCanvasBackend(backendMask);
|
||||
if (Preferences::GetBool("gfx.canvas.azure.prefer-skia", false)) {
|
||||
mPreferredDrawTargetBackend = BACKEND_SKIA;
|
||||
} else {
|
||||
mPreferredDrawTargetBackend = BACKEND_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
gfxPlatform*
|
||||
@ -406,9 +407,6 @@ gfxPlatform::Shutdown()
|
||||
|
||||
CompositorParent::ShutDown();
|
||||
|
||||
delete gBackendList;
|
||||
gBackendList = nsnull;
|
||||
|
||||
delete gPlatform;
|
||||
gPlatform = nsnull;
|
||||
}
|
||||
@ -475,9 +473,9 @@ gfxPlatform::OptimizeImage(gfxImageSurface *aSurface,
|
||||
cairo_user_data_key_t kDrawTarget;
|
||||
|
||||
RefPtr<DrawTarget>
|
||||
gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aSize)
|
||||
gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface)
|
||||
{
|
||||
RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize);
|
||||
RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface());
|
||||
aSurface->SetData(&kDrawTarget, drawTarget, NULL);
|
||||
return drawTarget;
|
||||
}
|
||||
@ -534,8 +532,11 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
|
||||
if (!srcBuffer) {
|
||||
nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
|
||||
|
||||
bool isWin32ImageSurf = imgSurface &&
|
||||
aSurface->GetType() == gfxASurface::SurfaceTypeWin32;
|
||||
bool isWin32ImageSurf = false;
|
||||
|
||||
if (imgSurface && aSurface->GetType() != gfxASurface::SurfaceTypeWin32) {
|
||||
isWin32ImageSurf = true;
|
||||
}
|
||||
|
||||
if (!imgSurface) {
|
||||
imgSurface = new gfxImageSurface(aSurface->GetSize(), OptimalFormatForContent(aSurface->GetContentType()));
|
||||
@ -571,8 +572,8 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
|
||||
|
||||
if (!srcBuffer) {
|
||||
// We need to check if our gfxASurface will keep the underlying data
|
||||
// alive. This is true if gfxASurface actually -is- an ImageSurface or
|
||||
// if it is a gfxWindowsSurface which supports GetAsImageSurface.
|
||||
// alive! This is true if gfxASurface actually -is- an ImageSurface or
|
||||
// if it is a gfxWindowsSurface which supportes GetAsImageSurface.
|
||||
if (imgSurface != aSurface && !isWin32ImageSurf) {
|
||||
// This shouldn't happen for now, it can be easily supported by making
|
||||
// a copy. For now let's just abort.
|
||||
@ -604,73 +605,77 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
|
||||
}
|
||||
|
||||
RefPtr<ScaledFont>
|
||||
gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
|
||||
gfxPlatform::GetScaledFontForFont(gfxFont *aFont)
|
||||
{
|
||||
NativeFont nativeFont;
|
||||
nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
|
||||
nativeFont.mFont = aFont->GetCairoScaledFont();
|
||||
nativeFont.mFont = aFont;
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
Factory::CreateScaledFontForNativeFont(nativeFont,
|
||||
aFont->GetAdjustedSize());
|
||||
return scaledFont;
|
||||
}
|
||||
|
||||
cairo_user_data_key_t kDrawSourceSurface;
|
||||
static void
|
||||
DataSourceSurfaceDestroy(void *dataSourceSurface)
|
||||
UserDataKey kThebesSurfaceKey;
|
||||
void
|
||||
DestroyThebesSurface(void *data)
|
||||
{
|
||||
static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
|
||||
}
|
||||
|
||||
cairo_user_data_key_t kDrawTargetForSurface;
|
||||
static void
|
||||
DataDrawTargetDestroy(void *aTarget)
|
||||
{
|
||||
static_cast<DrawTarget*>(aTarget)->Release();
|
||||
gfxASurface *surface = static_cast<gfxASurface*>(data);
|
||||
surface->Release();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
|
||||
{
|
||||
// If we have already created a thebes surface, we can just return it.
|
||||
void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
|
||||
if (surface) {
|
||||
nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
|
||||
return surf.forget();
|
||||
}
|
||||
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
if (aTarget->GetType() == BACKEND_CAIRO) {
|
||||
cairo_surface_t* csurf =
|
||||
static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
|
||||
return gfxASurface::Wrap(csurf);
|
||||
surf = gfxASurface::Wrap(csurf);
|
||||
} else {
|
||||
// The semantics of this part of the function are sort of weird. If we
|
||||
// don't have direct support for the backend, we snapshot the first time
|
||||
// and then return the snapshotted surface for the lifetime of the draw
|
||||
// target. Sometimes it seems like this works out, but it seems like it
|
||||
// might result in no updates ever.
|
||||
RefPtr<SourceSurface> source = aTarget->Snapshot();
|
||||
RefPtr<DataSourceSurface> data = source->GetDataSurface();
|
||||
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IntSize size = data->GetSize();
|
||||
gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
|
||||
|
||||
// We need to make a copy here because data might change its data under us
|
||||
nsRefPtr<gfxImageSurface> imageSurf = new gfxImageSurface(gfxIntSize(size.width, size.height), format, false);
|
||||
|
||||
bool resultOfCopy = imageSurf->CopyFrom(source);
|
||||
NS_ASSERTION(resultOfCopy, "Failed to copy surface.");
|
||||
surf = imageSurf;
|
||||
}
|
||||
|
||||
// The semantics of this part of the function are sort of weird. If we
|
||||
// don't have direct support for the backend, we snapshot the first time
|
||||
// and then return the snapshotted surface for the lifetime of the draw
|
||||
// target. Sometimes it seems like this works out, but it seems like it
|
||||
// might result in no updates ever.
|
||||
RefPtr<SourceSurface> source = aTarget->Snapshot();
|
||||
RefPtr<DataSourceSurface> data = source->GetDataSurface();
|
||||
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IntSize size = data->GetSize();
|
||||
gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
|
||||
|
||||
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxImageSurface(data->GetData(), gfxIntSize(size.width, size.height),
|
||||
data->Stride(), format);
|
||||
|
||||
surf->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
|
||||
// keep the draw target alive as long as we need its data
|
||||
aTarget->AddRef();
|
||||
surf->SetData(&kDrawTargetForSurface, aTarget, DataDrawTargetDestroy);
|
||||
// add a reference to be held by the drawTarget
|
||||
// careful, the reference graph is getting complicated here
|
||||
surf->AddRef();
|
||||
aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
|
||||
|
||||
return surf.forget();
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget>
|
||||
gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
|
||||
gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
|
||||
{
|
||||
BackendType backend;
|
||||
if (!SupportsAzureCanvas(backend)) {
|
||||
if (!SupportsAzure(backend)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -682,70 +687,26 @@ gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSi
|
||||
// now, but this might need to change in the future (using
|
||||
// CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
|
||||
// backends).
|
||||
if (aBackend == BACKEND_CAIRO) {
|
||||
if (backend == BACKEND_CAIRO) {
|
||||
nsRefPtr<gfxASurface> surf = CreateOffscreenSurface(ThebesIntSize(aSize),
|
||||
ContentForFormat(aFormat));
|
||||
if (!surf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return CreateDrawTargetForSurface(surf, aSize);
|
||||
return CreateDrawTargetForSurface(surf);
|
||||
} else {
|
||||
return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
|
||||
return Factory::CreateDrawTarget(backend, aSize, aFormat);
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget>
|
||||
gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
|
||||
{
|
||||
BackendType backend;
|
||||
if (!SupportsAzureCanvas(backend)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> target = CreateDrawTargetForBackend(backend, aSize, aFormat);
|
||||
if (target ||
|
||||
mFallbackCanvasBackend == BACKEND_NONE) {
|
||||
return target;
|
||||
}
|
||||
|
||||
return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat);
|
||||
}
|
||||
|
||||
|
||||
RefPtr<DrawTarget>
|
||||
gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
|
||||
{
|
||||
BackendType backend;
|
||||
if (!SupportsAzureCanvas(backend)) {
|
||||
if (!SupportsAzure(backend)) {
|
||||
return NULL;
|
||||
}
|
||||
return Factory::CreateDrawTargetForData(backend, aData, aSize, aStride, aFormat);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::SupportsAzureCanvas(BackendType& aBackend)
|
||||
{
|
||||
NS_ASSERTION(mFallbackCanvasBackend == BACKEND_NONE || mPreferredCanvasBackend != BACKEND_NONE,
|
||||
"fallback backend with no preferred backend");
|
||||
aBackend = mPreferredCanvasBackend;
|
||||
return mPreferredCanvasBackend != BACKEND_NONE;
|
||||
}
|
||||
|
||||
/* static */ BackendType
|
||||
gfxPlatform::BackendTypeForName(const nsCString& aName)
|
||||
{
|
||||
if (aName.EqualsLiteral("cairo"))
|
||||
return BACKEND_CAIRO;
|
||||
if (aName.EqualsLiteral("skia"))
|
||||
return BACKEND_SKIA;
|
||||
if (aName.EqualsLiteral("direct2d"))
|
||||
return BACKEND_DIRECT2D;
|
||||
if (aName.EqualsLiteral("cg"))
|
||||
return BACKEND_COREGRAPHICS;
|
||||
return BACKEND_NONE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxPlatform::GetFontList(nsIAtom *aLangGroup,
|
||||
const nsACString& aGenericFamily,
|
||||
@ -1166,53 +1127,20 @@ gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs[], PRUint32& aLen, eFontPre
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatform::InitCanvasBackend(PRUint32 aBackendBitmask)
|
||||
{
|
||||
if (!Preferences::GetBool("gfx.canvas.azure.enabled", false)) {
|
||||
mPreferredCanvasBackend = BACKEND_NONE;
|
||||
mFallbackCanvasBackend = BACKEND_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
mPreferredCanvasBackend = GetCanvasBackendPref(aBackendBitmask);
|
||||
mFallbackCanvasBackend = GetCanvasBackendPref(aBackendBitmask & ~(1 << mPreferredCanvasBackend));
|
||||
}
|
||||
|
||||
/* static */ BackendType
|
||||
gfxPlatform::GetCanvasBackendPref(PRUint32 aBackendBitmask)
|
||||
{
|
||||
if (!gBackendList) {
|
||||
gBackendList = new nsTArray<nsCString>();
|
||||
nsCString prefString;
|
||||
if (NS_SUCCEEDED(Preferences::GetCString("gfx.canvas.azure.backends", &prefString))) {
|
||||
ParseString(prefString, ',', *gBackendList);
|
||||
}
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < gBackendList->Length(); ++i) {
|
||||
BackendType result = BackendTypeForName((*gBackendList)[i]);
|
||||
if ((1 << result) & aBackendBitmask) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return BACKEND_NONE;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::UseProgressiveTilePainting()
|
||||
{
|
||||
static bool sUseProgressiveTilePainting;
|
||||
static bool sUseProgressiveTilePaintingPrefCached = false;
|
||||
static bool sUseProgressiveTilePainting;
|
||||
static bool sUseProgressiveTilePaintingPrefCached = false;
|
||||
|
||||
if (!sUseProgressiveTilePaintingPrefCached) {
|
||||
sUseProgressiveTilePaintingPrefCached = true;
|
||||
mozilla::Preferences::AddBoolVarCache(&sUseProgressiveTilePainting,
|
||||
"layers.progressive-paint",
|
||||
false);
|
||||
}
|
||||
if (!sUseProgressiveTilePaintingPrefCached) {
|
||||
sUseProgressiveTilePaintingPrefCached = true;
|
||||
mozilla::Preferences::AddBoolVarCache(&sUseProgressiveTilePainting,
|
||||
"layers.progressive-paint",
|
||||
false);
|
||||
}
|
||||
|
||||
return sUseProgressiveTilePainting;
|
||||
return sUseProgressiveTilePainting;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -38,6 +38,9 @@ class gfxTextRun;
|
||||
class nsIURI;
|
||||
class nsIAtom;
|
||||
|
||||
extern mozilla::gfx::UserDataKey kThebesSurfaceKey;
|
||||
void DestroyThebesSurface(void *data);
|
||||
|
||||
extern cairo_user_data_key_t kDrawTarget;
|
||||
|
||||
// pref lang id's for font prefs
|
||||
@ -127,7 +130,7 @@ GetBackendName(mozilla::gfx::BackendType aBackend)
|
||||
case mozilla::gfx::BACKEND_NONE:
|
||||
return "none";
|
||||
}
|
||||
MOZ_NOT_REACHED("Incomplete switch");
|
||||
MOZ_NOT_REACHED("Incomplet switch");
|
||||
}
|
||||
|
||||
class THEBES_API gfxPlatform {
|
||||
@ -169,21 +172,18 @@ public:
|
||||
gfxASurface::gfxImageFormat format);
|
||||
|
||||
virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
|
||||
CreateDrawTargetForSurface(gfxASurface *aSurface, const mozilla::gfx::IntSize& aSize);
|
||||
CreateDrawTargetForSurface(gfxASurface *aSurface);
|
||||
|
||||
/*
|
||||
* Creates a SourceSurface for a gfxASurface. This function does no caching,
|
||||
* so the caller should cache the gfxASurface if it will be used frequently.
|
||||
* The returned surface keeps a reference to aTarget, so it is OK to keep the
|
||||
* surface, even if aTarget changes.
|
||||
* aTarget should not keep a reference to the returned surface because that
|
||||
* will cause a cycle.
|
||||
* Creates a SourceSurface for a gfxASurface. This surface should -not- be
|
||||
* held around by the user after the underlying gfxASurface has been
|
||||
* destroyed as a copy of the data is not guaranteed.
|
||||
*/
|
||||
virtual mozilla::RefPtr<mozilla::gfx::SourceSurface>
|
||||
GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface);
|
||||
|
||||
virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
|
||||
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
|
||||
GetScaledFontForFont(gfxFont *aFont);
|
||||
|
||||
virtual already_AddRefed<gfxASurface>
|
||||
GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
|
||||
@ -195,12 +195,13 @@ public:
|
||||
CreateDrawTargetForData(unsigned char* aData, const mozilla::gfx::IntSize& aSize,
|
||||
int32_t aStride, mozilla::gfx::SurfaceFormat aFormat);
|
||||
|
||||
// aBackend will be set to the preferred backend for Azure canvas
|
||||
bool SupportsAzureCanvas(mozilla::gfx::BackendType& aBackend);
|
||||
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { return false; }
|
||||
|
||||
// aObj will contain the preferred backend for Azure canvas
|
||||
void GetAzureCanvasBackendInfo(mozilla::widget::InfoObject &aObj) {
|
||||
aObj.DefineProperty("AzureBackend", GetBackendName(mPreferredCanvasBackend));
|
||||
void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) {
|
||||
mozilla::gfx::BackendType backend;
|
||||
if (SupportsAzure(backend)) {
|
||||
aObj.DefineProperty("AzureBackend", GetBackendName(backend));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -454,30 +455,7 @@ protected:
|
||||
|
||||
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen,
|
||||
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
|
||||
|
||||
/**
|
||||
* Helper method, creates a draw target for a specific Azure backend.
|
||||
* Used by CreateOffscreenDrawTarget.
|
||||
*/
|
||||
mozilla::RefPtr<mozilla::gfx::DrawTarget>
|
||||
CreateDrawTargetForBackend(mozilla::gfx::BackendType aBackend,
|
||||
const mozilla::gfx::IntSize& aSize,
|
||||
mozilla::gfx::SurfaceFormat aFormat);
|
||||
|
||||
/**
|
||||
* Initialise the preferred and fallback canvas backends
|
||||
* aBackendBitmask specifies the backends which are acceptable to the caller.
|
||||
* The backend used is determined by aBackendBitmask and the order specified
|
||||
* by the gfx.canvas.azure.backends pref.
|
||||
*/
|
||||
void InitCanvasBackend(PRUint32 aBackendBitmask);
|
||||
/**
|
||||
* returns the first backend named in the pref gfx.canvas.azure.backends
|
||||
* which is a component of aBackendBitmask, a bitmask of backend types
|
||||
*/
|
||||
static mozilla::gfx::BackendType GetCanvasBackendPref(PRUint32 aBackendBitmask);
|
||||
static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName);
|
||||
|
||||
|
||||
PRInt8 mAllowDownloadableFonts;
|
||||
PRInt8 mDownloadableFontsSanitize;
|
||||
#ifdef MOZ_GRAPHITE
|
||||
@ -493,6 +471,9 @@ protected:
|
||||
// which scripts should be shaped with harfbuzz
|
||||
PRInt32 mUseHarfBuzzScripts;
|
||||
|
||||
// The preferred draw target backend to use
|
||||
mozilla::gfx::BackendType mPreferredDrawTargetBackend;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Start up Thebes.
|
||||
@ -505,13 +486,7 @@ private:
|
||||
nsTArray<PRUint32> mCJKPrefLangs;
|
||||
nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
|
||||
nsCOMPtr<nsIObserver> mFontPrefsObserver;
|
||||
|
||||
// The preferred draw target backend to use for canvas
|
||||
mozilla::gfx::BackendType mPreferredCanvasBackend;
|
||||
// The fallback draw target backend to use for canvas, if the preferred backend fails
|
||||
mozilla::gfx::BackendType mFallbackCanvasBackend;
|
||||
|
||||
mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureCanvasBackendCollector;
|
||||
mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureBackendCollector;
|
||||
bool mWorkAroundDriverBugs;
|
||||
};
|
||||
|
||||
|
@ -730,16 +730,22 @@ gfxPlatformGtk::GetGdkDrawable(gfxASurface *target)
|
||||
#endif
|
||||
|
||||
RefPtr<ScaledFont>
|
||||
gfxPlatformGtk::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
|
||||
gfxPlatformGtk::GetScaledFontForFont(gfxFont *aFont)
|
||||
{
|
||||
NativeFont nativeFont;
|
||||
if (aTarget->GetType() == BACKEND_CAIRO) {
|
||||
nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
|
||||
nativeFont.mFont = NULL;
|
||||
return Factory::CreateScaledFontWithCairo(nativeFont, aFont->GetAdjustedSize(), aFont->GetCairoScaledFont());
|
||||
}
|
||||
NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
|
||||
NativeFont nativeFont;
|
||||
nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
|
||||
nativeFont.mFont = static_cast<gfxFT2FontBase*>(aFont)->GetFontOptions();
|
||||
return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
|
||||
|
||||
return scaledFont;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatformGtk::SupportsAzure(BackendType& aBackend)
|
||||
{
|
||||
aBackend = BACKEND_SKIA;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,9 @@ public:
|
||||
gfxASurface::gfxContentType contentType);
|
||||
|
||||
mozilla::RefPtr<mozilla::gfx::ScaledFont>
|
||||
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
|
||||
GetScaledFontForFont(gfxFont *aFont);
|
||||
|
||||
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
|
||||
|
||||
nsresult GetFontList(nsIAtom *aLangGroup,
|
||||
const nsACString& aGenericFamily,
|
||||
|
@ -69,9 +69,6 @@ gfxPlatformMac::gfxPlatformMac()
|
||||
DisableFontActivation();
|
||||
}
|
||||
mFontAntiAliasingThreshold = ReadAntiAliasingThreshold();
|
||||
|
||||
PRUint32 backendMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA) | (1 << BACKEND_COREGRAPHICS);
|
||||
InitCanvasBackend(backendMask);
|
||||
}
|
||||
|
||||
gfxPlatformMac::~gfxPlatformMac()
|
||||
@ -136,12 +133,24 @@ gfxPlatformMac::OptimizeImage(gfxImageSurface *aSurface,
|
||||
}
|
||||
|
||||
RefPtr<ScaledFont>
|
||||
gfxPlatformMac::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
|
||||
gfxPlatformMac::GetScaledFontForFont(gfxFont *aFont)
|
||||
{
|
||||
gfxMacFont *font = static_cast<gfxMacFont*>(aFont);
|
||||
return font->GetScaledFont();
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatformMac::SupportsAzure(BackendType& aBackend)
|
||||
{
|
||||
if (mPreferredDrawTargetBackend != BACKEND_NONE) {
|
||||
aBackend = mPreferredDrawTargetBackend;
|
||||
} else {
|
||||
aBackend = BACKEND_COREGRAPHICS;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxPlatformMac::ResolveFontName(const nsAString& aFontName,
|
||||
FontResolverCallback aCallback,
|
||||
@ -380,16 +389,26 @@ already_AddRefed<gfxASurface>
|
||||
gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
|
||||
{
|
||||
if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
|
||||
CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
|
||||
void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
|
||||
if (surface) {
|
||||
nsRefPtr<gfxASurface> surf = static_cast<gfxQuartzSurface*>(surface);
|
||||
return surf.forget();
|
||||
} else {
|
||||
CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
|
||||
|
||||
//XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
|
||||
IntSize intSize = aTarget->GetSize();
|
||||
gfxIntSize size(intSize.width, intSize.height);
|
||||
//XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
|
||||
IntSize intSize = aTarget->GetSize();
|
||||
gfxIntSize size(intSize.width, intSize.height);
|
||||
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxQuartzSurface(cg, size);
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxQuartzSurface(cg, size);
|
||||
|
||||
return surf.forget();
|
||||
// add a reference to be held by the drawTarget
|
||||
surf->AddRef();
|
||||
aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
|
||||
|
||||
return surf.forget();
|
||||
}
|
||||
}
|
||||
|
||||
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
|
||||
|
@ -39,7 +39,9 @@ public:
|
||||
gfxASurface::gfxImageFormat format);
|
||||
|
||||
mozilla::RefPtr<mozilla::gfx::ScaledFont>
|
||||
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
|
||||
GetScaledFontForFont(gfxFont *aFont);
|
||||
|
||||
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
|
||||
|
||||
nsresult ResolveFontName(const nsAString& aFontName,
|
||||
FontResolverCallback aCallback,
|
||||
|
@ -606,3 +606,10 @@ gfxQtPlatform::GetOffscreenFormat()
|
||||
return sOffscreenFormat;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxQtPlatform::SupportsAzure(BackendType& aBackend)
|
||||
{
|
||||
aBackend = BACKEND_SKIA;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,8 @@ public:
|
||||
already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
|
||||
gfxASurface::gfxContentType contentType);
|
||||
|
||||
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
|
||||
|
||||
nsresult GetFontList(nsIAtom *aLangGroup,
|
||||
const nsACString& aGenericFamily,
|
||||
nsTArray<nsString>& aListOfFonts);
|
||||
|
@ -515,14 +515,6 @@ gfxWindowsPlatform::UpdateRenderMode()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PRUint32 backendMask = 1 << BACKEND_CAIRO;
|
||||
if (mRenderMode == RENDER_DIRECT2D) {
|
||||
backendMask |= 1 << BACKEND_DIRECT2D;
|
||||
} else {
|
||||
backendMask |= 1 << BACKEND_SKIA;
|
||||
}
|
||||
InitCanvasBackend(backendMask);
|
||||
}
|
||||
|
||||
void
|
||||
@ -772,7 +764,7 @@ gfxWindowsPlatform::CreateOffscreenImageSurface(const gfxIntSize& aSize,
|
||||
}
|
||||
|
||||
RefPtr<ScaledFont>
|
||||
gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
|
||||
gfxWindowsPlatform::GetScaledFontForFont(gfxFont *aFont)
|
||||
{
|
||||
if (aFont->GetType() == gfxFont::FONT_TYPE_DWRITE) {
|
||||
gfxDWriteFont *font = static_cast<gfxDWriteFont*>(aFont);
|
||||
@ -794,14 +786,10 @@ gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
|
||||
LOGFONT lf;
|
||||
GetObject(static_cast<gfxGDIFont*>(aFont)->GetHFONT(), sizeof(LOGFONT), &lf);
|
||||
nativeFont.mFont = &lf;
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
|
||||
|
||||
if (aTarget->GetType() == BACKEND_CAIRO) {
|
||||
return Factory::CreateScaledFontWithCairo(nativeFont,
|
||||
aFont->GetAdjustedSize(),
|
||||
aFont->GetCairoScaledFont());
|
||||
}
|
||||
|
||||
return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
|
||||
return scaledFont;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
@ -809,32 +797,64 @@ gfxWindowsPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
if (aTarget->GetType() == BACKEND_DIRECT2D) {
|
||||
if (!GetD2DDevice()) {
|
||||
// We no longer have a D2D device, can't do this.
|
||||
return NULL;
|
||||
void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
|
||||
if (surface) {
|
||||
nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
|
||||
return surf.forget();
|
||||
} else {
|
||||
if (!GetD2DDevice()) {
|
||||
// We no longer have a D2D device, can't do this.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RefPtr<ID3D10Texture2D> texture =
|
||||
static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
|
||||
|
||||
if (!texture) {
|
||||
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
|
||||
}
|
||||
|
||||
aTarget->Flush();
|
||||
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
|
||||
|
||||
// add a reference to be held by the drawTarget
|
||||
surf->AddRef();
|
||||
aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
|
||||
/* "It might be worth it to clear cairo surfaces associated with a drawtarget.
|
||||
The strong reference means for example for D2D that cairo's scratch surface
|
||||
will be kept alive (well after a user being done) and consume extra VRAM.
|
||||
We can deal with this in a follow-up though." */
|
||||
|
||||
// shouldn't this hold a reference?
|
||||
surf->SetData(&kDrawTarget, aTarget, NULL);
|
||||
return surf.forget();
|
||||
}
|
||||
|
||||
RefPtr<ID3D10Texture2D> texture =
|
||||
static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
|
||||
|
||||
if (!texture) {
|
||||
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
|
||||
}
|
||||
|
||||
aTarget->Flush();
|
||||
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
|
||||
|
||||
// shouldn't this hold a reference?
|
||||
surf->SetData(&kDrawTarget, aTarget, NULL);
|
||||
return surf.forget();
|
||||
}
|
||||
#endif
|
||||
|
||||
return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::SupportsAzure(BackendType& aBackend)
|
||||
{
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
if (mRenderMode == RENDER_DIRECT2D) {
|
||||
aBackend = BACKEND_DIRECT2D;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mPreferredDrawTargetBackend != BACKEND_NONE) {
|
||||
aBackend = mPreferredDrawTargetBackend;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxWindowsPlatform::GetFontList(nsIAtom *aLangGroup,
|
||||
const nsACString& aGenericFamily,
|
||||
|
@ -108,9 +108,11 @@ public:
|
||||
gfxASurface::gfxContentType aContentType);
|
||||
|
||||
virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
|
||||
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
|
||||
GetScaledFontForFont(gfxFont *aFont);
|
||||
virtual already_AddRefed<gfxASurface>
|
||||
GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
|
||||
|
||||
virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
|
||||
|
||||
enum RenderMode {
|
||||
/* Use GDI and windows surfaces */
|
||||
|
@ -225,17 +225,10 @@ pref("gfx.font_rendering.directwrite.use_gdi_table_loading", true);
|
||||
|
||||
#ifdef XP_WIN
|
||||
pref("gfx.canvas.azure.enabled", true);
|
||||
// comma separated list of backends to use in order of preference
|
||||
// e.g., pref("gfx.canvas.azure.backends", "direct2d,skia,cairo");
|
||||
pref("gfx.canvas.azure.backends", "direct2d");
|
||||
pref("gfx.content.azure.enabled", true);
|
||||
#else
|
||||
#ifdef XP_MACOSX
|
||||
pref("gfx.canvas.azure.enabled", true);
|
||||
pref("gfx.canvas.azure.backends", "cg");
|
||||
#else
|
||||
pref("gfx.canvas.azure.enabled", false);
|
||||
pref("gfx.canvas.azure.backends", "cairo,skia");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -43,6 +43,12 @@ GfxInfo::GetDWriteEnabled(bool *aEnabled)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GfxInfo::GetAzureEnabled(bool *aEnabled)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* readonly attribute DOMString DWriteVersion; */
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
// rest is brought forward from GfxInfoBase.
|
||||
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
|
||||
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
|
||||
NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
|
||||
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
|
||||
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
|
||||
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
|
||||
|
@ -24,6 +24,7 @@ public:
|
||||
// rest is brought forward from GfxInfoBase.
|
||||
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
|
||||
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
|
||||
NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
|
||||
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
|
||||
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
|
||||
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
|
||||
|
@ -154,6 +154,20 @@ GfxInfo::GetD2DEnabled(bool *aEnabled)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAzureEnabled(bool *aEnabled)
|
||||
{
|
||||
bool azure = false;
|
||||
nsresult rv = mozilla::Preferences::GetBool("gfx.canvas.azure.enabled", &azure);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && azure) {
|
||||
*aEnabled = true;
|
||||
} else {
|
||||
*aEnabled = false;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDWriteEnabled(bool *aEnabled)
|
||||
{
|
||||
|
@ -16,6 +16,7 @@ interface nsIGfxInfo : nsISupports
|
||||
*/
|
||||
readonly attribute boolean D2DEnabled;
|
||||
readonly attribute boolean DWriteEnabled;
|
||||
readonly attribute boolean AzureEnabled;
|
||||
readonly attribute DOMString DWriteVersion;
|
||||
readonly attribute DOMString cleartypeParameters;
|
||||
|
||||
|
@ -59,6 +59,26 @@ GfxInfo::GetDWriteEnabled(bool *aEnabled)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GfxInfo::GetAzureEnabled(bool *aEnabled)
|
||||
{
|
||||
*aEnabled = false;
|
||||
|
||||
bool d2dEnabled =
|
||||
gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
|
||||
|
||||
if (d2dEnabled) {
|
||||
bool azure = false;
|
||||
nsresult rv = mozilla::Preferences::GetBool("gfx.canvas.azure.enabled", &azure);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && azure) {
|
||||
*aEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute DOMString DWriteVersion; */
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
// rest is brought forward from GfxInfoBase.
|
||||
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
|
||||
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
|
||||
NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
|
||||
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
|
||||
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
|
||||
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
|
||||
|
@ -61,7 +61,7 @@ GetRenderingContext(nsIDocShell *shell, gfxASurface *surface,
|
||||
|
||||
if (!ctx) {
|
||||
// create the canvas rendering context
|
||||
ctx = do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=2d", &rv);
|
||||
ctx = do_CreateInstance("@mozilla.org/content/2dthebes-canvas-rendering-context;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Could not create nsICanvasRenderingContext2D for tab previews!");
|
||||
return rv;
|
||||
|
@ -370,6 +370,12 @@ GfxInfo::GetDWriteEnabled(bool *aEnabled)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetAzureEnabled(bool *aEnabled)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* readonly attribute DOMString DWriteVersion; */
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
|
||||
|
@ -21,6 +21,7 @@ public:
|
||||
// rest is brought forward from GfxInfoBase.
|
||||
NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
|
||||
NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
|
||||
NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
|
||||
NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
|
||||
NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
|
||||
NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
|
||||
|
Loading…
Reference in New Issue
Block a user