import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1149728. Move CreateXForOffscreen functions. r=jrmuizel (87d69e4b7c)
- missing part of Bug 1179280. Update ANGLE (ee6228fa90)
- missing bit of Bug 1191042 - Use CreateOffscreen for WebGL instead of CreateHeadless. - r=jrmuizel (87c26edf2c)
- add back XP bits (f198a909bd)
- put back SQLITE_ENABLE_DBSTAT_VTAB checks (a06fd5b7a9)
- Bug 1197387 - Use glXGetProcAddress to link against GLX_ARB_create_context_robustness. r=jgilbert (651b85207d)
- add back feature report (a0a33bb8e5)
- Bug 1209022 - Fix AA handling in EGL's CreateOffscreen. - r=jrmuizel (64d4e0f65a)
- Bug 1171228 - Expose WEBGL_debug_renderer_info to web content on non-RELEASE_BUILDs. - r=kamidphish, sr=jst (e7405ef944)
- Bug 1175257 - Remove the fails-if(B2G) annotation on capturestream.html. (80bf24c623)
- Bug 1177726 - Inflate the bounds when stroking the canvas text. r=jmuizelaar (15969cb828)
- Bug 1183363 - Make EnsureWritablePath and EnsureUserSpacePath always imply EnsureTarget. r=Basimply EnsureTarget. r=Bas (12d825cf30)
- Bug 1183363 - Add canvas crashtest. r=Bas (69b6099607)
- Bug 1186689 - check for OOM on destination array before mapping source to avoid needing unmap. r=bas (7a3ed105d6)
- Bug 1206161 - Make sure the DrawTarget is available when creating a CanvasLayer so that we can check for SkiaGL. r=Bas (fdf15fd552)
- Bug 232227 - Do not expose system colors to CSS or canvas. r=jmuizelaar r=enndeakin tor-r=arthuredelstein (dfd6f07fd8)
- Bug 1209206 (part 1) - Remove mgfx namespace synonym. (5916056863)
- Bug 1209206 (part 2) - Rename and re-comment HasNonOpaqueColor(). r=jdaggett. (768a0d549b)
- Bug 1209206 (part 3) - Use sinf() and cosf() instead of sin() and cos() in a couple of places. r=Bas. (7af9ebaa7f)
- No bug - Remove outdated comment and additional comment questioning its relevance. r=me DONTBUILD (6f7eca8452)
- Bug 1145934 - Update obsolete glyph-run assertion. r=jdaggett (ce2442e64b)
- Bug 1182361 p1 - move old generic lookup methods into gfxPangoFontGroup. r=heycam (ef39e6fd52)
- Bug 1182361 p2 - count generic lookups. r=heycam (53050ad6e8)
- bug 1180010 make some methods protected and non-virtual r=jdaggett (815e503481)
- Bug 1165179 - use all style matched faces within a font family. r=heycam (d2711db48b)
- Bug 1182361 p3 - move generic lookup methods to platform fontlist. r=heycam (63b974a000)
- Bug 1182361 p4 - move pref font util methods to platform fontlist. r=heycam (23d7352442)
- Bug 1182361 p5 - cache pref fonts per langGroup. r=heycam (c4244432cb)
- Bug 1182361 p6 - eliminate old pref font caching. r=heycam (c5293f0b8d)
- Bug 1182361 p7 - fixups based on review comments. r=heycam (51a2204179)
- Bug 1170688 - Move initialization of text-run parameters until *after* the draw target has been updated; r=jfkthame (e523ff6e96)
- Bug 1157629 - Fix uninitialized member warning in BufferAlphaColor. r=jdaggett (a564effd24)
- Bug 1184282 - Remove break suggested inside cluster warning. r=roc (54da46a09f)
- Bug 1197650 - remove duplicate validity check for newly created fonts. r=m_kato (5ffb28a313)
- Bug 1171357 - log font matching for textruns. r=m_kato (2354cd36f6)
- Bug 1185812 - rejigger the ordering of fonts within a family to avoid obscure faces. r=heycam (0518f4ef64)
- Bug 1167697 - Mark refs to gfxFontEntry in UserFontCache as MOZ_NON_OWNING_REF. r=jtd (1fdcccdac2)
- bits of Bug 1073209 - Eliminate usage of CreateSamplingRestrictedDrawable (9058557527)
- and sync gfx/gl to same state as af-frontend branch
This commit is contained in:
2022-10-03 09:47:32 +08:00
parent 1406b5eef9
commit d041f9bde0
64 changed files with 2357 additions and 1529 deletions
+29
View File
@@ -6452,6 +6452,35 @@ then
if test "x$ac_cv_sqlite_enable_unlock_notify" = "xno"; then
AC_MSG_ERROR([System SQLite library is not compiled with SQLITE_ENABLE_UNLOCK_NOTIFY.])
fi
dnl =========================================
dnl === SQLITE_ENABLE_DBSTAT_VTAB check ===
dnl =========================================
dnl check to see if the system SQLite package is compiled with
dnl SQLITE_ENABLE_DBSTAT_VTAB.
AC_MSG_CHECKING(for SQLITE_ENABLE_DBSTAT_VTAB support in system SQLite)
_SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $SQLITE_CFLAGS"
_SAVE_LIBS="$LIBS"
LIBS="$LIBS $SQLITE_LIBS"
AC_CACHE_VAL(ac_cv_sqlite_dbstat_vtab,[
AC_TRY_RUN([
#include "sqlite3.h"
int main(int argc, char **argv){
return !sqlite3_compileoption_used("SQLITE_ENABLE_DBSTAT_VTAB");
}],
ac_cv_sqlite_dbstat_vtab=yes,
ac_cv_sqlite_dbstat_vtab=no,
ac_cv_sqlite_dbstat_vtab=no
)
])
AC_MSG_RESULT($ac_cv_sqlite_dbstat_vtab)
CFLAGS="$_SAVE_CFLAGS"
LIBS="$_SAVE_LIBS"
if test "x$ac_cv_sqlite_dbstat_vtab" = "xno"; then
AC_MSG_ERROR([System SQLite library is not compiled with SQLITE_ENABLE_DBSTAT_VTAB.])
fi
fi
if test -n "$MOZ_NATIVE_SQLITE"; then
+2 -1
View File
@@ -37,7 +37,8 @@ SOURCES += [
# concurrent connections, especially when they use shared cache.
# Note: Be sure to update the configure.in checks when these change!
for var in ('SQLITE_SECURE_DELETE', 'SQLITE_THREADSAFE', 'SQLITE_CORE',
'SQLITE_ENABLE_FTS3', 'SQLITE_ENABLE_UNLOCK_NOTIFY'):
'SQLITE_ENABLE_FTS3', 'SQLITE_ENABLE_UNLOCK_NOTIFY',
'SQLITE_ENABLE_DBSTAT_VTAB'):
DEFINES[var] = 1
DEFINES['SQLITE_DEFAULT_PAGE_SIZE'] = 32768
+132 -126
View File
@@ -152,8 +152,6 @@ using namespace mozilla::image;
using namespace mozilla::ipc;
using namespace mozilla::layers;
namespace mgfx = mozilla::gfx;
namespace mozilla {
namespace dom {
@@ -297,10 +295,10 @@ public:
AdjustedTargetForFilter(CanvasRenderingContext2D *ctx,
DrawTarget *aFinalTarget,
const mgfx::IntPoint& aFilterSpaceToTargetOffset,
const mgfx::IntRect& aPreFilterBounds,
const mgfx::IntRect& aPostFilterBounds,
mgfx::CompositionOp aCompositionOp)
const gfx::IntPoint& aFilterSpaceToTargetOffset,
const gfx::IntRect& aPreFilterBounds,
const gfx::IntRect& aPostFilterBounds,
gfx::CompositionOp aCompositionOp)
: mCtx(nullptr)
, mCompositionOp(aCompositionOp)
{
@@ -348,7 +346,7 @@ public:
// Return a SourceSurface that contains the FillPaint or StrokePaint source.
already_AddRefed<SourceSurface>
DoSourcePaint(mgfx::IntRect& aRect, CanvasRenderingContext2D::Style aStyle)
DoSourcePaint(gfx::IntRect& aRect, CanvasRenderingContext2D::Style aStyle)
{
if (aRect.IsEmpty()) {
return nullptr;
@@ -367,8 +365,8 @@ public:
dt->SetTransform(transform);
if (transform.Invert()) {
mgfx::Rect dtBounds(0, 0, aRect.width, aRect.height);
mgfx::Rect fillRect = transform.TransformBounds(dtBounds);
gfx::Rect dtBounds(0, 0, aRect.width, aRect.height);
gfx::Rect fillRect = transform.TransformBounds(dtBounds);
dt->FillRect(fillRect, CanvasGeneralPattern().ForStyle(mCtx, aStyle, dt));
}
return dt->Snapshot();
@@ -390,9 +388,9 @@ public:
AutoRestoreTransform autoRestoreTransform(mFinalTarget);
mFinalTarget->SetTransform(Matrix());
mgfx::FilterSupport::RenderFilterDescription(
gfx::FilterSupport::RenderFilterDescription(
mFinalTarget, mCtx->CurrentState().filter,
mgfx::Rect(mPostFilterBounds),
gfx::Rect(mPostFilterBounds),
snapshot, mSourceGraphicRect,
fillPaint, mFillPaintRect,
strokePaint, mStrokePaintRect,
@@ -410,12 +408,12 @@ private:
RefPtr<DrawTarget> mTarget;
RefPtr<DrawTarget> mFinalTarget;
CanvasRenderingContext2D *mCtx;
mgfx::IntRect mSourceGraphicRect;
mgfx::IntRect mFillPaintRect;
mgfx::IntRect mStrokePaintRect;
mgfx::IntRect mPostFilterBounds;
mgfx::IntPoint mOffset;
mgfx::CompositionOp mCompositionOp;
gfx::IntRect mSourceGraphicRect;
gfx::IntRect mFillPaintRect;
gfx::IntRect mStrokePaintRect;
gfx::IntRect mPostFilterBounds;
gfx::IntPoint mOffset;
gfx::CompositionOp mCompositionOp;
};
/* This is an RAII based class that can be used as a drawtarget for
@@ -429,8 +427,8 @@ public:
AdjustedTargetForShadow(CanvasRenderingContext2D *ctx,
DrawTarget *aFinalTarget,
const mgfx::Rect& aBounds,
mgfx::CompositionOp aCompositionOp)
const gfx::Rect& aBounds,
gfx::CompositionOp aCompositionOp)
: mCtx(nullptr)
, mCompositionOp(aCompositionOp)
{
@@ -441,7 +439,7 @@ public:
mSigma = state.ShadowBlurSigma();
mgfx::Rect bounds = aBounds;
gfx::Rect bounds = aBounds;
int32_t blurRadius = state.ShadowBlurRadius();
@@ -488,7 +486,7 @@ public:
return mTarget;
}
mgfx::IntPoint OffsetToFinalDT()
gfx::IntPoint OffsetToFinalDT()
{
return mTempRect.TopLeft();
}
@@ -498,8 +496,8 @@ private:
RefPtr<DrawTarget> mFinalTarget;
CanvasRenderingContext2D *mCtx;
Float mSigma;
mgfx::IntRect mTempRect;
mgfx::CompositionOp mCompositionOp;
gfx::IntRect mTempRect;
gfx::CompositionOp mCompositionOp;
};
/* This is an RAII based class that can be used as a drawtarget for
@@ -519,7 +517,7 @@ public:
typedef CanvasRenderingContext2D::ContextState ContextState;
explicit AdjustedTarget(CanvasRenderingContext2D* ctx,
const mgfx::Rect *aBounds = nullptr)
const gfx::Rect *aBounds = nullptr)
{
mTarget = ctx->mTarget;
@@ -529,21 +527,21 @@ public:
// calculate what their maximum required bounds would need to be if we
// were to fill the whole canvas. Everything outside those bounds we don't
// need to render.
mgfx::Rect r(0, 0, ctx->mWidth, ctx->mHeight);
mgfx::Rect maxSourceNeededBoundsForShadow =
gfx::Rect r(0, 0, ctx->mWidth, ctx->mHeight);
gfx::Rect maxSourceNeededBoundsForShadow =
MaxSourceNeededBoundsForShadow(r, ctx);
mgfx::Rect maxSourceNeededBoundsForFilter =
gfx::Rect maxSourceNeededBoundsForFilter =
MaxSourceNeededBoundsForFilter(maxSourceNeededBoundsForShadow, ctx);
mgfx::Rect bounds = maxSourceNeededBoundsForFilter;
gfx::Rect bounds = maxSourceNeededBoundsForFilter;
if (aBounds) {
bounds = bounds.Intersect(*aBounds);
}
mgfx::Rect boundsAfterFilter = BoundsAfterFilter(bounds, ctx);
gfx::Rect boundsAfterFilter = BoundsAfterFilter(bounds, ctx);
mozilla::gfx::CompositionOp op = ctx->CurrentState().op;
mgfx::IntPoint offsetToFinalDT;
gfx::IntPoint offsetToFinalDT;
// First set up the shadow draw target, because the shadow goes outside.
// It applies to the post-filter results, if both a filter and a shadow
@@ -556,20 +554,20 @@ public:
// If we also have a filter, the filter needs to be drawn with OP_OVER
// because shadow drawing already applies op on the result.
op = mgfx::CompositionOp::OP_OVER;
op = gfx::CompositionOp::OP_OVER;
}
// Now set up the filter draw target.
if (ctx->NeedToApplyFilter()) {
bounds.RoundOut();
mgfx::IntRect intBounds;
gfx::IntRect intBounds;
if (!bounds.ToIntRect(&intBounds)) {
return;
}
mFilterTarget = MakeUnique<AdjustedTargetForFilter>(
ctx, mTarget, offsetToFinalDT, intBounds,
mgfx::RoundedToInt(boundsAfterFilter), op);
gfx::RoundedToInt(boundsAfterFilter), op);
mTarget = mFilterTarget->DT();
}
}
@@ -594,8 +592,8 @@ public:
private:
mgfx::Rect
MaxSourceNeededBoundsForFilter(const mgfx::Rect& aDestBounds, CanvasRenderingContext2D *ctx)
gfx::Rect
MaxSourceNeededBoundsForFilter(const gfx::Rect& aDestBounds, CanvasRenderingContext2D *ctx)
{
if (!ctx->NeedToApplyFilter()) {
return aDestBounds;
@@ -606,21 +604,21 @@ private:
nsIntRegion strokePaintNeededRegion;
FilterSupport::ComputeSourceNeededRegions(
ctx->CurrentState().filter, mgfx::RoundedToInt(aDestBounds),
ctx->CurrentState().filter, gfx::RoundedToInt(aDestBounds),
sourceGraphicNeededRegion, fillPaintNeededRegion, strokePaintNeededRegion);
return mgfx::Rect(sourceGraphicNeededRegion.GetBounds());
return gfx::Rect(sourceGraphicNeededRegion.GetBounds());
}
mgfx::Rect
MaxSourceNeededBoundsForShadow(const mgfx::Rect& aDestBounds, CanvasRenderingContext2D *ctx)
gfx::Rect
MaxSourceNeededBoundsForShadow(const gfx::Rect& aDestBounds, CanvasRenderingContext2D *ctx)
{
if (!ctx->NeedToDrawShadow()) {
return aDestBounds;
}
const ContextState &state = ctx->CurrentState();
mgfx::Rect sourceBounds = aDestBounds - state.shadowOffset;
gfx::Rect sourceBounds = aDestBounds - state.shadowOffset;
sourceBounds.Inflate(state.ShadowBlurRadius());
// Union the shadow source with the original rect because we're going to
@@ -628,25 +626,25 @@ private:
return sourceBounds.Union(aDestBounds);
}
mgfx::Rect
BoundsAfterFilter(const mgfx::Rect& aBounds, CanvasRenderingContext2D *ctx)
gfx::Rect
BoundsAfterFilter(const gfx::Rect& aBounds, CanvasRenderingContext2D *ctx)
{
if (!ctx->NeedToApplyFilter()) {
return aBounds;
}
mgfx::Rect bounds(aBounds);
gfx::Rect bounds(aBounds);
bounds.RoundOut();
mgfx::IntRect intBounds;
gfx::IntRect intBounds;
if (!bounds.ToIntRect(&intBounds)) {
return mgfx::Rect();
return gfx::Rect();
}
nsIntRegion extents =
mgfx::FilterSupport::ComputePostFilterExtents(ctx->CurrentState().filter,
intBounds);
return mgfx::Rect(extents.GetBounds());
gfx::FilterSupport::ComputePostFilterExtents(ctx->CurrentState().filter,
intBounds);
return gfx::Rect(extents.GetBounds());
}
RefPtr<DrawTarget> mTarget;
@@ -676,7 +674,9 @@ CanvasGradient::AddColorStop(float offset, const nsAString& colorstr, ErrorResul
}
nscolor color;
if (!nsRuleNode::ComputeColor(value, nullptr, nullptr, color)) {
nsCOMPtr<nsIPresShell> presShell = mContext ? mContext->GetPresShell() : nullptr;
if (!nsRuleNode::ComputeColor(value, presShell ? presShell->GetPresContext() : nullptr,
nullptr, color)) {
rv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
@@ -948,6 +948,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
, mZero(false), mOpaque(false)
, mResetLayer(true)
, mIPC(false)
, mIsSkiaGL(false)
, mDrawObserver(nullptr)
, mIsEntireFrameInvalid(false)
, mPredictManyRedrawCalls(false)
@@ -1137,7 +1138,7 @@ CanvasRenderingContext2D::Redraw()
}
void
CanvasRenderingContext2D::Redraw(const mgfx::Rect &r)
CanvasRenderingContext2D::Redraw(const gfx::Rect &r)
{
mIsCapturedFrameInvalid = true;
@@ -1185,8 +1186,7 @@ CanvasRenderingContext2D::RedrawUser(const gfxRect& r)
return;
}
mgfx::Rect newr =
mTarget->GetTransform().TransformBounds(ToRect(r));
gfx::Rect newr = mTarget->GetTransform().TransformBounds(ToRect(r));
Redraw(newr);
}
@@ -1233,7 +1233,7 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
mRenderingMode = attemptedMode;
// Restore the content from the old DrawTarget
mgfx::Rect r(0, 0, mWidth, mHeight);
gfx::Rect r(0, 0, mWidth, mHeight);
mTarget->DrawSurface(snapshot, r, r);
// Restore the clips and transform
@@ -1378,6 +1378,8 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
}
}
mIsSkiaGL = false;
// Check that the dimensions are sane
IntSize size(mWidth, mHeight);
if (size.width <= gfxPrefs::MaxCanvasSize() &&
@@ -1411,6 +1413,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
if (mTarget) {
AddDemotableContext(this);
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
mIsSkiaGL = true;
} else {
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
mode = RenderingMode::SoftwareBackendMode;
@@ -1445,15 +1448,15 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
JS_updateMallocCounter(context, mWidth * mHeight * 4);
}
mTarget->ClearRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
if (mTarget->GetBackendType() == mgfx::BackendType::CAIRO) {
mTarget->ClearRect(gfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
if (mTarget->GetBackendType() == gfx::BackendType::CAIRO) {
// Cairo doesn't play well with huge clips. When given a very big clip it
// will try to allocate big mask surface without taking the target
// size into account which can cause OOM. See bug 1034593.
// This limits the clip extents to the size of the canvas.
// A fix in Cairo would probably be preferable, but requires somewhat
// invasive changes.
mTarget->PushClipRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
mTarget->PushClipRect(gfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
}
// Force a full layer transaction since we didn't have a layer before
// and now we might need one.
@@ -1578,9 +1581,9 @@ CanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *shell,
mTarget = sErrorTarget;
}
if (mTarget->GetBackendType() == mgfx::BackendType::CAIRO) {
if (mTarget->GetBackendType() == gfx::BackendType::CAIRO) {
// Cf comment in EnsureTarget
mTarget->PushClipRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
mTarget->PushClipRect(gfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
}
return NS_OK;
@@ -2540,7 +2543,7 @@ CanvasRenderingContext2D::ClearRect(double x, double y, double w,
return;
}
mTarget->ClearRect(mgfx::Rect(x, y, w, h));
mTarget->ClearRect(gfx::Rect(x, y, w, h));
RedrawUser(gfxRect(x, y, w, h));
}
@@ -2601,16 +2604,16 @@ CanvasRenderingContext2D::FillRect(double x, double y, double w,
}
}
mgfx::Rect bounds;
gfx::Rect bounds;
EnsureTarget();
if (NeedToCalculateBounds()) {
bounds = mgfx::Rect(x, y, w, h);
bounds = gfx::Rect(x, y, w, h);
bounds = mTarget->GetTransform().TransformBounds(bounds);
}
AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
FillRect(mgfx::Rect(x, y, w, h),
FillRect(gfx::Rect(x, y, w, h),
CanvasGeneralPattern().ForStyle(this, Style::FILL, mTarget),
DrawOptions(state.globalAlpha, UsedOperation()));
@@ -2623,7 +2626,7 @@ CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
{
const ContextState &state = CurrentState();
mgfx::Rect bounds;
gfx::Rect bounds;
if (!w && !h) {
return;
@@ -2639,8 +2642,8 @@ CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
}
if (NeedToCalculateBounds()) {
bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
w + state.lineWidth, h + state.lineWidth);
bounds = gfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
w + state.lineWidth, h + state.lineWidth);
bounds = mTarget->GetTransform().TransformBounds(bounds);
}
@@ -2679,14 +2682,14 @@ CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
}
AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
StrokeRect(mgfx::Rect(x, y, w, h),
CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
StrokeOptions(state.lineWidth, state.lineJoin,
state.lineCap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset),
DrawOptions(state.globalAlpha, UsedOperation()));
StrokeRect(gfx::Rect(x, y, w, h),
CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
StrokeOptions(state.lineWidth, state.lineJoin,
state.lineCap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset),
DrawOptions(state.globalAlpha, UsedOperation()));
Redraw();
}
@@ -2707,14 +2710,13 @@ CanvasRenderingContext2D::BeginPath()
void
CanvasRenderingContext2D::Fill(const CanvasWindingRule& winding)
{
EnsureTarget();
EnsureUserSpacePath(winding);
if (!mPath) {
return;
}
mgfx::Rect bounds;
gfx::Rect bounds;
if (NeedToCalculateBounds()) {
bounds = mPath->GetBounds(mTarget->GetTransform());
@@ -2737,7 +2739,7 @@ void CanvasRenderingContext2D::Fill(const CanvasPath& path, const CanvasWindingR
return;
}
mgfx::Rect bounds;
gfx::Rect bounds;
if (NeedToCalculateBounds()) {
bounds = gfxpath->GetBounds(mTarget->GetTransform());
@@ -2753,7 +2755,6 @@ void CanvasRenderingContext2D::Fill(const CanvasPath& path, const CanvasWindingR
void
CanvasRenderingContext2D::Stroke()
{
EnsureTarget();
EnsureUserSpacePath();
if (!mPath) {
@@ -2767,7 +2768,7 @@ CanvasRenderingContext2D::Stroke()
state.dash.Length(), state.dash.Elements(),
state.dashOffset);
mgfx::Rect bounds;
gfx::Rect bounds;
if (NeedToCalculateBounds()) {
bounds =
mPath->GetStrokedBounds(strokeOptions, mTarget->GetTransform());
@@ -2798,7 +2799,7 @@ CanvasRenderingContext2D::Stroke(const CanvasPath& path)
state.dash.Length(), state.dash.Elements(),
state.dashOffset);
mgfx::Rect bounds;
gfx::Rect bounds;
if (NeedToCalculateBounds()) {
bounds =
gfxpath->GetStrokedBounds(strokeOptions, mTarget->GetTransform());
@@ -2889,8 +2890,6 @@ bool CanvasRenderingContext2D::DrawCustomFocusRing(mozilla::dom::Element& aEleme
void
CanvasRenderingContext2D::Clip(const CanvasWindingRule& winding)
{
EnsureTarget();
EnsureUserSpacePath(winding);
if (!mPath) {
@@ -3048,6 +3047,8 @@ CanvasRenderingContext2D::Ellipse(double aX, double aY, double aRadiusX, double
void
CanvasRenderingContext2D::EnsureWritablePath()
{
EnsureTarget();
if (mDSPathBuilder) {
return;
}
@@ -3066,7 +3067,6 @@ CanvasRenderingContext2D::EnsureWritablePath()
return;
}
EnsureTarget();
if (!mPath) {
NS_ASSERTION(!mPathTransformWillUpdate, "mPathTransformWillUpdate should be false, if all paths are null");
mPathBuilder = mTarget->CreatePathBuilder(fillRule);
@@ -3087,8 +3087,9 @@ CanvasRenderingContext2D::EnsureUserSpacePath(const CanvasWindingRule& winding)
if(winding == CanvasWindingRule::Evenodd)
fillRule = FillRule::FILL_EVEN_ODD;
EnsureTarget();
if (!mPath && !mPathBuilder && !mDSPathBuilder) {
EnsureTarget();
mPathBuilder = mTarget->CreatePathBuilder(fillRule);
}
@@ -3364,6 +3365,7 @@ CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorRes
{
RefPtr<gfx::Path> path;
if (options.mPath) {
EnsureTarget();
path = options.mPath->GetPath(CanvasWindingRule::Nonzero, mTarget);
}
@@ -3379,7 +3381,7 @@ CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorRes
}
// get the bounds of the current path. They are relative to the canvas
mgfx::Rect bounds(path->GetBounds(mTarget->GetTransform()));
gfx::Rect bounds(path->GetBounds(mTarget->GetTransform()));
if ((bounds.width == 0) || (bounds.height == 0) || !bounds.IsFinite()) {
// The specified region has no pixels.
error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
@@ -3443,7 +3445,7 @@ CanvasRenderingContext2D::GetHitRegionRect(Element* aElement, nsRect& aRect)
for (unsigned int x = 0; x < mHitRegionsOptions.Length(); x++) {
RegionInfo& info = mHitRegionsOptions[x];
if (info.mElement == aElement) {
mgfx::Rect bounds(info.mPath->GetBounds());
gfx::Rect bounds(info.mPath->GetBounds());
gfxRect rect(bounds.x, bounds.y, bounds.width, bounds.height);
aRect = nsLayoutUtils::RoundGfxRectToAppRect(rect, AppUnitsPerCSSPixel());
@@ -3707,12 +3709,18 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess
buffer.mGlyphs = &glyphBuf.front();
buffer.mNumGlyphs = 1;
const ContextState& state = *mState;
AdjustedTarget target(mCtx, &bounds);
const StrokeOptions strokeOpts(state.lineWidth, state.lineJoin,
state.lineCap, state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset);
// We need to adjust the bounds for the adjusted target
bounds.Inflate(MaxStrokeExtents(strokeOpts, mCtx->mTarget->GetTransform()));
AdjustedTarget target(mCtx, &bounds);
CanvasGeneralPattern cgp;
const Pattern& patForStyle
(cgp.ForStyle(mCtx, CanvasRenderingContext2D::Style::STROKE, mCtx->mTarget));
@@ -4289,11 +4297,11 @@ bool CanvasRenderingContext2D::IsPointInStroke(const CanvasPath& mPath, double x
// On entry, aSourceRect is relative to aSurface, and on return aSourceRect is
// relative to the returned surface.
static already_AddRefed<SourceSurface>
ExtractSubrect(SourceSurface* aSurface, mgfx::Rect* aSourceRect, DrawTarget* aTargetDT)
ExtractSubrect(SourceSurface* aSurface, gfx::Rect* aSourceRect, DrawTarget* aTargetDT)
{
mgfx::Rect roundedOutSourceRect = *aSourceRect;
gfx::Rect roundedOutSourceRect = *aSourceRect;
roundedOutSourceRect.RoundOut();
mgfx::IntRect roundedOutSourceRectInt;
gfx::IntRect roundedOutSourceRectInt;
if (!roundedOutSourceRect.ToIntRect(&roundedOutSourceRectInt)) {
RefPtr<SourceSurface> surface(aSurface);
return surface.forget();
@@ -4617,19 +4625,19 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
Filter filter;
if (CurrentState().imageSmoothingEnabled)
filter = mgfx::Filter::LINEAR;
filter = gfx::Filter::LINEAR;
else
filter = mgfx::Filter::POINT;
filter = gfx::Filter::POINT;
mgfx::Rect bounds;
gfx::Rect bounds;
if (NeedToCalculateBounds()) {
bounds = mgfx::Rect(dx, dy, dw, dh);
bounds = gfx::Rect(dx, dy, dw, dh);
bounds = mTarget->GetTransform().TransformBounds(bounds);
}
if (srcSurf) {
mgfx::Rect sourceRect(sx, sy, sw, sh);
gfx::Rect sourceRect(sx, sy, sw, sh);
if (element == mCanvasElement) {
// srcSurf is a snapshot of mTarget. If we draw to mTarget now, we'll
// trigger a COW copy of the whole canvas into srcSurf. That's a huge
@@ -4640,14 +4648,14 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
}
AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
DrawSurface(srcSurf,
mgfx::Rect(dx, dy, dw, dh),
gfx::Rect(dx, dy, dw, dh),
sourceRect,
DrawSurfaceOptions(filter),
DrawOptions(CurrentState().globalAlpha, UsedOperation()));
} else {
DrawDirectlyToCanvas(drawInfo, &bounds,
mgfx::Rect(dx, dy, dw, dh),
mgfx::Rect(sx, sy, sw, sh),
gfx::Rect(dx, dy, dw, dh),
gfx::Rect(sx, sy, sw, sh),
imgSize);
}
@@ -4657,9 +4665,9 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
void
CanvasRenderingContext2D::DrawDirectlyToCanvas(
const nsLayoutUtils::DirectDrawInfo& image,
mgfx::Rect* bounds,
mgfx::Rect dest,
mgfx::Rect src,
gfx::Rect* bounds,
gfx::Rect dest,
gfx::Rect src,
gfx::IntSize imgSize)
{
MOZ_ASSERT(src.width > 0 && src.height > 0,
@@ -4925,10 +4933,10 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
return;
}
mgfx::Rect destRect(0, 0, w, h);
mgfx::Rect sourceRect(0, 0, sw, sh);
gfx::Rect destRect(0, 0, w, h);
gfx::Rect sourceRect(0, 0, sw, sh);
mTarget->DrawSurface(source, destRect, sourceRect,
DrawSurfaceOptions(mgfx::Filter::POINT),
DrawSurfaceOptions(gfx::Filter::POINT),
DrawOptions(GlobalAlpha(), CompositionOp::OP_OVER,
AntialiasMode::NONE));
mTarget->Flush();
@@ -5066,9 +5074,9 @@ CanvasRenderingContext2D::DrawWidgetAsOnScreen(nsGlobalWindow& aWindow,
return;
}
mgfx::Rect sourceRect(mgfx::Point(0, 0), mgfx::Size(snapshot->GetSize()));
gfx::Rect sourceRect(gfx::Point(0, 0), gfx::Size(snapshot->GetSize()));
mTarget->DrawSurface(snapshot, sourceRect, sourceRect,
DrawSurfaceOptions(mgfx::Filter::POINT),
DrawSurfaceOptions(gfx::Filter::POINT),
DrawOptions(GlobalAlpha(), CompositionOp::OP_OVER,
AntialiasMode::NONE));
mTarget->Flush();
@@ -5201,21 +5209,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
return NS_ERROR_DOM_SYNTAX_ERR;
}
IntRect srcRect(0, 0, mWidth, mHeight);
IntRect destRect(aX, aY, aWidth, aHeight);
IntRect srcReadRect = srcRect.Intersect(destRect);
RefPtr<DataSourceSurface> readback;
DataSourceSurface::MappedSurface rawData;
if (!srcReadRect.IsEmpty() && !mZero) {
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
if (snapshot) {
readback = snapshot->GetDataSurface();
}
if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
JS::Rooted<JSObject*> darray(aCx, JS_NewUint8ClampedArray(aCx, len.value()));
if (!darray) {
return NS_ERROR_OUT_OF_MEMORY;
@@ -5226,6 +5219,21 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
return NS_OK;
}
IntRect srcRect(0, 0, mWidth, mHeight);
IntRect destRect(aX, aY, aWidth, aHeight);
IntRect srcReadRect = srcRect.Intersect(destRect);
RefPtr<DataSourceSurface> readback;
DataSourceSurface::MappedSurface rawData;
if (!srcReadRect.IsEmpty()) {
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
if (snapshot) {
readback = snapshot->GetDataSurface();
}
if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
IntRect dstWriteRect = srcReadRect;
dstWriteRect.MoveBy(-aX, -aY);
@@ -5244,10 +5252,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
srcStride = aWidth * 4;
}
// 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;
uint8_t a,r,g,b;
@@ -5518,7 +5522,7 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
dirtyRect.width, dirtyRect.height),
IntPoint(dirtyRect.x, dirtyRect.y));
Redraw(mgfx::Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
Redraw(gfx::Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
return NS_OK;
}
@@ -5618,9 +5622,11 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
LayerManager *aManager)
{
if (mOpaque) {
if (mOpaque || mIsSkiaGL) {
// If we're opaque then make sure we have a surface so we paint black
// instead of transparent.
// If we're using SkiaGL, then SkiaGLTex() below needs the target to
// be accessible.
EnsureTarget();
}
+3
View File
@@ -723,6 +723,9 @@ protected:
bool mResetLayer;
// This is needed for drawing in drawAsyncXULElement
bool mIPC;
// True if the current DrawTarget is using skia-gl, used so we can avoid
// requesting the DT from mBufferProvider to check.
bool mIsSkiaGL;
nsTArray<CanvasRenderingContext2DUserData*> mUserDatas;
+14
View File
@@ -159,6 +159,20 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) &&
gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) &&
gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5);
case WebGLExtensionID::WEBGL_debug_renderer_info:
{
bool isEnabled = true;
#ifdef RELEASE_BUILD
// Keep this disabled on Release and Beta for now. (see bug 1171228)
isEnabled = false;
#endif
if (Preferences::GetBool("webgl.disable-debug-renderer-info", false))
isEnabled = false;
return isEnabled;
}
case WebGLExtensionID::WEBGL_depth_texture:
// WEBGL_depth_texture supports DEPTH_STENCIL textures
if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
+59 -16
View File
@@ -4,16 +4,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLContextUtils.h"
#include "WebGLBuffer.h"
#include "WebGLShader.h"
#include "WebGLProgram.h"
#include "WebGLFramebuffer.h"
#include "WebGLRenderbuffer.h"
#include "WebGLTexture.h"
#include "WebGLVertexArray.h"
#include "GLContext.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/Preferences.h"
#include "nsString.h"
#include "WebGLBuffer.h"
#include "WebGLContextUtils.h"
#include "WebGLFramebuffer.h"
#include "WebGLProgram.h"
#include "WebGLRenderbuffer.h"
#include "WebGLShader.h"
#include "WebGLTexture.h"
#include "WebGLVertexArray.h"
namespace mozilla {
@@ -57,6 +60,18 @@ WebGLContext::Enable(GLenum cap)
gl->fEnable(cap);
}
static JS::Value
StringValue(JSContext* cx, const nsAString& str, ErrorResult& rv)
{
JSString* jsStr = JS_NewUCStringCopyN(cx, str.BeginReading(), str.Length());
if (!jsStr) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return JS::NullValue();
}
return JS::StringValue(jsStr);
}
bool
WebGLContext::GetStencilBits(GLint* out_stencilBits)
{
@@ -176,19 +191,47 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
}
// Privileged string params exposed by WEBGL_debug_renderer_info:
// Privileged string params exposed by WEBGL_debug_renderer_info.
// The privilege check is done in WebGLContext::IsExtensionSupported.
// So here we just have to check that the extension is enabled.
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
switch (pname) {
case UNMASKED_VENDOR_WEBGL:
case UNMASKED_RENDERER_WEBGL:
GLenum glstringname = LOCAL_GL_NONE;
if (pname == UNMASKED_VENDOR_WEBGL) {
glstringname = LOCAL_GL_VENDOR;
} else if (pname == UNMASKED_RENDERER_WEBGL) {
glstringname = LOCAL_GL_RENDERER;
{
const char* overridePref = nullptr;
GLenum driverEnum = LOCAL_GL_NONE;
switch (pname) {
case UNMASKED_RENDERER_WEBGL:
overridePref = "webgl.renderer-string-override";
driverEnum = LOCAL_GL_RENDERER;
break;
case UNMASKED_VENDOR_WEBGL:
overridePref = "webgl.vendor-string-override";
driverEnum = LOCAL_GL_VENDOR;
break;
default:
MOZ_CRASH("bad `pname`");
}
bool hasRetVal = false;
nsAutoString ret;
if (overridePref) {
nsresult res = Preferences::GetString(overridePref, &ret);
if (NS_SUCCEEDED(res) && ret.Length() > 0)
hasRetVal = true;
}
if (!hasRetVal) {
const char* chars = reinterpret_cast<const char*>(gl->fGetString(driverEnum));
ret = NS_ConvertASCIItoUTF16(chars);
hasRetVal = true;
}
return StringValue(cx, ret, rv);
}
const GLchar* string = (const GLchar*) gl->fGetString(glstringname);
return StringValue(cx, string, rv);
}
}
+23
View File
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var ctx = canvas.getContext('2d');
ctx.rect(2, 6, 9, 8);
ctx.setTransform(1, 2, 3, 0, 4, 1);
setTimeout(function() {
ctx.moveTo(0, 1);
ctx.isPointInPath(0, 0, 'evenodd');
}, 0);
}
</script>
</head>
<body onload="boom();">
<canvas id="canvas"></canvas>
</body>
</html>
+1
View File
@@ -22,3 +22,4 @@ load 896047-2.html
load 916128-1.html
load 934939-1.html
load 1099143-1.html
load 1183363.html
@@ -2,6 +2,12 @@
<html>
<script>
var Cu = parent.Components.utils;
Cu.import("resource://gre/modules/AppConstants.jsm");
// This gives us `AppConstants` in the global scope.
// We need this because we only expose debug_renderer_info #ifndef MOZ_RELEASE_BUILD.
// This should match AppConstants.RELEASE_BUILD.
// This file has the portion of the test_webgl_renderer_info chrome mochitest
// that has to run as non-chrome to check that this WebGL extension is not exposed to content
@@ -28,30 +34,58 @@ function run() {
const UNMASKED_VENDOR_WEBGL = 0x9245;
const UNMASKED_RENDERER_WEBGL = 0x9246;
var shouldHaveRendererInfo = false;
if (!AppConstants.RELEASE_BUILD)
shouldHaveRendererInfo = true;
var canvas = document.createElement("canvas");
var gl = canvas.getContext("experimental-webgl");
ok(!gl.getError(), "getError on newly created WebGL context should return NO_ERROR");
ok(!gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_VENDOR_WEBGL without having enabled the WEBGL_debug_renderer_info extension");
"Should not be able to query UNMASKED_VENDOR_WEBGL without having enabled the"
+ " WEBGL_debug_renderer_info extension");
ok(!gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_RENDERER_WEBGL without having enabled the WEBGL_debug_renderer_info extension");
"Should not be able to query UNMASKED_RENDERER_WEBGL without having enabled the"
+ " WEBGL_debug_renderer_info extension");
var exts = gl.getSupportedExtensions();
ok(exts.indexOf("WEBGL_debug_renderer_info") == -1,
"WEBGL_debug_renderer_info should not be listed by getSupportedExtensions in non-chrome contexts");
var debugRendererInfoExtension = gl.getExtension("WEBGL_debug_renderer_info");
ok(!debugRendererInfoExtension,
"WEBGL_debug_renderer_info should not be available through getExtension in non-chrome contexts");
if (shouldHaveRendererInfo) {
ok(exts.indexOf("WEBGL_debug_renderer_info") != -1,
"WEBGL_debug_renderer_info should be listed by getSupportedExtensions in"
+ " non-chrome contexts on non-RELEASE_BUILDs");
ok(!gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_VENDOR_WEBGL if enabling WEBGL_debug_renderer_info failed");
ok(!gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_RENDERER_WEBGL if enabling WEBGL_debug_renderer_info failed");
var ext = gl.getExtension("WEBGL_debug_renderer_info");
ok(!!ext,
"WEBGL_debug_renderer_info should be available through getExtension in non-chrome"
+ " contexts on non-RELEASE_BUILDs");
ok(gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.NO_ERROR,
"Should be able to query UNMASKED_VENDOR_WEBGL if enabling"
+ " WEBGL_debug_renderer_info succeeded");
ok(gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.NO_ERROR,
"Should be able to query UNMASKED_RENDERER_WEBGL if enabling"
+ " WEBGL_debug_renderer_info succeeded");
} else {
ok(exts.indexOf("WEBGL_debug_renderer_info") == -1,
"WEBGL_debug_renderer_info should not be listed by getSupportedExtensions in"
+ " non-chrome contexts");
var ext = gl.getExtension("WEBGL_debug_renderer_info");
ok(!ext,
"WEBGL_debug_renderer_info should not be available through getExtension in"
+ " non-chrome contexts");
ok(!gl.getParameter(UNMASKED_VENDOR_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_VENDOR_WEBGL if enabling"
+ " WEBGL_debug_renderer_info failed");
ok(!gl.getParameter(UNMASKED_RENDERER_WEBGL) && gl.getError() == gl.INVALID_ENUM,
"Should not be able to query UNMASKED_RENDERER_WEBGL if enabling"
+ " WEBGL_debug_renderer_info failed");
}
window.postMessage({allTestsFinished: true}, "*");
}
</script>
</html>
</html>
@@ -43,13 +43,13 @@ function checkChromeCase(canvas) {
var exts = gl.getSupportedExtensions();
ok(exts.indexOf("WEBGL_debug_renderer_info") != -1,
"WEBGL_debug_renderer_info should be listed by getSupportedExtensions in chrome contexts");
var debugRendererInfoExtension = gl.getExtension("WEBGL_debug_renderer_info");
ok(debugRendererInfoExtension,
var ext = gl.getExtension("WEBGL_debug_renderer_info");
ok(ext,
"WEBGL_debug_renderer_info should be available through getExtension in chrome contexts");
ok(debugRendererInfoExtension.UNMASKED_VENDOR_WEBGL == UNMASKED_VENDOR_WEBGL,
ok(ext.UNMASKED_VENDOR_WEBGL == UNMASKED_VENDOR_WEBGL,
"UNMASKED_VENDOR_WEBGL has the correct value");
ok(debugRendererInfoExtension.UNMASKED_RENDERER_WEBGL == UNMASKED_RENDERER_WEBGL,
ok(ext.UNMASKED_RENDERER_WEBGL == UNMASKED_RENDERER_WEBGL,
"UNMASKED_RENDERER_WEBGL has the correct value");
ok(isNonEmptyString(gl.getParameter(UNMASKED_VENDOR_WEBGL)) && gl.getError() == gl.NO_ERROR,
@@ -67,7 +67,7 @@ function main()
// Now run the non-chrome code to verify the security of this WebGL chrome-only extension.
var iframe = document.createElement("iframe");
iframe.src = "http://mochi.test:8888/chrome/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html";
iframe.src = "chrome://mochitests/content/chrome/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html";
iframe.onload = function () {
+1
View File
@@ -213,6 +213,7 @@ skip-if = toolkit != 'cocoa'
[test_2d.path.rect.zero.6.html]
disabled = bug 407107
[test_2d.strokeRect.zero.5.html]
[test_bug232227.html]
[test_bug613794.html]
[test_bug753758.html]
[test_bug764125.html]
@@ -0,0 +1,24 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Testcase for bug 1177726</title>
</head>
<body>
<canvas id="c" width="400" height="200">
<p>No canvas.</p>
</canvas>
<script>
var canvas = document.getElementsByTagName("canvas")[0];
var ctx = canvas.getContext('2d');
ctx.font = "120px 'Helvetica'";
ctx.lineWidth = 15;
ctx.lineJoin = "round";
ctx.strokeText("Ehsan", 20, 110);
</script>
</body>
</html>
@@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Testcase for bug 1177726</title>
</head>
<body>
<canvas id="c" width="400" height="200">
<p>No canvas.</p>
</canvas>
<script>
var canvas = document.getElementsByTagName("canvas")[0];
var ctx = canvas.getContext('2d');
ctx.shadowColor = 'white';
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;
ctx.shadowBlur = 0;
ctx.font = "120px 'Helvetica'";
ctx.lineWidth = 15;
ctx.lineJoin = "round";
ctx.strokeText("Ehsan", 20, 110);
</script>
</body>
</html>
+3 -1
View File
@@ -157,4 +157,6 @@ pref(canvas.focusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidVersion
pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidVersion<15,8,500) skip-if(winWidget) needs-focus == drawCustomFocusRing.html drawCustomFocusRing-ref.html
# Check that captureStream() displays in a local video element
pref(canvas.capturestream.enabled,true) fails-if(B2G) skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
pref(canvas.capturestream.enabled,true) skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
fuzzy-if(Android,3,40) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
+151
View File
@@ -0,0 +1,151 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=232227
-->
<head>
<title>Test for Bug 232227</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=232227">Mozilla Bug 232227</a>
<!-- CSS system colors -->
<!--<table cellspacing=0 border=1>
<caption>CSS system colors</caption>
<canvas id=colorTestCanvas width=1 height=1 style="display:none"></canvas> -->
<script type="application/javascript">
/** Test for Bug 232227 **/
function beginTest() {
var colorNames = [
[ "ActiveBorder", 0xB4, 0xB4, 0xB4 ],
[ "ActiveCaption", 0x99, 0xB4, 0xD1 ],
[ "AppWorkspace", 0xAB, 0xAB, 0xAB ],
[ "Background", 0x00, 0x00, 0x00 ],
[ "ButtonFace", 0xF0, 0xF0, 0xF0 ],
[ "ButtonHighlight", 0xFF, 0xFF, 0xFF ],
[ "ButtonShadow", 0xA0, 0xA0, 0xA0 ],
[ "ButtonText", 0x00, 0x00, 0x00 ],
[ "CaptionText", 0x00, 0x00, 0x00 ],
[ "GrayText", 0x6D, 0x6D, 0x6D ],
[ "Highlight", 0x33, 0x99, 0xFF ],
[ "HighlightText", 0xFF, 0xFF, 0xFF ],
[ "InactiveBorder", 0xF4, 0xF7, 0xFC ],
[ "InactiveCaption", 0xBF, 0xCD, 0xDB ],
[ "InactiveCaptionText", 0x43, 0x4E, 0x54 ],
[ "InfoBackground", 0xFF, 0xFF, 0xE1 ],
[ "InfoText", 0x00, 0x00, 0x00 ],
[ "Menu", 0xF0, 0xF0, 0xF0 ],
[ "MenuText", 0x00, 0x00, 0x00 ],
[ "Scrollbar", 0xC8, 0xC8, 0xC8 ],
[ "ThreeDDarkShadow", 0x69, 0x69, 0x69 ],
[ "ThreeDFace", 0xF0, 0xF0, 0xF0 ],
[ "ThreeDHighlight", 0xFF, 0xFF, 0xFF ],
[ "ThreeDLightShadow", 0xE3, 0xE3, 0xE3 ],
[ "ThreeDShadow", 0xA0, 0xA0, 0xA0 ],
[ "Window", 0xFF, 0xFF, 0xFF ],
[ "WindowFrame", 0x64, 0x64, 0x64 ],
[ "WindowText", 0x00, 0x00, 0x00 ],
[ "-moz-ButtonDefault", 0x69, 0x69, 0x69 ],
[ "-moz-ButtonHoverFace", 0xF0, 0xF0, 0xF0 ],
[ "-moz-ButtonHoverText", 0x00, 0x00, 0x00 ],
[ "-moz-CellHighlight", 0xF0, 0xF0, 0xF0 ],
[ "-moz-CellHighlightText", 0x00, 0x00, 0x00 ],
[ "-moz-Combobox", 0xFF, 0xFF, 0xFF ],
[ "-moz-ComboboxText", 0x00, 0x00, 0x00 ],
[ "-moz-Dialog", 0xF0, 0xF0, 0xF0 ],
[ "-moz-DialogText", 0x00, 0x00, 0x00 ],
[ "-moz-DragTargetZone", 0xFF, 0xFF, 0xFF ],
[ "-moz-EvenTreeRow", 0xFF, 0xFF, 0xFF ],
[ "-moz-Field", 0xFF, 0xFF, 0xFF ],
[ "-moz-FieldText", 0x00, 0x00, 0x00 ],
[ "-moz-MenuHover", 0x33, 0x99, 0xFF ],
[ "-moz-MenuHoverText", 0x00, 0x00, 0x00 ],
[ "-moz-MenubarText", 0x00, 0x00, 0x00 ],
[ "-moz-MenubarHoverText", 0x00, 0x00, 0x00 ],
[ "-moz-NativeHyperlinkText", 0x00, 0x66, 0xCC ],
[ "-moz-OddTreeRow", 0xFF, 0xFF, 0xFF ],
[ "-moz-html-CellHighlight", 0x33, 0x99, 0xFF ],
[ "-moz-html-CellHighlightText", 0xFF, 0xFF, 0xFF ],
[ "-moz-mac-chrome-active", 0xB2, 0xB2, 0xB2 ],
[ "-moz-mac-chrome-inactive", 0xE1, 0xE1, 0xE1 ],
[ "-moz-mac-focusring", 0x60, 0x9D, 0xD7 ],
[ "-moz-mac-menuselect", 0x38, 0x75, 0xD7 ],
[ "-moz-mac-menushadow", 0xA3, 0xA3, 0xA3 ],
[ "-moz-mac-menutextdisable", 0x88, 0x88, 0x88 ],
[ "-moz-mac-menutextselect", 0xFF, 0xFF, 0xFF ],
[ "-moz-mac-DisabledToolbarText", 0x3F, 0x3F, 0x3F ],
[ "-moz-mac-AlternatePrimaryHighlight", 0x3F, 0x3F, 0x3F ],
[ "-moz-mac-SecondaryHighlight", 0xD4, 0xD4, 0xD4 ],
[ "-moz-win-MediaText", 0xFF, 0xFF, 0xFF ],
[ "-moz-win-CommunicationsText", 0xFF, 0xFF, 0xFF ],
// These five are configured via Tools -> Options -> Content -> Colors.
//"-moz-ActiveHyperlinkText",
//"-moz-HyperLinkText",
//"-moz-VisitedHyperlinkText",
//"-moz-default-background-color",
//"-moz-default-color",
];
var colorTestCanvas = document.createElement("canvas");
colorTestCanvas.width = colorTestCanvas.height = 1;
colorTestCanvas = colorTestCanvas.getContext("2d");
var colorTestDiv = document.createElement("div");
document.body.appendChild(colorTestDiv); // ie
for (var i in colorNames) {
(function(colorName, r, g, b) {
// test value
var ctest = "rgb(" + r + ", " + g + ", " + b + ")";
// computed value
colorTestDiv.style.backgroundColor = "#FF00FE";
try {
colorTestDiv.style.backgroundColor = colorName;
} catch (ex) {} // ie
var c1;
if (window.getComputedStyle) {
c1 = getComputedStyle(colorTestDiv, null).backgroundColor;
} else { // ie
var range = document.body.createTextRange();
range.moveToElementText(colorTestDiv);
c1 = range.queryCommandValue("BackColor");
c1 = "rgb(" + (c1 & 0xFF) + ", " + ((c1 >> 8) & 0xFF) + ", " + ((c1 >> 16) & 0xFF) + ")";
}
if (c1 != "rgb(255, 0, 254)") {
is(c1, ctest, "Stand-in computed color: " + colorName + " is correct.");
}
// canvas
if (colorTestCanvas) {
colorTestCanvas.fillStyle = colorName;
colorTestCanvas.fillRect(0, 0, 1, 1);
var c2 = colorTestCanvas.getImageData(0, 0, 1, 1).data;
c2 = "rgb(" + c2[0] + ", " + c2[1] + ", " + c2[2] + ")";
// combine
if (c2 != c1 && c2 != "rgb(0, 0, 0)") {
is(c2, ctest, "Stand-in canvas color: " + colorName + " is correct.");
}
}
})(colorNames[i][0], colorNames[i][1], colorNames[i][2], colorNames[i][3]);
}
SimpleTest.finish();
}
var prefs = [
[ "ui.use_standins_for_native_colors", true ],
[ "ui.use_native_colors", true ],
];
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
</script>
<!-- </table> -->
</body>
</html>
+1
View File
@@ -22,6 +22,7 @@ skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in
skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.3 aws only; bug 1030942
[webgl-mochitest/test_noprog_draw.html]
[webgl-mochitest/test_privileged_exts.html]
[webgl-mochitest/test_renderer_strings.html]
[webgl-mochitest/test_texsubimage_float.html]
[webgl-mochitest/test_webgl_available.html]
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
@@ -24,7 +24,7 @@ function TestExt(gl, name) {
}
// Privileged extensions:
TestExt(gl, 'WEBGL_debug_renderer_info');
TestExt(gl, 'WEBGL_debug_shaders');
})();
</script>
@@ -0,0 +1,98 @@
<!DOCTYPE HTML>
<html>
<head>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
function AssertError(gl, expected, info) {
var actual = gl.getError();
while (gl.getError()) {}
ok(actual == expected,
'For ' + info + ', expected 0x' + expected.toString(16) + ', got 0x'
+ actual.toString(16));
}
var gl;
var RENDERER_OVERRIDE = 'overridden renderer';
var VENDOR_OVERRIDE = 'overridden vendor';
function TestExt() {
var ext = gl.getExtension('WEBGL_debug_renderer_info');
ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
AssertError(gl, 0, 'start of test');
var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
ok(renderer,
'UNMASKED_RENDERER_WEBGL value should not be empty, was \'' + renderer + '\'');
var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
ok(vendor, 'UNMASKED_VENDOR_WEBGL value should not be empty, was \'' + vendor + '\'');
var prefArrArr = [
['webgl.renderer-string-override', RENDERER_OVERRIDE],
['webgl.vendor-string-override', VENDOR_OVERRIDE],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, TestOverrides);
}
function TestOverrides() {
var ext = gl.getExtension('WEBGL_debug_renderer_info');
ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
AssertError(gl, 0, 'start of test');
var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
ok(renderer == RENDERER_OVERRIDE,
'UNMASKED_RENDERER_WEBGL value should be \'' + RENDERER_OVERRIDE + '\', was \''
+ renderer + '\'');
var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
ok(vendor == VENDOR_OVERRIDE,
'UNMASKED_VENDOR_WEBGL value should be \'' + VENDOR_OVERRIDE + '\', was \'' + vendor
+ '\'');
var prefArrArr = [
['webgl.disable-debug-renderer-info', true],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, TestDisable);
}
function TestDisable() {
var ext = gl.getExtension('WEBGL_debug_renderer_info');
ok(!ext, 'Should not have access to \'WEBGL_debug_renderer_info\'.');
ok(true, 'Test complete.');
SimpleTest.finish();
}
(function() {
var canvas = document.createElement('canvas');
gl = canvas.getContext('experimental-webgl');
if (!gl) {
todo(gl, 'Get WebGL working here first.');
ok(true, 'Test complete.');
return;
}
SimpleTest.waitForExplicitFinish();
var prefArrArr = [
['webgl.disable-debug-renderer-info', false],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, TestExt);
})();
</script>
</body>
</html>
+2 -2
View File
@@ -91,8 +91,8 @@ Matrix::Rotation(Float aAngle)
{
Matrix newMatrix;
Float s = sin(aAngle);
Float c = cos(aAngle);
Float s = sinf(aAngle);
Float c = cosf(aAngle);
newMatrix._11 = c;
newMatrix._12 = s;
+4 -4
View File
@@ -267,8 +267,8 @@ PathBuilderD2D::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
}
Point endPoint;
endPoint.x = aOrigin.x + aRadius * cos(aEndAngle);
endPoint.y = aOrigin.y + aRadius * sin(aEndAngle);
endPoint.x = aOrigin.x + aRadius * cosf(aEndAngle);
endPoint.y = aOrigin.y + aRadius * sinf(aEndAngle);
D2D1_ARC_SIZE arcSize = D2D1_ARC_SIZE_SMALL;
D2D1_SWEEP_DIRECTION direction =
@@ -296,8 +296,8 @@ PathBuilderD2D::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
else {
// draw small circles as two half-circles
Point midPoint;
midPoint.x = aOrigin.x + aRadius * cos(midAngle);
midPoint.y = aOrigin.y + aRadius * sin(midAngle);
midPoint.x = aOrigin.x + aRadius * cosf(midAngle);
midPoint.y = aOrigin.y + aRadius * sinf(midAngle);
mSink->AddArc(D2D1::ArcSegment(D2DPoint(midPoint),
D2D1::SizeF(aRadius, aRadius),
+4 -4
View File
@@ -185,8 +185,8 @@ inline float EvalLanczos(int filter_size, float x) {
x < std::numeric_limits<float>::epsilon())
return 1.0f; // Special case the discontinuity at the origin.
float xpi = x * static_cast<float>(M_PI);
return (sin(xpi) / xpi) * // sinc(x)
sin(xpi / filter_size) / (xpi / filter_size); // sinc(x/filter_size)
return (sinf(xpi) / xpi) * // sinc(x)
sinf(xpi / filter_size) / (xpi / filter_size); // sinc(x/filter_size)
}
// Evaluates the Hamming filter of the given filter size window for the given
@@ -212,8 +212,8 @@ inline float EvalHamming(int filter_size, float x) {
return 1.0f; // Special case the sinc discontinuity at the origin.
const float xpi = x * static_cast<float>(M_PI);
return ((sin(xpi) / xpi) * // sinc(x)
(0.54f + 0.46f * cos(xpi / filter_size))); // hamming(x)
return ((sinf(xpi) / xpi) * // sinc(x)
(0.54f + 0.46f * cosf(xpi / filter_size))); // hamming(x)
}
// ResizeFilter ----------------------------------------------------------------
+2 -2
View File
@@ -23,7 +23,7 @@ CreateEGLImage(GLContext* gl, GLuint tex)
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));
EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
EGLContext eglContext = GLContextEGL::Cast(gl)->GetEGLContext();
EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
EGLImage image = sEGLLibrary.fCreateImage(EGL_DISPLAY(),
eglContext,
LOCAL_EGL_GL_TEXTURE_2D,
@@ -42,7 +42,7 @@ EGLImageWrapper::Create(GLContext* gl, GLuint tex)
GLLibraryEGL& library = sEGLLibrary;
EGLDisplay display = EGL_DISPLAY();
EGLContext eglContext = GLContextEGL::Cast(gl)->GetEGLContext();
EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
EGLImage image = library.fCreateImage(display,
eglContext,
-113
View File
@@ -30,119 +30,6 @@ using mozilla::layers::PlanarYCbCrData;
namespace mozilla {
namespace gl {
static void
RenderbufferStorageBySamples(GLContext* aGL, GLsizei aSamples,
GLenum aInternalFormat, const gfx::IntSize& aSize)
{
if (aSamples) {
aGL->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
aSamples,
aInternalFormat,
aSize.width, aSize.height);
} else {
aGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
aInternalFormat,
aSize.width, aSize.height);
}
}
GLuint
CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
GLenum aType, const gfx::IntSize& aSize, bool linear)
{
GLuint tex = 0;
aGL->fGenTextures(1, &tex);
ScopedBindTexture autoTex(aGL, tex);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
LOCAL_GL_TEXTURE_MIN_FILTER, linear ? LOCAL_GL_LINEAR
: LOCAL_GL_NEAREST);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
LOCAL_GL_TEXTURE_MAG_FILTER, linear ? LOCAL_GL_LINEAR
: LOCAL_GL_NEAREST);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S,
LOCAL_GL_CLAMP_TO_EDGE);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T,
LOCAL_GL_CLAMP_TO_EDGE);
aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
0,
aInternalFormat,
aSize.width, aSize.height,
0,
aFormat,
aType,
nullptr);
return tex;
}
GLuint
CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
const gfx::IntSize& aSize)
{
MOZ_ASSERT(aFormats.color_texInternalFormat);
MOZ_ASSERT(aFormats.color_texFormat);
MOZ_ASSERT(aFormats.color_texType);
return CreateTexture(aGL,
aFormats.color_texInternalFormat,
aFormats.color_texFormat,
aFormats.color_texType,
aSize);
}
GLuint
CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples,
const gfx::IntSize& aSize)
{
GLuint rb = 0;
aGL->fGenRenderbuffers(1, &rb);
ScopedBindRenderbuffer autoRB(aGL, rb);
RenderbufferStorageBySamples(aGL, aSamples, aFormat, aSize);
return rb;
}
void
CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats,
const gfx::IntSize& aSize, bool aMultisample,
GLuint* aColorMSRB, GLuint* aDepthRB,
GLuint* aStencilRB)
{
GLsizei samples = aMultisample ? aFormats.samples : 0;
if (aColorMSRB) {
MOZ_ASSERT(aFormats.samples > 0);
MOZ_ASSERT(aFormats.color_rbFormat);
*aColorMSRB = CreateRenderbuffer(aGL, aFormats.color_rbFormat, samples, aSize);
}
if (aDepthRB &&
aStencilRB &&
aFormats.depthStencil)
{
*aDepthRB = CreateRenderbuffer(aGL, aFormats.depthStencil, samples, aSize);
*aStencilRB = *aDepthRB;
} else {
if (aDepthRB) {
MOZ_ASSERT(aFormats.depth);
*aDepthRB = CreateRenderbuffer(aGL, aFormats.depth, samples, aSize);
}
if (aStencilRB) {
MOZ_ASSERT(aFormats.stencil);
*aStencilRB = CreateRenderbuffer(aGL, aFormats.stencil, samples, aSize);
}
}
}
GLBlitHelper::GLBlitHelper(GLContext* gl)
: mGL(gl)
, mTexBlit_Buffer(0)
-42
View File
@@ -27,48 +27,6 @@ namespace gl {
class GLContext;
/**
* Helper function that creates a 2D texture aSize.width x aSize.height with
* storage type specified by aFormats. Returns GL texture object id.
*
* See mozilla::gl::CreateTexture.
*/
GLuint CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
const gfx::IntSize& aSize);
/**
* Helper function that creates a 2D texture aSize.width x aSize.height with
* storage type aInternalFormat. Returns GL texture object id.
*
* Initialize textyre parameters to:
* GL_TEXTURE_MIN_FILTER = GL_LINEAR
* GL_TEXTURE_MAG_FILTER = GL_LINEAR
* GL_TEXTURE_WRAP_S = GL_CLAMP_TO_EDGE
* GL_TEXTURE_WRAP_T = GL_CLAMP_TO_EDGE
*/
GLuint CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
GLenum aType, const gfx::IntSize& aSize, bool linear = true);
/**
* Helper function to create, potentially, multisample render buffers suitable
* for offscreen rendering. Buffers of size aSize.width x aSize.height with
* storage specified by aFormat. returns GL render buffer object id.
*/
GLuint CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples,
const gfx::IntSize& aSize);
/**
* Helper function to create, potentially, multisample render buffers suitable
* for offscreen rendering. Buffers of size aSize.width x aSize.height with
* storage specified by aFormats. GL render buffer object ids are returned via
* aColorMSRB, aDepthRB, and aStencilRB
*/
void CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats,
const gfx::IntSize& aSize, bool aMultisample,
GLuint* aColorMSRB, GLuint* aDepthRB,
GLuint* aStencilRB);
/** Buffer blitting helper */
class GLBlitHelper final
{
+54 -1
View File
@@ -304,7 +304,6 @@ GLContext::GLContext(const SurfaceCaps& caps,
mRenderer(GLRenderer::Other),
mHasRobustness(false),
mTopError(LOCAL_GL_NO_ERROR),
mLocalErrorScope(nullptr),
mSharedContext(sharedContext),
mCaps(caps),
mScreen(nullptr),
@@ -2933,5 +2932,59 @@ GLContext::IsDrawingToDefaultFramebuffer()
return Screen()->IsDrawFramebufferDefault();
}
GLuint
CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
GLenum aType, const gfx::IntSize& aSize, bool linear)
{
GLuint tex = 0;
aGL->fGenTextures(1, &tex);
ScopedBindTexture autoTex(aGL, tex);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
LOCAL_GL_TEXTURE_MIN_FILTER, linear ? LOCAL_GL_LINEAR
: LOCAL_GL_NEAREST);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
LOCAL_GL_TEXTURE_MAG_FILTER, linear ? LOCAL_GL_LINEAR
: LOCAL_GL_NEAREST);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S,
LOCAL_GL_CLAMP_TO_EDGE);
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T,
LOCAL_GL_CLAMP_TO_EDGE);
aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
0,
aInternalFormat,
aSize.width, aSize.height,
0,
aFormat,
aType,
nullptr);
return tex;
}
GLuint
CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
const gfx::IntSize& aSize)
{
MOZ_ASSERT(aFormats.color_texInternalFormat);
MOZ_ASSERT(aFormats.color_texFormat);
MOZ_ASSERT(aFormats.color_texType);
GLenum internalFormat = aFormats.color_texInternalFormat;
GLenum unpackFormat = aFormats.color_texFormat;
GLenum unpackType = aFormats.color_texType;
if (aGL->IsANGLE()) {
MOZ_ASSERT(internalFormat == LOCAL_GL_RGBA);
MOZ_ASSERT(unpackFormat == LOCAL_GL_RGBA);
MOZ_ASSERT(unpackType == LOCAL_GL_UNSIGNED_BYTE);
internalFormat = LOCAL_GL_BGRA_EXT;
unpackFormat = LOCAL_GL_BGRA_EXT;
}
return CreateTexture(aGL, internalFormat, unpackFormat, unpackType, aSize);
}
} /* namespace gl */
} /* namespace mozilla */
+33 -11
View File
@@ -7,12 +7,13 @@
#ifndef GLCONTEXT_H_
#define GLCONTEXT_H_
#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
#include <map>
#include <bitset>
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <map>
#include <queue>
#include <stack>
#ifdef DEBUG
#include <string.h>
@@ -619,7 +620,7 @@ public:
class LocalErrorScope;
private:
LocalErrorScope* mLocalErrorScope;
std::stack<const LocalErrorScope*> mLocalErrorScopeStack;
public:
class LocalErrorScope {
@@ -632,8 +633,7 @@ public:
: mGL(gl)
, mHasBeenChecked(false)
{
MOZ_ASSERT(!mGL.mLocalErrorScope);
mGL.mLocalErrorScope = this;
mGL.mLocalErrorScopeStack.push(this);
mGL.FlushErrors();
@@ -653,10 +653,10 @@ public:
MOZ_ASSERT(mGL.fGetError() == LOCAL_GL_NO_ERROR);
mGL.mTopError = mOldTop;
MOZ_ASSERT(mGL.mLocalErrorScopeStack.top() == this);
mGL.mLocalErrorScopeStack.pop();
MOZ_ASSERT(mGL.mLocalErrorScope == this);
mGL.mLocalErrorScope = nullptr;
mGL.mTopError = mOldTop;
}
};
@@ -738,7 +738,7 @@ private:
}
if (err != LOCAL_GL_NO_ERROR &&
!mLocalErrorScope)
!mLocalErrorScopeStack.size())
{
printf_stderr("[gl:%p] %s: Generated unexpected %s error."
" (0x%04x)\n", this, funcName,
@@ -3652,6 +3652,28 @@ MarkBitfieldByStrings(const std::vector<nsCString>& strList,
}
}
/**
* Helper function that creates a 2D texture aSize.width x aSize.height with
* storage type specified by aFormats. Returns GL texture object id.
*
* See mozilla::gl::CreateTexture.
*/
GLuint CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
const gfx::IntSize& aSize);
/**
* Helper function that creates a 2D texture aSize.width x aSize.height with
* storage type aInternalFormat. Returns GL texture object id.
*
* Initialize textyre parameters to:
* GL_TEXTURE_MIN_FILTER = GL_LINEAR
* GL_TEXTURE_MAG_FILTER = GL_LINEAR
* GL_TEXTURE_WRAP_S = GL_CLAMP_TO_EDGE
* GL_TEXTURE_WRAP_T = GL_CLAMP_TO_EDGE
*/
GLuint CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
GLenum aType, const gfx::IntSize& aSize, bool linear = true);
} /* namespace gl */
} /* namespace mozilla */
+11 -10
View File
@@ -92,16 +92,12 @@ public:
// for the lifetime of this context.
void HoldSurface(gfxASurface *aSurf);
EGLContext GetEGLContext() {
return mContext;
}
EGLSurface GetEGLSurface() {
EGLSurface GetEGLSurface() const {
return mSurface;
}
EGLDisplay GetEGLDisplay() {
return EGL_DISPLAY();
EGLDisplay GetEGLDisplay() const {
return sEGLLibrary.Display();
}
bool BindTex2DOffscreen(GLContext *aOffscreen);
@@ -112,15 +108,20 @@ public:
CreateEGLPixmapOffscreenContext(const gfx::IntSize& size);
static already_AddRefed<GLContextEGL>
CreateEGLPBufferOffscreenContext(const gfx::IntSize& size);
CreateEGLPBufferOffscreenContext(const gfx::IntSize& size,
const SurfaceCaps& minCaps);
protected:
friend class GLContextProviderEGL;
EGLConfig mConfig;
public:
const EGLConfig mConfig;
protected:
EGLSurface mSurface;
public:
const EGLContext mContext;
protected:
EGLSurface mSurfaceOverride;
EGLContext mContext;
nsRefPtr<gfxASurface> mThebesSurface;
bool mBound;
+23 -36
View File
@@ -9,7 +9,6 @@
#include "GLContextTypes.h"
#include "nsAutoPtr.h"
#include "SurfaceTypes.h"
#include "mozilla/TypedEnumBits.h"
#include "nsSize.h" // for gfx::IntSize (needed by GLContextProviderImpl.h below)
@@ -18,16 +17,6 @@ class nsIWidget;
namespace mozilla {
namespace gl {
enum class CreateContextFlags : int8_t {
NONE = 0,
REQUIRE_COMPAT_PROFILE = 1 << 0,
// Force the use of hardware backed GL, don't allow software implementations.
FORCE_ENABLE_HARDWARE = 1 << 1,
/* Don't force discrete GPU to be used (if applicable) */
ALLOW_OFFLINE_RENDERER = 1 << 2,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
#define IN_GL_CONTEXT_PROVIDER_H
// Null is always there
@@ -36,47 +25,45 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
#undef GL_CONTEXT_PROVIDER_NAME
#ifdef XP_WIN
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderWGL
#include "GLContextProviderImpl.h"
#undef GL_CONTEXT_PROVIDER_NAME
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWGL
#define DEFAULT_IMPL WGL
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderWGL
#include "GLContextProviderImpl.h"
#undef GL_CONTEXT_PROVIDER_NAME
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWGL
#define DEFAULT_IMPL WGL
#endif
#ifdef XP_MACOSX
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderCGL
#include "GLContextProviderImpl.h"
#undef GL_CONTEXT_PROVIDER_NAME
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderCGL
#include "GLContextProviderImpl.h"
#undef GL_CONTEXT_PROVIDER_NAME
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
#endif
#if defined(MOZ_X11)
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
#include "GLContextProviderImpl.h"
#undef GL_CONTEXT_PROVIDER_NAME
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX
#endif
#if defined(ANDROID) || defined(XP_WIN)
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
#include "GLContextProviderImpl.h"
#undef GL_CONTEXT_PROVIDER_NAME
#ifndef GL_CONTEXT_PROVIDER_DEFAULT
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
#endif
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
#endif
#ifdef MOZ_GL_PROVIDER
#define GL_CONTEXT_PROVIDER_NAME MOZ_GL_PROVIDER
#include "GLContextProviderImpl.h"
#undef GL_CONTEXT_PROVIDER_NAME
#define GL_CONTEXT_PROVIDER_DEFAULT MOZ_GL_PROVIDER
#endif
#if defined(MOZ_X11) && !defined(GL_CONTEXT_PROVIDER_DEFAULT)
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
#include "GLContextProviderImpl.h"
#undef GL_CONTEXT_PROVIDER_NAME
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX
#define GL_CONTEXT_PROVIDER_NAME MOZ_GL_PROVIDER
#include "GLContextProviderImpl.h"
#undef GL_CONTEXT_PROVIDER_NAME
#define GL_CONTEXT_PROVIDER_DEFAULT MOZ_GL_PROVIDER
#endif
#ifdef GL_CONTEXT_PROVIDER_DEFAULT
typedef GL_CONTEXT_PROVIDER_DEFAULT GLContextProvider;
typedef GL_CONTEXT_PROVIDER_DEFAULT GLContextProvider;
#else
typedef GLContextProviderNull GLContextProvider;
typedef GLContextProviderNull GLContextProvider;
#endif
#undef IN_GL_CONTEXT_PROVIDER_H
+7 -6
View File
@@ -319,16 +319,17 @@ GLContextProviderCGL::CreateHeadless(CreateContextFlags flags)
already_AddRefed<GLContext>
GLContextProviderCGL::CreateOffscreen(const IntSize& size,
const SurfaceCaps& caps,
const SurfaceCaps& minCaps,
CreateContextFlags flags)
{
nsRefPtr<GLContext> glContext = CreateHeadless(flags);
if (!glContext->InitOffscreen(size, caps)) {
NS_WARNING("Failed during InitOffscreen.");
RefPtr<GLContext> gl = CreateHeadless(flags);
if (!gl)
return nullptr;
}
return glContext.forget();
if (!gl->InitOffscreen(size, minCaps))
return nullptr;
return gl.forget();
}
static nsRefPtr<GLContext> gGlobalContext;
+247 -136
View File
@@ -3,116 +3,108 @@
* 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 "mozilla/ArrayUtils.h"
#include "GLContextEGL.h"
#if defined(MOZ_WIDGET_GTK)
#include <gdk/gdkx.h>
// we're using default display for now
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->GetNativeData(NS_NATIVE_WINDOW)))
#elif defined(MOZ_WIDGET_QT)
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW))
#else
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
#endif
#if defined(XP_UNIX)
#ifdef MOZ_WIDGET_GONK
#include "libdisplay/GonkDisplay.h"
#include "nsWindow.h"
#include "nsScreenManagerGonk.h"
#endif
#ifdef MOZ_WIDGET_GTK
#include <gdk/gdkx.h>
// we're using default display for now
#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW))
#elif defined(MOZ_WIDGET_QT)
#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)(aWidget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW))
#elif defined(MOZ_WIDGET_GONK)
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
#include "libdisplay/GonkDisplay.h"
#include "nsWindow.h"
#include "nsScreenManagerGonk.h"
#endif
#ifdef ANDROID
/* from widget */
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
#if defined(ANDROID)
/* from widget */
#if defined(MOZ_WIDGET_ANDROID)
#include "AndroidBridge.h"
#endif
#include <android/log.h>
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
#include <android/log.h>
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
#ifdef MOZ_WIDGET_GONK
#include "cutils/properties.h"
#include <ui/GraphicBuffer.h>
# if defined(MOZ_WIDGET_GONK)
# include "cutils/properties.h"
# include <ui/GraphicBuffer.h>
using namespace android;
#endif
#endif
using namespace android;
# endif
#endif
#define GLES2_LIB "libGLESv2.so"
#define GLES2_LIB2 "libGLESv2.so.2"
#define GLES2_LIB "libGLESv2.so"
#define GLES2_LIB2 "libGLESv2.so.2"
#elif defined(XP_WIN)
#include "nsIFile.h"
#include "nsIFile.h"
#define GLES2_LIB "libGLESv2.dll"
#define GLES2_LIB "libGLESv2.dll"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#include <windows.h>
// a little helper
class AutoDestroyHWND {
public:
AutoDestroyHWND(HWND aWnd = nullptr)
: mWnd(aWnd)
{
}
~AutoDestroyHWND() {
if (mWnd) {
::DestroyWindow(mWnd);
// a little helper
class AutoDestroyHWND {
public:
AutoDestroyHWND(HWND aWnd = nullptr)
: mWnd(aWnd)
{
}
}
operator HWND() {
return mWnd;
}
HWND forget() {
HWND w = mWnd;
mWnd = nullptr;
return w;
}
HWND operator=(HWND aWnd) {
if (mWnd && mWnd != aWnd) {
::DestroyWindow(mWnd);
~AutoDestroyHWND() {
if (mWnd) {
::DestroyWindow(mWnd);
}
}
mWnd = aWnd;
return mWnd;
}
HWND mWnd;
};
operator HWND() {
return mWnd;
}
HWND forget() {
HWND w = mWnd;
mWnd = nullptr;
return w;
}
HWND operator=(HWND aWnd) {
if (mWnd && mWnd != aWnd) {
::DestroyWindow(mWnd);
}
mWnd = aWnd;
return mWnd;
}
HWND mWnd;
};
#else
#error "Platform not recognized"
#error "Platform not recognized"
#endif
#include "mozilla/Preferences.h"
#include "gfxUtils.h"
#include "gfxFailure.h"
#include "gfxASurface.h"
#include "gfxCrashReporterUtils.h"
#include "gfxFailure.h"
#include "gfxPlatform.h"
#include "gfxUtils.h"
#include "GLBlitHelper.h"
#include "GLContextEGL.h"
#include "GLContextProvider.h"
#include "GLLibraryEGL.h"
#include "TextureImageEGL.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Preferences.h"
#include "nsDebug.h"
#include "nsThreadUtils.h"
#include "nsIWidget.h"
#include "gfxCrashReporterUtils.h"
#include "nsThreadUtils.h"
#include "ScopedGLHelpers.h"
#include "GLBlitHelper.h"
#include "TextureImageEGL.h"
using namespace mozilla::gfx;
@@ -190,17 +182,15 @@ DestroySurface(EGLSurface oldSurface) {
static EGLSurface
CreateSurfaceForWindow(nsIWidget* widget, const EGLConfig& config) {
EGLSurface newSurface = EGL_NO_SURFACE;
EGLSurface newSurface = nullptr;
#ifdef MOZ_WIDGET_ANDROID
mozilla::AndroidBridge::Bridge()->RegisterCompositor();
newSurface = mozilla::AndroidBridge::Bridge()->CreateEGLSurfaceForCompositor();
if (newSurface == EGL_NO_SURFACE) {
return EGL_NO_SURFACE;
}
#elif defined(XP_WIN)
#else
MOZ_ASSERT(widget != nullptr);
newSurface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, GET_NATIVE_WINDOW(widget), 0);
newSurface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config,
GET_NATIVE_WINDOW(widget), 0);
#endif
return newSurface;
}
@@ -215,8 +205,8 @@ GLContextEGL::GLContextEGL(
: GLContext(caps, shareContext, isOffscreen)
, mConfig(config)
, mSurface(surface)
, mSurfaceOverride(EGL_NO_SURFACE)
, mContext(context)
, mSurfaceOverride(EGL_NO_SURFACE)
, mThebesSurface(nullptr)
, mBound(false)
, mIsPBuffer(false)
@@ -351,7 +341,8 @@ GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) {
}
mSurfaceOverride = surf;
MakeCurrent(true);
DebugOnly<bool> ok = MakeCurrent(true);
MOZ_ASSERT(ok);
}
bool
@@ -425,7 +416,7 @@ GLContextEGL::RenewSurface() {
// If we get here, then by definition we know that we want to get a new surface.
ReleaseSurface();
mSurface = mozilla::gl::CreateSurfaceForWindow(nullptr, mConfig); // the nullptr here is where we assume Android.
if (mSurface == EGL_NO_SURFACE) {
if (!mSurface) {
return false;
}
return MakeCurrent(true);
@@ -490,6 +481,10 @@ GLContextEGL::CreateSurfaceForWindow(nsIWidget* aWidget)
}
EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config);
if (!surface) {
MOZ_CRASH("Failed to create EGLSurface for window!\n");
return nullptr;
}
return surface;
}
@@ -780,8 +775,7 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
}
EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config);
if (surface == EGL_NO_SURFACE) {
if (!surface) {
MOZ_CRASH("Failed to create EGLSurface!\n");
return nullptr;
}
@@ -839,60 +833,144 @@ GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface)
}
#endif // defined(ANDROID)
already_AddRefed<GLContextEGL>
GLContextEGL::CreateEGLPBufferOffscreenContext(const mozilla::gfx::IntSize& size)
static void
FillContextAttribs(bool alpha, bool depth, bool stencil, bool bpp16,
nsTArray<EGLint>* out)
{
EGLConfig config;
EGLSurface surface;
out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
const EGLint numConfigs = 1; // We only need one.
EGLConfig configs[numConfigs];
out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
out->AppendElement(LOCAL_EGL_OPENGL_ES2_BIT);
out->AppendElement(LOCAL_EGL_RED_SIZE);
if (bpp16) {
out->AppendElement(alpha ? 4 : 5);
} else {
out->AppendElement(8);
}
out->AppendElement(LOCAL_EGL_GREEN_SIZE);
if (bpp16) {
out->AppendElement(alpha ? 4 : 6);
} else {
out->AppendElement(8);
}
out->AppendElement(LOCAL_EGL_BLUE_SIZE);
if (bpp16) {
out->AppendElement(alpha ? 4 : 5);
} else {
out->AppendElement(8);
}
out->AppendElement(LOCAL_EGL_ALPHA_SIZE);
if (alpha) {
out->AppendElement(bpp16 ? 4 : 8);
} else {
out->AppendElement(0);
}
out->AppendElement(LOCAL_EGL_DEPTH_SIZE);
out->AppendElement(depth ? 16 : 0);
out->AppendElement(LOCAL_EGL_STENCIL_SIZE);
out->AppendElement(stencil ? 8 : 0);
// EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
out->AppendElement(LOCAL_EGL_NONE);
out->AppendElement(0);
out->AppendElement(0);
out->AppendElement(0);
}
static GLint
GetAttrib(GLLibraryEGL* egl, EGLConfig config, EGLint attrib)
{
EGLint bits = 0;
egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits);
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
return bits;
}
static EGLConfig
ChooseConfig(GLLibraryEGL* egl, const SurfaceCaps& minCaps,
SurfaceCaps* const out_configCaps)
{
nsTArray<EGLint> configAttribList;
FillContextAttribs(minCaps.alpha, minCaps.depth, minCaps.stencil, minCaps.bpp16,
&configAttribList);
const EGLint* configAttribs = configAttribList.Elements();
// We're guaranteed to get at least minCaps, and the sorting dictated by the spec for
// eglChooseConfig reasonably assures that a reasonable 'best' config is on top.
const EGLint kMaxConfigs = 1;
EGLConfig configs[kMaxConfigs];
EGLint foundConfigs = 0;
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(),
kEGLConfigAttribsOffscreenPBuffer,
configs, numConfigs,
&foundConfigs)
if (!egl->fChooseConfig(egl->Display(), configAttribs, configs, kMaxConfigs,
&foundConfigs)
|| foundConfigs == 0)
{
NS_WARNING("No EGL Config for minimal PBuffer!");
return EGL_NO_CONFIG;
}
EGLConfig config = configs[0];
*out_configCaps = minCaps; // Pick up any preserve, etc.
out_configCaps->color = true;
out_configCaps->alpha = bool(GetAttrib(egl, config, LOCAL_EGL_ALPHA_SIZE));
out_configCaps->depth = bool(GetAttrib(egl, config, LOCAL_EGL_DEPTH_SIZE));
out_configCaps->stencil = bool(GetAttrib(egl, config, LOCAL_EGL_STENCIL_SIZE));
out_configCaps->bpp16 = (GetAttrib(egl, config, LOCAL_EGL_RED_SIZE) < 8);
return config;
}
/*static*/ already_AddRefed<GLContextEGL>
GLContextEGL::CreateEGLPBufferOffscreenContext(const mozilla::gfx::IntSize& size,
const SurfaceCaps& minCaps)
{
SurfaceCaps configCaps;
EGLConfig config = ChooseConfig(&sEGLLibrary, minCaps, &configCaps);
if (config == EGL_NO_CONFIG) {
NS_WARNING("Failed to find a compatible config.");
return nullptr;
}
// We absolutely don't care, so just pick the first one.
config = configs[0];
if (GLContext::ShouldSpew())
sEGLLibrary.DumpEGLConfig(config);
mozilla::gfx::IntSize pbSize(size);
surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
LOCAL_EGL_NONE,
pbSize);
EGLSurface surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
LOCAL_EGL_NONE,
pbSize);
if (!surface) {
NS_WARNING("Failed to create PBuffer for context!");
return nullptr;
}
SurfaceCaps dummyCaps = SurfaceCaps::Any();
nsRefPtr<GLContextEGL> glContext =
GLContextEGL::CreateGLContext(dummyCaps,
nullptr, true,
config, surface);
if (!glContext) {
RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(configCaps, nullptr, true,
config, surface);
if (!gl) {
NS_WARNING("Failed to create GLContext from PBuffer");
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
return nullptr;
}
if (!glContext->Init()) {
if (!gl->Init()) {
NS_WARNING("Failed to initialize GLContext!");
// GLContextEGL::dtor will destroy |surface| for us.
return nullptr;
}
return glContext.forget();
return gl.forget();
}
already_AddRefed<GLContextEGL>
/*static*/ already_AddRefed<GLContextEGL>
GLContextEGL::CreateEGLPixmapOffscreenContext(const mozilla::gfx::IntSize& size)
{
gfxASurface *thebesSurface = nullptr;
@@ -932,49 +1010,82 @@ GLContextEGL::CreateEGLPixmapOffscreenContext(const mozilla::gfx::IntSize& size)
return glContext.forget();
}
already_AddRefed<GLContext>
/*static*/ already_AddRefed<GLContext>
GLContextProviderEGL::CreateHeadless(CreateContextFlags flags)
{
if (!sEGLLibrary.EnsureInitialized(bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE))) {
bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
if (!sEGLLibrary.EnsureInitialized(forceEnableHardware))
return nullptr;
}
mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
nsRefPtr<GLContext> glContext;
glContext = GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize);
if (!glContext)
return nullptr;
return glContext.forget();
SurfaceCaps dummyCaps = SurfaceCaps::Any();
return GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize, dummyCaps);
}
// Under EGL, on Android, pbuffers are supported fine, though
// often without the ability to texture from them directly.
already_AddRefed<GLContext>
/*static*/ already_AddRefed<GLContext>
GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
const SurfaceCaps& caps,
const SurfaceCaps& minCaps,
CreateContextFlags flags)
{
nsRefPtr<GLContext> glContext = CreateHeadless(flags);
if (!glContext)
bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
if (!sEGLLibrary.EnsureInitialized(forceEnableHardware))
return nullptr;
if (!glContext->InitOffscreen(size, caps))
bool canOffscreenUseHeadless = true;
if (sEGLLibrary.IsANGLE()) {
// ANGLE needs to use PBuffers.
canOffscreenUseHeadless = false;
}
RefPtr<GLContext> gl;
SurfaceCaps minOffscreenCaps = minCaps;
if (canOffscreenUseHeadless) {
gl = CreateHeadless(flags);
if (!gl)
return nullptr;
} else {
SurfaceCaps minBackbufferCaps = minOffscreenCaps;
if (minOffscreenCaps.antialias) {
minBackbufferCaps.antialias = false;
minBackbufferCaps.depth = false;
minBackbufferCaps.stencil = false;
}
gl = GLContextEGL::CreateEGLPBufferOffscreenContext(size, minBackbufferCaps);
if (!gl)
return nullptr;
// Pull the actual resulting caps to ensure that our offscreen matches our
// backbuffer.
minOffscreenCaps.alpha = gl->Caps().alpha;
if (!minOffscreenCaps.antialias) {
// Only update these if we don't have AA. If we do have AA, we ignore
// backbuffer depth/stencil.
minOffscreenCaps.depth = gl->Caps().depth;
minOffscreenCaps.stencil = gl->Caps().stencil;
}
}
// Init the offscreen with the updated offscreen caps.
if (!gl->InitOffscreen(size, minOffscreenCaps))
return nullptr;
return glContext.forget();
return gl.forget();
}
// Don't want a global context on Android as 1) share groups across 2 threads fail on many Tegra drivers (bug 759225)
// and 2) some mobile devices have a very strict limit on global number of GL contexts (bug 754257)
// and 3) each EGL context eats 750k on B2G (bug 813783)
GLContext*
/*static*/ GLContext*
GLContextProviderEGL::GetGlobalContext()
{
return nullptr;
}
void
/*static*/ void
GLContextProviderEGL::Shutdown()
{
}
+103 -88
View File
@@ -76,6 +76,7 @@ GLXLibrary::EnsureInitialized()
if (!mOGLLibrary) {
const char* libGLfilename = nullptr;
bool forceFeatureReport = false;
// see e.g. bug 608526: it is intrinsically interesting to know whether we have dynamically linked to libGL.so.1
// because at least the NVIDIA implementation requires an executable stack, which causes mprotect calls,
@@ -86,11 +87,13 @@ GLXLibrary::EnsureInitialized()
libGLfilename = "libGL.so.1";
#endif
ScopedGfxFeatureReporter reporter(libGLfilename, forceFeatureReport);
mOGLLibrary = PR_LoadLibrary(libGLfilename);
if (!mOGLLibrary) {
NS_WARNING("Couldn't load OpenGL shared library.");
return false;
}
reporter.SetSuccessful();
}
if (PR_GetEnv("MOZ_GLX_DEBUG")) {
@@ -232,7 +235,9 @@ GLXLibrary::EnsureInitialized()
}
if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness") &&
GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_robustness)) {
GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_robustness,
(GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress))
{
mHasRobustness = true;
}
@@ -1123,75 +1128,96 @@ GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget)
return glContext.forget();
}
static already_AddRefed<GLContextGLX>
CreateOffscreenPixmapContext(const IntSize& size)
static bool
ChooseConfig(GLXLibrary* glx, Display* display, int screen, const SurfaceCaps& minCaps,
ScopedXFree<GLXFBConfig>* const out_scopedConfigArr,
GLXFBConfig* const out_config, int* const out_visid)
{
GLXLibrary& glx = sGLXLibrary;
if (!glx.EnsureInitialized()) {
return nullptr;
}
ScopedXFree<GLXFBConfig>& scopedConfigArr = *out_scopedConfigArr;
Display *display = DefaultXDisplay();
int xscreen = DefaultScreen(display);
if (minCaps.antialias)
return false;
int attribs[] = {
LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT,
LOCAL_GLX_X_RENDERABLE, True,
LOCAL_GLX_RED_SIZE, 8,
LOCAL_GLX_GREEN_SIZE, 8,
LOCAL_GLX_BLUE_SIZE, 8,
LOCAL_GLX_ALPHA_SIZE, minCaps.alpha ? 8 : 0,
LOCAL_GLX_DEPTH_SIZE, minCaps.depth ? 16 : 0,
LOCAL_GLX_STENCIL_SIZE, minCaps.stencil ? 8 : 0,
0
};
int numConfigs = 0;
scopedConfigArr = glx->xChooseFBConfig(display, screen, attribs, &numConfigs);
if (!scopedConfigArr || !numConfigs)
return false;
ScopedXFree<GLXFBConfig> cfgs;
cfgs = glx.xChooseFBConfig(display,
xscreen,
attribs,
&numConfigs);
if (!cfgs) {
return nullptr;
}
// Issues with glxChooseFBConfig selection and sorting:
// * ALPHA_SIZE is sorted as 'largest total RGBA bits first'. If we don't request
// alpha bits, we'll probably get RGBA anyways, since 32 is more than 24.
// * DEPTH_SIZE is sorted largest first, including for `0` inputs.
// * STENCIL_SIZE is smallest first, but it might return `8` even though we ask for
// `0`.
MOZ_ASSERT(numConfigs > 0,
"glXChooseFBConfig() failed to match our requested format and "
"violated its spec!");
int visid = None;
int chosenIndex = 0;
// For now, we don't care about these. We *will* care when we do XPixmap sharing.
for (int i = 0; i < numConfigs; ++i) {
int dtype;
GLXFBConfig curConfig = scopedConfigArr[i];
if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_DRAWABLE_TYPE, &dtype) != Success
|| !(dtype & LOCAL_GLX_PIXMAP_BIT))
{
continue;
}
if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid) != Success
|| visid == 0)
int visid;
if (glx->xGetFBConfigAttrib(display, curConfig, LOCAL_GLX_VISUAL_ID, &visid)
!= Success)
{
continue;
}
chosenIndex = i;
break;
if (!visid)
continue;
*out_config = curConfig;
*out_visid = visid;
return true;
}
if (!visid) {
NS_WARNING("glXChooseFBConfig() didn't give us any configs with visuals!");
return false;
}
static already_AddRefed<GLContextGLX>
CreateOffscreenPixmapContext(const IntSize& size, const SurfaceCaps& minCaps)
{
GLXLibrary* glx = &sGLXLibrary;
if (!glx->EnsureInitialized())
return nullptr;
Display* display = DefaultXDisplay();
int screen = DefaultScreen(display);
ScopedXFree<GLXFBConfig> scopedConfigArr;
GLXFBConfig config;
int visid;
if (!ChooseConfig(glx, display, screen, minCaps, &scopedConfigArr, &config, &visid)) {
NS_WARNING("Failed to find a compatible config.");
return nullptr;
}
Visual *visual;
Visual* visual;
int depth;
FindVisualAndDepth(display, visid, &visual, &depth);
ScopedXErrorHandler xErrorHandler;
GLXPixmap glxpixmap = 0;
bool error = false;
IntSize dummySize(16, 16);
nsRefPtr<gfxXlibSurface> xsurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
visual,
dummySize);
if (xsurface->CairoStatus() != 0) {
ScopedXErrorHandler xErrorHandler;
bool error = false;
// Must be declared before goto:
Drawable drawable;
GLXPixmap pixmap;
gfx::IntSize dummySize(16, 16);
RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
visual,
dummySize);
if (surface->CairoStatus() != 0) {
error = true;
goto DONE_CREATING_PIXMAP;
}
@@ -1199,73 +1225,60 @@ CreateOffscreenPixmapContext(const IntSize& size)
// Handle slightly different signature between glXCreatePixmap and
// its pre-GLX-1.3 extension equivalent (though given the ABI, we
// might not need to).
if (glx.GLXVersionCheck(1, 3)) {
glxpixmap = glx.xCreatePixmap(display,
cfgs[chosenIndex],
xsurface->XDrawable(),
nullptr);
drawable = surface->XDrawable();
if (glx->GLXVersionCheck(1, 3)) {
pixmap = glx->xCreatePixmap(display, config, drawable, nullptr);
} else {
glxpixmap = glx.xCreateGLXPixmapWithConfig(display,
cfgs[chosenIndex],
xsurface->
XDrawable());
pixmap = glx->xCreateGLXPixmapWithConfig(display, config, drawable);
}
if (glxpixmap == 0) {
if (pixmap == 0) {
error = true;
}
DONE_CREATING_PIXMAP:
nsRefPtr<GLContextGLX> glContext;
bool serverError = xErrorHandler.SyncAndGetError(display);
if (error || serverError)
return nullptr;
if (!error && // earlier recorded error
!serverError)
{
// We might have an alpha channel, but it doesn't matter.
SurfaceCaps dummyCaps = SurfaceCaps::Any();
GLContextGLX* shareContext = GetGlobalContextGLX();
glContext = GLContextGLX::CreateGLContext(dummyCaps,
shareContext,
true,
display,
glxpixmap,
cfgs[chosenIndex],
true,
xsurface);
}
return glContext.forget();
GLContextGLX* shareContext = GetGlobalContextGLX();
return GLContextGLX::CreateGLContext(minCaps, shareContext, true, display, pixmap,
config, true, surface);
}
already_AddRefed<GLContext>
/*static*/ already_AddRefed<GLContext>
GLContextProviderGLX::CreateHeadless(CreateContextFlags)
{
IntSize dummySize = IntSize(16, 16);
nsRefPtr<GLContext> glContext = CreateOffscreenPixmapContext(dummySize);
if (!glContext)
return nullptr;
return glContext.forget();
SurfaceCaps dummyCaps = SurfaceCaps::Any();
return CreateOffscreenPixmapContext(dummySize, dummyCaps);
}
already_AddRefed<GLContext>
/*static*/ already_AddRefed<GLContext>
GLContextProviderGLX::CreateOffscreen(const IntSize& size,
const SurfaceCaps& caps,
const SurfaceCaps& minCaps,
CreateContextFlags flags)
{
nsRefPtr<GLContext> glContext = CreateHeadless(flags);
if (!glContext)
SurfaceCaps minBackbufferCaps = minCaps;
if (minCaps.antialias) {
minBackbufferCaps.antialias = false;
minBackbufferCaps.depth = false;
minBackbufferCaps.stencil = false;
}
RefPtr<GLContext> gl;
gl = CreateOffscreenPixmapContext(size, minBackbufferCaps);
if (!gl)
return nullptr;
if (!glContext->InitOffscreen(size, caps))
if (!gl->InitOffscreen(size, minCaps))
return nullptr;
return glContext.forget();
return gl.forget();
}
GLContext*
/*static*/ GLContext*
GLContextProviderGLX::GetGlobalContext()
{
static bool checkedContextSharing = false;
@@ -1286,17 +1299,19 @@ GLContextProviderGLX::GetGlobalContext()
triedToCreateContext = true;
IntSize dummySize = IntSize(16, 16);
SurfaceCaps dummyCaps = SurfaceCaps::Any();
// StaticPtr doesn't support assignments from already_AddRefed,
// so use a temporary nsRefPtr to make the reference counting
// fall out correctly.
nsRefPtr<GLContext> holder = CreateOffscreenPixmapContext(dummySize);
RefPtr<GLContext> holder;
holder = CreateOffscreenPixmapContext(dummySize, dummyCaps);
gGlobalContext = holder;
}
return gGlobalContext;
}
void
/*static*/ void
GLContextProviderGLX::Shutdown()
{
gGlobalContext = nullptr;
+7 -5
View File
@@ -54,16 +54,18 @@ public:
* resource sharing can be avoided on the target platform, it will
* be, in order to isolate the offscreen context.
*
* @param size The initial size of this offscreen context.
* @param caps The SurfaceCaps for this offscreen context.
* @param flags The set of CreateContextFlags to be used for this
* offscreen context.
* @param size The initial size of this offscreen context.
* @param minCaps The required SurfaceCaps for this offscreen context. The resulting
* context *may* have more/better caps than requested, but it cannot
* have fewer/worse caps than requested.
* @param flags The set of CreateContextFlags to be used for this
* offscreen context.
*
* @return Context to use for offscreen rendering
*/
static already_AddRefed<GLContext>
CreateOffscreen(const mozilla::gfx::IntSize& size,
const SurfaceCaps& caps,
const SurfaceCaps& minCaps,
CreateContextFlags flags);
// Just create a context. We'll add offscreen stuff ourselves.
+9 -9
View File
@@ -601,7 +601,7 @@ CreateWindowOffscreenContext()
return glContext.forget();
}
already_AddRefed<GLContext>
/*static*/ already_AddRefed<GLContext>
GLContextProviderWGL::CreateHeadless(CreateContextFlags)
{
if (!sWGLLib.EnsureInitialized()) {
@@ -634,24 +634,24 @@ GLContextProviderWGL::CreateHeadless(CreateContextFlags)
return retGL.forget();
}
already_AddRefed<GLContext>
/*static*/ already_AddRefed<GLContext>
GLContextProviderWGL::CreateOffscreen(const IntSize& size,
const SurfaceCaps& caps,
const SurfaceCaps& minCaps,
CreateContextFlags flags)
{
nsRefPtr<GLContext> glContext = CreateHeadless(flags);
if (!glContext)
RefPtr<GLContext> gl = CreateHeadless(flags);
if (!gl)
return nullptr;
if (!glContext->InitOffscreen(size, caps))
if (!gl->InitOffscreen(size, minCaps))
return nullptr;
return glContext.forget();
return gl.forget();
}
static nsRefPtr<GLContextWGL> gGlobalContext;
GLContext *
/*static*/ GLContext*
GLContextProviderWGL::GetGlobalContext()
{
if (!sWGLLib.EnsureInitialized()) {
@@ -679,7 +679,7 @@ GLContextProviderWGL::GetGlobalContext()
return static_cast<GLContext*>(gGlobalContext);
}
void
/*static*/ void
GLContextProviderWGL::Shutdown()
{
gGlobalContext = nullptr;
+11
View File
@@ -7,6 +7,7 @@
#define GLCONTEXT_TYPES_H_
#include "GLTypes.h"
#include "mozilla/TypedEnumBits.h"
namespace mozilla {
namespace gl {
@@ -43,6 +44,16 @@ struct GLFormats
GLsizei samples;
};
enum class CreateContextFlags : int8_t {
NONE = 0,
REQUIRE_COMPAT_PROFILE = 1 << 0,
// Force the use of hardware backed GL, don't allow software implementations.
FORCE_ENABLE_HARDWARE = 1 << 1,
/* Don't force discrete GPU to be used (if applicable) */
ALLOW_OFFLINE_RENDERER = 1 << 2,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
} /* namespace gl */
} /* namespace mozilla */
+2 -2
View File
@@ -37,8 +37,8 @@ static const char *sEGLExtensionNames[] = {
"EGL_KHR_fence_sync",
"EGL_ANDROID_native_fence_sync",
"EGL_ANDROID_image_crop",
"ANGLE_platform_angle",
"ANGLE_platform_angle_d3d"
"EGL_ANGLE_platform_angle",
"EGL_ANGLE_platform_angle_d3d"
};
#if defined(ANDROID)
+22 -30
View File
@@ -17,40 +17,32 @@
#include <bitset>
#include <vector>
#if defined(XP_WIN)
#ifdef XP_WIN
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
typedef HWND EGLNativeWindowType;
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
#include <windows.h>
typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
typedef HWND EGLNativeWindowType;
#else
typedef void *EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
typedef void* EGLNativeDisplayType;
typedef void* EGLNativePixmapType;
typedef void* EGLNativeWindowType;
#ifdef ANDROID
// We only need to explicitly dlopen egltrace
// on android as we can use LD_PRELOAD or other tricks
// on other platforms. We look for it in /data/local
// as that's writeable by all users
//
// This should really go in GLLibraryEGL.cpp but we currently reference
// APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
// will come in subsequent patches on Bug 732865
#define APITRACE_LIB "/data/local/tmp/egltrace.so"
#ifdef MOZ_WIDGET_ANDROID
#endif // MOZ_WIDGET_ANDROID
#endif // ANDROID
#ifdef ANDROID
// We only need to explicitly dlopen egltrace
// on android as we can use LD_PRELOAD or other tricks
// on other platforms. We look for it in /data/local
// as that's writeable by all users
//
// This should really go in GLLibraryEGL.cpp but we currently reference
// APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
// will come in subsequent patches on Bug 732865
#define APITRACE_LIB "/data/local/tmp/egltrace.so"
#endif
#endif
#if defined(MOZ_X11)
+80
View File
@@ -486,9 +486,16 @@ GLScreenBuffer::Swap(const gfx::IntSize& size)
//uint32_t srcPixel = ReadPixel(src);
//uint32_t destPixel = ReadPixel(dest);
//printf_stderr("Before: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel);
#ifdef DEBUG
GLContext::LocalErrorScope errorScope(*mGL);
#endif
SharedSurface::ProdCopy(src, dest, mFactory.get());
#ifdef DEBUG
MOZ_ASSERT(!errorScope.GetError());
#endif
//srcPixel = ReadPixel(src);
//destPixel = ReadPixel(dest);
//printf_stderr("After: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel);
@@ -611,6 +618,79 @@ GLScreenBuffer::IsReadFramebufferDefault() const
return SharedSurf()->mAttachType == AttachmentType::Screen;
}
////////////////////////////////////////////////////////////////////////
// Utils
static void
RenderbufferStorageBySamples(GLContext* aGL, GLsizei aSamples,
GLenum aInternalFormat, const gfx::IntSize& aSize)
{
if (aSamples) {
aGL->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
aSamples,
aInternalFormat,
aSize.width, aSize.height);
} else {
aGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
aInternalFormat,
aSize.width, aSize.height);
}
}
static GLuint
CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples,
const gfx::IntSize& aSize)
{
GLuint rb = 0;
aGL->fGenRenderbuffers(1, &rb);
ScopedBindRenderbuffer autoRB(aGL, rb);
RenderbufferStorageBySamples(aGL, aSamples, aFormat, aSize);
return rb;
}
static void
CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats,
const gfx::IntSize& aSize, bool aMultisample,
GLuint* aColorMSRB, GLuint* aDepthRB,
GLuint* aStencilRB)
{
GLsizei samples = aMultisample ? aFormats.samples : 0;
if (aColorMSRB) {
MOZ_ASSERT(aFormats.samples > 0);
MOZ_ASSERT(aFormats.color_rbFormat);
GLenum colorFormat = aFormats.color_rbFormat;
if (aGL->IsANGLE()) {
MOZ_ASSERT(colorFormat == LOCAL_GL_RGBA8);
colorFormat = LOCAL_GL_BGRA8_EXT;
}
*aColorMSRB = CreateRenderbuffer(aGL, colorFormat, samples, aSize);
}
if (aDepthRB &&
aStencilRB &&
aFormats.depthStencil)
{
*aDepthRB = CreateRenderbuffer(aGL, aFormats.depthStencil, samples, aSize);
*aStencilRB = *aDepthRB;
} else {
if (aDepthRB) {
MOZ_ASSERT(aFormats.depth);
*aDepthRB = CreateRenderbuffer(aGL, aFormats.depth, samples, aSize);
}
if (aStencilRB) {
MOZ_ASSERT(aFormats.stencil);
*aStencilRB = CreateRenderbuffer(aGL, aFormats.stencil, samples, aSize);
}
}
}
////////////////////////////////////////////////////////////////////////
// DrawBuffer
+1 -1
View File
@@ -26,7 +26,7 @@
namespace mozilla {
namespace layers {
class SharedSurfaceTextureClient;
}
} // namespace layers
namespace gl {
+10 -159
View File
@@ -41,17 +41,14 @@ CreatePBufferSurface(GLLibraryEGL* egl,
}
/*static*/ UniquePtr<SharedSurface_ANGLEShareHandle>
SharedSurface_ANGLEShareHandle::Create(GLContext* gl,
EGLContext context, EGLConfig config,
SharedSurface_ANGLEShareHandle::Create(GLContext* gl, EGLConfig config,
const gfx::IntSize& size, bool hasAlpha)
{
GLLibraryEGL* egl = &sEGLLibrary;
MOZ_ASSERT(egl);
MOZ_ASSERT(egl->IsExtensionSupported(
GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle));
if (!context || !config)
return nullptr;
MOZ_ASSERT(config);
EGLDisplay display = egl->Display();
EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, size);
@@ -82,8 +79,8 @@ SharedSurface_ANGLEShareHandle::Create(GLContext* gl,
}
typedef SharedSurface_ANGLEShareHandle ptrT;
UniquePtr<ptrT> ret( new ptrT(gl, egl, size, hasAlpha, context,
pbuffer, shareHandle, keyedMutex, fence) );
UniquePtr<ptrT> ret( new ptrT(gl, egl, size, hasAlpha, pbuffer, shareHandle,
keyedMutex, fence) );
return Move(ret);
}
@@ -97,7 +94,6 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
GLLibraryEGL* egl,
const gfx::IntSize& size,
bool hasAlpha,
EGLContext context,
EGLSurface pbuffer,
HANDLE shareHandle,
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
@@ -109,7 +105,6 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
hasAlpha,
true)
, mEGL(egl)
, mContext(context)
, mPBuffer(pbuffer)
, mShareHandle(shareHandle)
, mKeyedMutex(keyedMutex)
@@ -283,137 +278,6 @@ SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor(layers::SurfaceDescriptor* c
////////////////////////////////////////////////////////////////////////////////
// Factory
static void
FillPBufferAttribs_ByBits(nsTArray<EGLint>& aAttrs,
int redBits, int greenBits,
int blueBits, int alphaBits,
int depthBits, int stencilBits)
{
aAttrs.Clear();
#if defined(A1) || defined(A2)
#error The temp-macro names we want are already defined.
#endif
#define A1(_x) do { aAttrs.AppendElement(_x); } while (0)
#define A2(_x,_y) do { A1(_x); A1(_y); } while (0)
A2(LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT);
A2(LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT);
A2(LOCAL_EGL_RED_SIZE, redBits);
A2(LOCAL_EGL_GREEN_SIZE, greenBits);
A2(LOCAL_EGL_BLUE_SIZE, blueBits);
A2(LOCAL_EGL_ALPHA_SIZE, alphaBits);
A2(LOCAL_EGL_DEPTH_SIZE, depthBits);
A2(LOCAL_EGL_STENCIL_SIZE, stencilBits);
A1(LOCAL_EGL_NONE);
#undef A1
#undef A2
}
static void
FillPBufferAttribs_BySizes(nsTArray<EGLint>& attribs,
bool bpp16, bool hasAlpha,
int depthBits, int stencilBits)
{
int red = 0;
int green = 0;
int blue = 0;
int alpha = 0;
if (bpp16) {
if (hasAlpha) {
red = green = blue = alpha = 4;
} else {
red = 5;
green = 6;
blue = 5;
}
} else {
red = green = blue = 8;
if (hasAlpha)
alpha = 8;
}
FillPBufferAttribs_ByBits(attribs, red, green, blue, alpha, depthBits,
stencilBits);
}
static bool
DoesAttribBitsMatchCapBool(GLLibraryEGL* egl, EGLConfig config, EGLint attrib,
bool capBool)
{
EGLint bits = 0;
egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits);
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
bool hasBits = !!bits;
return hasBits == capBool;
}
static EGLConfig
ChooseConfig(GLContext* gl, GLLibraryEGL* egl, const SurfaceCaps& caps)
{
MOZ_ASSERT(egl);
MOZ_ASSERT(caps.color);
// We might want 24-bit depth, but we're only (fairly) sure to get 16-bit.
int depthBits = caps.depth ? 16 : 0;
int stencilBits = caps.stencil ? 8 : 0;
// Ok, now we have everything.
nsTArray<EGLint> attribs(32);
FillPBufferAttribs_BySizes(attribs, caps.bpp16, caps.alpha, depthBits,
stencilBits);
// Time to try to get this config:
EGLConfig configs[64];
int numConfigs = sizeof(configs)/sizeof(EGLConfig);
int foundConfigs = 0;
if (!egl->fChooseConfig(egl->Display(), attribs.Elements(), configs,
numConfigs, &foundConfigs) ||
!foundConfigs)
{
NS_WARNING("No configs found for the requested formats.");
return EGL_NO_CONFIG;
}
// The requests passed to ChooseConfig are treated as minimums. If you ask
// for 0 bits of alpha, we might still get 8 bits.
EGLConfig config = EGL_NO_CONFIG;
for (int i = 0; i < foundConfigs; i++) {
EGLConfig cur = configs[i];
if (!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_ALPHA_SIZE,
caps.alpha) ||
!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_DEPTH_SIZE,
caps.depth) ||
!DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_STENCIL_SIZE,
caps.stencil))
{
continue;
}
config = cur;
break;
}
if (config == EGL_NO_CONFIG) {
NS_WARNING("No acceptable EGLConfig found.");
return EGL_NO_CONFIG;
}
if (gl->DebugMode()) {
egl->DumpEGLConfig(config);
}
return config;
}
/*static*/ UniquePtr<SurfaceFactory_ANGLEShareHandle>
SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
@@ -427,13 +291,10 @@ SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps,
if (!egl->IsExtensionSupported(ext))
return nullptr;
bool success;
EGLConfig config = GLContextEGL::Cast(gl)->mConfig;
typedef SurfaceFactory_ANGLEShareHandle ptrT;
UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, egl, &success) );
if (!success)
return nullptr;
UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, egl, config) );
return Move(ret);
}
@@ -442,22 +303,12 @@ SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags,
GLLibraryEGL* egl,
bool* const out_success)
EGLConfig config)
: SurfaceFactory(SharedSurfaceType::EGLSurfaceANGLE, gl, caps, allocator, flags)
, mProdGL(gl)
, mEGL(egl)
{
MOZ_ASSERT(out_success);
*out_success = false;
mContext = GLContextEGL::Cast(mProdGL)->GetEGLContext();
mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps);
if (mConfig == EGL_NO_CONFIG)
return;
MOZ_ASSERT(mConfig && mContext);
*out_success = true;
}
, mConfig(config)
{ }
} /* namespace gl */
} /* namespace mozilla */
+3 -9
View File
@@ -23,7 +23,6 @@ class SharedSurface_ANGLEShareHandle
{
public:
static UniquePtr<SharedSurface_ANGLEShareHandle> Create(GLContext* gl,
EGLContext context,
EGLConfig config,
const gfx::IntSize& size,
bool hasAlpha);
@@ -36,7 +35,6 @@ public:
protected:
GLLibraryEGL* const mEGL;
const EGLContext mContext;
const EGLSurface mPBuffer;
public:
const HANDLE mShareHandle;
@@ -51,7 +49,6 @@ protected:
GLLibraryEGL* egl,
const gfx::IntSize& size,
bool hasAlpha,
EGLContext context,
EGLSurface pbuffer,
HANDLE shareHandle,
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
@@ -94,8 +91,7 @@ class SurfaceFactory_ANGLEShareHandle
protected:
GLContext* const mProdGL;
GLLibraryEGL* const mEGL;
EGLContext mContext;
EGLConfig mConfig;
const EGLConfig mConfig;
public:
static UniquePtr<SurfaceFactory_ANGLEShareHandle> Create(GLContext* gl,
@@ -107,13 +103,11 @@ protected:
SurfaceFactory_ANGLEShareHandle(GLContext* gl, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags, GLLibraryEGL* egl,
bool* const out_success);
EGLConfig config);
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
bool hasAlpha = mReadCaps.alpha;
return SharedSurface_ANGLEShareHandle::Create(mProdGL,
mContext, mConfig,
size, hasAlpha);
return SharedSurface_ANGLEShareHandle::Create(mProdGL, mConfig, size, hasAlpha);
}
};
+1 -1
View File
@@ -220,7 +220,7 @@ SurfaceFactory_EGLImage::Create(GLContext* prodGL, const SurfaceCaps& caps,
const RefPtr<layers::ISurfaceAllocator>& allocator,
const layers::TextureFlags& flags)
{
EGLContext context = GLContextEGL::Cast(prodGL)->GetEGLContext();
EGLContext context = GLContextEGL::Cast(prodGL)->mContext;
typedef SurfaceFactory_EGLImage ptrT;
UniquePtr<ptrT> ret;
+1 -4
View File
@@ -27,10 +27,7 @@ SharedSurface_Basic::Create(GLContext* gl,
gl->MakeCurrent();
GLContext::LocalErrorScope localError(*gl);
GLuint tex = CreateTexture(gl, formats.color_texInternalFormat,
formats.color_texFormat,
formats.color_texType,
size);
GLuint tex = CreateTextureForOffscreen(gl, formats, size);
GLenum err = localError.GetError();
MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY);
+7 -7
View File
@@ -71,7 +71,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'WGLLibrary.h',
]
UNIFIED_SOURCES += [
'GLContextProviderEGL.cpp',
'GLContextProviderWGL.cpp',
'SharedSurfaceANGLE.cpp',
]
if CONFIG['MOZ_ENABLE_SKIA_GPU']:
@@ -113,10 +113,6 @@ elif gl_provider == 'GLX':
EXPORTS += [
'SharedSurfaceGLX.h'
]
else:
UNIFIED_SOURCES += [
'GLContextProvider%s.cpp' % gl_provider,
]
UNIFIED_SOURCES += [
'AndroidNativeWindow.cpp',
@@ -127,6 +123,7 @@ UNIFIED_SOURCES += [
'GLBlitHelper.cpp',
'GLContext.cpp',
'GLContextFeatures.cpp',
'GLContextProviderEGL.cpp',
'GLContextTypes.cpp',
'GLDebugUtils.cpp',
'GLLibraryEGL.cpp',
@@ -153,9 +150,12 @@ if CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']:
if CONFIG['MOZ_D3DCOMPILER_XP_DLL']:
DEFINES['MOZ_D3DCOMPILER_XP_DLL'] = CONFIG['MOZ_D3DCOMPILER_XP_DLL']
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
CXXFLAGS += CONFIG['TK_CFLAGS']
CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
CFLAGS += CONFIG['TK_CFLAGS']
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
if CONFIG['OS_ARCH'] == 'WINNT':
del DEFINES['UNICODE']
+1 -1
View File
@@ -1144,7 +1144,7 @@ gfxFT2FontList::FindFonts()
gfxFontCache *fc = gfxFontCache::GetCache();
if (fc)
fc->AgeAllGenerations();
mPrefFonts.Clear();
ClearLangGroupPrefFonts();
mCodepointsWithNoFonts.reset();
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
+2
View File
@@ -410,6 +410,7 @@ public:
uint32_t fallbackSystem;
uint32_t textrunConst;
uint32_t textrunDestr;
uint32_t genericLookups;
};
uint32_t reflowCount;
@@ -443,6 +444,7 @@ public:
cumulative.fallbackSystem += current.fallbackSystem;
cumulative.textrunConst += current.textrunConst;
cumulative.textrunDestr += current.textrunDestr;
cumulative.genericLookups += current.genericLookups;
memset(&current, 0, sizeof(current));
}
};
+12
View File
@@ -210,4 +210,16 @@ enum {
#define NS_FONT_SUB_SUPER_SMALL_SIZE (20.0)
#define NS_FONT_SUB_SUPER_LARGE_SIZE (45.0)
// pref lang id's for font prefs
enum eFontPrefLang {
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) eFontPrefLang_ ## enum_id_
#include "gfxFontPrefLangList.h"
#undef FONT_PREF_LANG
, eFontPrefLang_CJKSet // special code for CJK set
, eFontPrefLang_First = eFontPrefLang_Western
, eFontPrefLang_Last = eFontPrefLang_Others
, eFontPrefLang_Count = (eFontPrefLang_Last - eFontPrefLang_First + 1)
};
#endif
+3 -3
View File
@@ -1334,9 +1334,9 @@ gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
uint32_t minDistance = 0xffffffff;
gfxFontEntry* matched = nullptr;
// iterate in reverse order so that the last-defined font is the first one
// in the fontlist used for matching, as per CSS Fonts spec
for (int32_t i = count - 1; i >= 0; i--) {
// iterate in forward order so that faces like 'Bold' are matched before
// matching style distance faces such as 'Bold Outline' (see bug 1185812)
for (uint32_t i = 0; i < count; i++) {
fe = mAvailableFonts[i];
uint32_t distance =
WeightDistance(aFontStyle.weight, fe->Weight()) +
+6 -2
View File
@@ -29,7 +29,7 @@ enum FontFamilyType {
eFamily_named_quoted,
// generics
eFamily_serif,
eFamily_serif, // pref font code relies on this ordering!!!
eFamily_sans_serif,
eFamily_monospace,
eFamily_cursive,
@@ -37,7 +37,11 @@ enum FontFamilyType {
// special
eFamily_moz_variable,
eFamily_moz_fixed
eFamily_moz_fixed,
eFamily_generic_first = eFamily_serif,
eFamily_generic_last = eFamily_fantasy,
eFamily_generic_count = (eFamily_fantasy - eFamily_serif + 1)
};
enum QuotedName { eQuotedName, eUnquotedName };
+139 -5
View File
@@ -25,6 +25,9 @@
#include "gfxFontconfigUtils.h"
#include "gfxUserFontSet.h"
#include "gfxFontConstants.h"
#include "nsGkAtoms.h"
#include "nsILanguageAtomService.h"
#include "nsServiceManagerUtils.h"
#include <cairo.h>
#include <cairo-ft.h>
@@ -1281,9 +1284,140 @@ gfxPangoFontGroup::Copy(const gfxFontStyle *aStyle)
}
void
gfxPangoFontGroup::FindPlatformFont(const nsAString& fontName,
bool aUseFontSet,
void *aClosure)
gfxPangoFontGroup::FindGenericFontsPFG(FontFamilyType aGenericType,
nsIAtom *aLanguage,
void *aClosure)
{
nsAutoTArray<nsString, 5> resolvedGenerics;
ResolveGenericFontNamesPFG(aGenericType, aLanguage, resolvedGenerics);
uint32_t g = 0, numGenerics = resolvedGenerics.Length();
for (g = 0; g < numGenerics; g++) {
FindPlatformFontPFG(resolvedGenerics[g], false, aClosure);
}
}
/* static */ void
gfxPangoFontGroup::ResolveGenericFontNamesPFG(FontFamilyType aGenericType,
nsIAtom *aLanguage,
nsTArray<nsString>& aGenericFamilies)
{
static const char kGeneric_serif[] = "serif";
static const char kGeneric_sans_serif[] = "sans-serif";
static const char kGeneric_monospace[] = "monospace";
static const char kGeneric_cursive[] = "cursive";
static const char kGeneric_fantasy[] = "fantasy";
// treat -moz-fixed as monospace
if (aGenericType == eFamily_moz_fixed) {
aGenericType = eFamily_monospace;
}
// type should be standard generic type at this point
NS_ASSERTION(aGenericType >= eFamily_serif &&
aGenericType <= eFamily_fantasy,
"standard generic font family type required");
// create the lang string
nsIAtom *langGroupAtom = nullptr;
nsAutoCString langGroupString;
if (aLanguage) {
if (!gLangService) {
CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService);
}
if (gLangService) {
nsresult rv;
langGroupAtom = gLangService->GetLanguageGroup(aLanguage, &rv);
}
}
if (!langGroupAtom) {
langGroupAtom = nsGkAtoms::Unicode;
}
langGroupAtom->ToUTF8String(langGroupString);
// map generic type to string
const char *generic = nullptr;
switch (aGenericType) {
case eFamily_serif:
generic = kGeneric_serif;
break;
case eFamily_sans_serif:
generic = kGeneric_sans_serif;
break;
case eFamily_monospace:
generic = kGeneric_monospace;
break;
case eFamily_cursive:
generic = kGeneric_cursive;
break;
case eFamily_fantasy:
generic = kGeneric_fantasy;
break;
default:
break;
}
if (!generic) {
return;
}
aGenericFamilies.Clear();
// load family for "font.name.generic.lang"
nsAutoCString prefFontName("font.name.");
prefFontName.Append(generic);
prefFontName.Append('.');
prefFontName.Append(langGroupString);
gfxFontUtils::AppendPrefsFontList(prefFontName.get(),
aGenericFamilies);
// if lang has pref fonts, also load fonts for "font.name-list.generic.lang"
if (!aGenericFamilies.IsEmpty()) {
nsAutoCString prefFontListName("font.name-list.");
prefFontListName.Append(generic);
prefFontListName.Append('.');
prefFontListName.Append(langGroupString);
gfxFontUtils::AppendPrefsFontList(prefFontListName.get(),
aGenericFamilies);
}
#if 0 // dump out generic mappings
printf("%s ===> ", prefFontName.get());
for (uint32_t k = 0; k < aGenericFamilies.Length(); k++) {
if (k > 0) printf(", ");
printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]).get());
}
printf("\n");
#endif
}
void gfxPangoFontGroup::EnumerateFontListPFG(nsIAtom *aLanguage, void *aClosure)
{
// initialize fonts in the font family list
const nsTArray<FontFamilyName>& fontlist = mFamilyList.GetFontlist();
// lookup fonts in the fontlist
uint32_t i, numFonts = fontlist.Length();
for (i = 0; i < numFonts; i++) {
const FontFamilyName& name = fontlist[i];
if (name.IsNamed()) {
FindPlatformFontPFG(name.mName, true, aClosure);
} else {
FindGenericFontsPFG(name.mType, aLanguage, aClosure);
}
}
// if necessary, append default generic onto the end
if (mFamilyList.GetDefaultFontType() != eFamily_none &&
!mFamilyList.HasDefaultGeneric()) {
FindGenericFontsPFG(mFamilyList.GetDefaultFontType(),
aLanguage, aClosure);
}
}
void
gfxPangoFontGroup::FindPlatformFontPFG(const nsAString& fontName,
bool aUseFontSet,
void *aClosure)
{
nsTArray<nsString> *list = static_cast<nsTArray<nsString>*>(aClosure);
@@ -1360,8 +1494,8 @@ gfxPangoFontGroup::MakeFontSet(PangoLanguage *aLang, gfxFloat aSizeAdjustFactor,
}
nsAutoTArray<nsString, 20> fcFamilyList;
EnumerateFontList(langGroup ? langGroup.get() : mStyle.language.get(),
&fcFamilyList);
EnumerateFontListPFG(langGroup ? langGroup.get() : mStyle.language.get(),
&fcFamilyList);
// To consider: A fontset cache here could be helpful.
+21 -3
View File
@@ -94,9 +94,27 @@ private:
return mSizeAdjustFactor;
}
virtual void FindPlatformFont(const nsAString& aName,
bool aUseFontSet,
void *aClosure);
// old helper methods from gfxFontGroup, moved here so that those methods
// can be revamped without affecting the legacy code here
// iterate over the fontlist, lookup names and expand generics
void EnumerateFontListPFG(nsIAtom *aLanguage, void *aClosure);
// expand a generic to a list of specific names based on prefs
void FindGenericFontsPFG(mozilla::FontFamilyType aGenericType,
nsIAtom *aLanguage,
void *aClosure);
// lookup and add a font with a given name (i.e. *not* a generic!)
void FindPlatformFontPFG(const nsAString& aName,
bool aUseFontSet,
void *aClosure);
static void
ResolveGenericFontNamesPFG(mozilla::FontFamilyType aGenericType,
nsIAtom *aLanguage,
nsTArray<nsString>& aGenericFamilies);
friend class gfxSystemFcFontEntry;
static FT_Library GetFTLibrary();
-312
View File
@@ -364,27 +364,6 @@ MemoryPressureObserver::Observe(nsISupports *aSubject,
return NS_OK;
}
// xxx - this can probably be eliminated by reworking pref font handling code
static const char *gPrefLangNames[] = {
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) str_
#include "gfxFontPrefLangList.h"
#undef FONT_PREF_LANG
};
static nsIAtom* PrefLangToLangGroups(uint32_t aIndex)
{
// static array here avoids static constructor
static nsIAtom* gPrefLangToLangGroups[] = {
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) nsGkAtoms::atom_id_
#include "gfxFontPrefLangList.h"
#undef FONT_PREF_LANG
};
return aIndex < ArrayLength(gPrefLangToLangGroups)
? gPrefLangToLangGroups[aIndex]
: nsGkAtoms::Unicode;
}
gfxPlatform::gfxPlatform()
: mTileWidth(-1)
, mTileHeight(-1)
@@ -1364,160 +1343,6 @@ gfxPlatform::MakePlatformFont(const nsAString& aFontName,
return nullptr;
}
bool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray[], uint32_t aLangArrayLen, PrefFontCallback aCallback,
void *aClosure)
{
NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
uint32_t i;
for (i = 0; i < aLangArrayLen; i++) {
eFontPrefLang prefLang = aLangArray[i];
const char *langGroup = GetPrefLangName(prefLang);
nsAutoCString prefName;
prefName.AssignLiteral("font.default.");
prefName.Append(langGroup);
nsAdoptingCString genericDotLang = Preferences::GetCString(prefName.get());
genericDotLang.Append('.');
genericDotLang.Append(langGroup);
// fetch font.name.xxx value
prefName.AssignLiteral("font.name.");
prefName.Append(genericDotLang);
nsAdoptingCString nameValue = Preferences::GetCString(prefName.get());
if (nameValue) {
if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(nameValue), aClosure))
return false;
}
// fetch font.name-list.xxx value
prefName.AssignLiteral("font.name-list.");
prefName.Append(genericDotLang);
nsAdoptingCString nameListValue = Preferences::GetCString(prefName.get());
if (nameListValue && !nameListValue.Equals(nameValue)) {
const char kComma = ',';
const char *p, *p_end;
nsAutoCString list(nameListValue);
list.BeginReading(p);
list.EndReading(p_end);
while (p < p_end) {
while (nsCRT::IsAsciiSpace(*p)) {
if (++p == p_end)
break;
}
if (p == p_end)
break;
const char *start = p;
while (++p != p_end && *p != kComma)
/* nothing */ ;
nsAutoCString fontName(Substring(start, p));
fontName.CompressWhitespace(false, true);
if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(fontName), aClosure))
return false;
p++;
}
}
}
return true;
}
eFontPrefLang
gfxPlatform::GetFontPrefLangFor(const char* aLang)
{
if (!aLang || !aLang[0]) {
return eFontPrefLang_Others;
}
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); ++i) {
if (!PL_strcasecmp(gPrefLangNames[i], aLang)) {
return eFontPrefLang(i);
}
}
return eFontPrefLang_Others;
}
eFontPrefLang
gfxPlatform::GetFontPrefLangFor(nsIAtom *aLang)
{
if (!aLang)
return eFontPrefLang_Others;
nsAutoCString lang;
aLang->ToUTF8String(lang);
return GetFontPrefLangFor(lang.get());
}
nsIAtom*
gfxPlatform::GetLangGroupForPrefLang(eFontPrefLang aLang)
{
// the special CJK set pref lang should be resolved into separate
// calls to individual CJK pref langs before getting here
NS_ASSERTION(aLang != eFontPrefLang_CJKSet, "unresolved CJK set pref lang");
return PrefLangToLangGroups(uint32_t(aLang));
}
const char*
gfxPlatform::GetPrefLangName(eFontPrefLang aLang)
{
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
return gPrefLangNames[uint32_t(aLang)];
}
return nullptr;
}
eFontPrefLang
gfxPlatform::GetFontPrefLangFor(uint8_t aUnicodeRange)
{
switch (aUnicodeRange) {
case kRangeSetLatin: return eFontPrefLang_Western;
case kRangeCyrillic: return eFontPrefLang_Cyrillic;
case kRangeGreek: return eFontPrefLang_Greek;
case kRangeHebrew: return eFontPrefLang_Hebrew;
case kRangeArabic: return eFontPrefLang_Arabic;
case kRangeThai: return eFontPrefLang_Thai;
case kRangeKorean: return eFontPrefLang_Korean;
case kRangeJapanese: return eFontPrefLang_Japanese;
case kRangeSChinese: return eFontPrefLang_ChineseCN;
case kRangeTChinese: return eFontPrefLang_ChineseTW;
case kRangeDevanagari: return eFontPrefLang_Devanagari;
case kRangeTamil: return eFontPrefLang_Tamil;
case kRangeArmenian: return eFontPrefLang_Armenian;
case kRangeBengali: return eFontPrefLang_Bengali;
case kRangeCanadian: return eFontPrefLang_Canadian;
case kRangeEthiopic: return eFontPrefLang_Ethiopic;
case kRangeGeorgian: return eFontPrefLang_Georgian;
case kRangeGujarati: return eFontPrefLang_Gujarati;
case kRangeGurmukhi: return eFontPrefLang_Gurmukhi;
case kRangeKhmer: return eFontPrefLang_Khmer;
case kRangeMalayalam: return eFontPrefLang_Malayalam;
case kRangeOriya: return eFontPrefLang_Oriya;
case kRangeTelugu: return eFontPrefLang_Telugu;
case kRangeKannada: return eFontPrefLang_Kannada;
case kRangeSinhala: return eFontPrefLang_Sinhala;
case kRangeTibetan: return eFontPrefLang_Tibetan;
case kRangeSetCJK: return eFontPrefLang_CJKSet;
default: return eFontPrefLang_Others;
}
}
bool
gfxPlatform::IsLangCJK(eFontPrefLang aLang)
{
switch (aLang) {
case eFontPrefLang_Japanese:
case eFontPrefLang_ChineseTW:
case eFontPrefLang_ChineseCN:
case eFontPrefLang_ChineseHK:
case eFontPrefLang_Korean:
case eFontPrefLang_CJKSet:
return true;
default:
return false;
}
}
mozilla::layers::DiagnosticTypes
gfxPlatform::GetLayerDiagnosticTypes()
{
@@ -1537,143 +1362,6 @@ gfxPlatform::GetLayerDiagnosticTypes()
return type;
}
void
gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{
if (IsLangCJK(aCharLang)) {
AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
} else {
AppendPrefLang(aPrefLangs, aLen, aCharLang);
}
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
}
void
gfxPlatform::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{
// prefer the lang specified by the page *if* CJK
if (IsLangCJK(aPageLang)) {
AppendPrefLang(aPrefLangs, aLen, aPageLang);
}
// if not set up, set up the default CJK order, based on accept lang settings and locale
if (mCJKPrefLangs.Length() == 0) {
// temp array
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
uint32_t tempLen = 0;
// Add the CJK pref fonts from accept languages, the order should be same order
nsAdoptingCString list = Preferences::GetLocalizedCString("intl.accept_languages");
if (!list.IsEmpty()) {
const char kComma = ',';
const char *p, *p_end;
list.BeginReading(p);
list.EndReading(p_end);
while (p < p_end) {
while (nsCRT::IsAsciiSpace(*p)) {
if (++p == p_end)
break;
}
if (p == p_end)
break;
const char *start = p;
while (++p != p_end && *p != kComma)
/* nothing */ ;
nsAutoCString lang(Substring(start, p));
lang.CompressWhitespace(false, true);
eFontPrefLang fpl = gfxPlatform::GetFontPrefLangFor(lang.get());
switch (fpl) {
case eFontPrefLang_Japanese:
case eFontPrefLang_Korean:
case eFontPrefLang_ChineseCN:
case eFontPrefLang_ChineseHK:
case eFontPrefLang_ChineseTW:
AppendPrefLang(tempPrefLangs, tempLen, fpl);
break;
default:
break;
}
p++;
}
}
do { // to allow 'break' to abort this block if a call fails
nsresult rv;
nsCOMPtr<nsILocaleService> ls =
do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
break;
nsCOMPtr<nsILocale> appLocale;
rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
if (NS_FAILED(rv))
break;
nsString localeStr;
rv = appLocale->
GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
if (NS_FAILED(rv))
break;
const nsAString& lang = Substring(localeStr, 0, 2);
if (lang.EqualsLiteral("ja")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
} else if (lang.EqualsLiteral("zh")) {
const nsAString& region = Substring(localeStr, 3, 2);
if (region.EqualsLiteral("CN")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
} else if (region.EqualsLiteral("TW")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
} else if (region.EqualsLiteral("HK")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
}
} else if (lang.EqualsLiteral("ko")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
}
} while (0);
// last resort... (the order is same as old gfx.)
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
// copy into the cached array
uint32_t j;
for (j = 0; j < tempLen; j++) {
mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
}
}
// append in cached CJK langs
uint32_t i, numCJKlangs = mCJKPrefLangs.Length();
for (i = 0; i < numCJKlangs; i++) {
AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
}
}
void
gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang)
{
if (aLen >= kMaxLenPrefLangList) return;
// make sure
uint32_t i = 0;
while (i < aLen && aPrefLangs[i] != aAddLang) {
i++;
}
if (i == aLen) {
aPrefLangs[aLen] = aAddLang;
aLen++;
}
}
void
gfxPlatform::InitBackendPrefs(uint32_t aCanvasBitmask, BackendType aCanvasDefault,
uint32_t aContentBitmask, BackendType aContentDefault)
-48
View File
@@ -70,15 +70,6 @@ BackendTypeBit(BackendType b)
extern cairo_user_data_key_t kDrawTarget;
// pref lang id's for font prefs
enum eFontPrefLang {
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) eFontPrefLang_ ## enum_id_
#include "gfxFontPrefLangList.h"
#undef FONT_PREF_LANG
, eFontPrefLang_CJKSet // special code for CJK set
};
enum eCMSMode {
eCMSMode_Off = 0, // No color management
eCMSMode_All = 1, // Color manage everything
@@ -436,41 +427,6 @@ public:
virtual bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) { return false; }
// in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
/**
* Iterate over pref fonts given a list of lang groups. For a single lang
* group, multiple pref fonts are possible. If error occurs, returns false,
* true otherwise. Callback returns false to abort process.
*/
typedef bool (*PrefFontCallback) (eFontPrefLang aLang, const nsAString& aName,
void *aClosure);
static bool ForEachPrefFont(eFontPrefLang aLangArray[], uint32_t aLangArrayLen,
PrefFontCallback aCallback,
void *aClosure);
// convert a lang group to enum constant (i.e. "zh-TW" ==> eFontPrefLang_ChineseTW)
static eFontPrefLang GetFontPrefLangFor(const char* aLang);
// convert a lang group atom to enum constant
static eFontPrefLang GetFontPrefLangFor(nsIAtom *aLang);
// convert an enum constant to a lang group atom
static nsIAtom* GetLangGroupForPrefLang(eFontPrefLang aLang);
// convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW ==> "zh-TW")
static const char* GetPrefLangName(eFontPrefLang aLang);
// map a Unicode range (based on char code) to a font language for Preferences
static eFontPrefLang GetFontPrefLangFor(uint8_t aUnicodeRange);
// returns true if a pref lang is CJK
static bool IsLangCJK(eFontPrefLang aLang);
// helper method to add a pref lang to an array, if not already in array
static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang);
// returns a list of commonly used fonts for a given character
// these are *possible* matches, no cmap-checking is done at this level
virtual void GetCommonFallbackFonts(uint32_t /*aCh*/, uint32_t /*aNextCh*/,
@@ -677,9 +633,6 @@ protected:
gfxPlatform();
virtual ~gfxPlatform();
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen,
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
/**
* Initialized hardware vsync based on each platform.
*/
@@ -794,7 +747,6 @@ private:
void PopulateScreenInfo();
nsRefPtr<gfxASurface> mScreenReferenceSurface;
nsTArray<uint32_t> mCJKPrefLangs;
nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
nsCOMPtr<nsIObserver> mFontPrefsObserver;
nsCOMPtr<nsIObserver> mMemoryPressureObserver;
+460 -25
View File
@@ -9,6 +9,10 @@
#include "gfxTextRun.h"
#include "gfxUserFontSet.h"
#include "nsCRT.h"
#include "nsGkAtoms.h"
#include "nsILocaleService.h"
#include "nsServiceManagerUtils.h"
#include "nsUnicharUtils.h"
#include "nsUnicodeRange.h"
#include "nsUnicodeProperties.h"
@@ -94,6 +98,16 @@ static const char* kObservedPrefs[] = {
nullptr
};
// xxx - this can probably be eliminated by reworking pref font handling code
static const char *gPrefLangNames[] = {
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) str_
#include "gfxFontPrefLangList.h"
#undef FONT_PREF_LANG
};
static_assert(MOZ_ARRAY_LENGTH(gPrefLangNames) == uint32_t(eFontPrefLang_Count),
"size of pref lang name array doesn't match pref lang enum size");
class gfxFontListPrefObserver final : public nsIObserver {
~gfxFontListPrefObserver() {}
public:
@@ -113,7 +127,7 @@ gfxFontListPrefObserver::Observe(nsISupports *aSubject,
NS_ASSERTION(!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID), "invalid topic");
// XXX this could be made to only clear out the cache for the prefs that were changed
// but it probably isn't that big a deal.
gfxPlatformFontList::PlatformFontList()->ClearPrefFonts();
gfxPlatformFontList::PlatformFontList()->ClearLangGroupPrefFonts();
gfxFontCache::GetCache()->AgeAllGenerations();
return NS_OK;
}
@@ -162,7 +176,7 @@ gfxPlatformFontList::MemoryReporter::CollectReports(
gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
: mFontFamilies(64), mOtherFamilyNames(16),
mPrefFonts(8), mBadUnderlineFamilyNames(8), mSharedCmaps(8),
mBadUnderlineFamilyNames(8), mSharedCmaps(8),
mStartIndex(0), mIncrement(1), mNumFamilies(0), mFontlistInitCount(0)
{
mOtherFamilyNamesInitialized = false;
@@ -187,11 +201,15 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
gfxPlatformFontList::~gfxPlatformFontList()
{
mSharedCmaps.Clear();
ClearLangGroupPrefFonts();
NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs);
NS_RELEASE(gFontListPrefObserver);
}
// number of CSS generic font families
const uint32_t kNumGenerics = 5;
nsresult
gfxPlatformFontList::InitFontList()
{
@@ -216,7 +234,7 @@ gfxPlatformFontList::InitFontList()
mExtraNames->mPostscriptNames.Clear();
}
mFaceNameListsInitialized = false;
mPrefFonts.Clear();
ClearLangGroupPrefFonts();
mReplacementCharFallbackFamily = nullptr;
CancelLoader();
@@ -703,18 +721,6 @@ gfxPlatformFontList::FindFontForFamily(const nsAString& aFamily, const gfxFontSt
return nullptr;
}
bool
gfxPlatformFontList::GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> > *array)
{
return mPrefFonts.Get(uint32_t(aLangGroup), array);
}
void
gfxPlatformFontList::SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> >& array)
{
mPrefFonts.Put(uint32_t(aLangGroup), array);
}
void
gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName)
{
@@ -801,6 +807,419 @@ gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap)
}
}
void
gfxPlatformFontList::ResolveGenericFontNames(
FontFamilyType aGenericType,
eFontPrefLang aPrefLang,
nsTArray<nsRefPtr<gfxFontFamily>>* aGenericFamilies
)
{
const char* langGroupStr = GetPrefLangName(aPrefLang);
static const char kGeneric_serif[] = "serif";
static const char kGeneric_sans_serif[] = "sans-serif";
static const char kGeneric_monospace[] = "monospace";
static const char kGeneric_cursive[] = "cursive";
static const char kGeneric_fantasy[] = "fantasy";
// type should be standard generic type at this point
NS_ASSERTION(aGenericType >= eFamily_serif &&
aGenericType <= eFamily_fantasy,
"standard generic font family type required");
// map generic type to string
const char *generic = nullptr;
switch (aGenericType) {
case eFamily_serif:
generic = kGeneric_serif;
break;
case eFamily_sans_serif:
generic = kGeneric_sans_serif;
break;
case eFamily_monospace:
generic = kGeneric_monospace;
break;
case eFamily_cursive:
generic = kGeneric_cursive;
break;
case eFamily_fantasy:
generic = kGeneric_fantasy;
break;
default:
break;
}
if (!generic) {
return;
}
nsAutoTArray<nsString,4> genericFamilies;
// load family for "font.name.generic.lang"
nsAutoCString prefFontName("font.name.");
prefFontName.Append(generic);
prefFontName.Append('.');
prefFontName.Append(langGroupStr);
gfxFontUtils::AppendPrefsFontList(prefFontName.get(), genericFamilies);
// load fonts for "font.name-list.generic.lang"
nsAutoCString prefFontListName("font.name-list.");
prefFontListName.Append(generic);
prefFontListName.Append('.');
prefFontListName.Append(langGroupStr);
gfxFontUtils::AppendPrefsFontList(prefFontListName.get(), genericFamilies);
nsIAtom* langGroup = GetLangGroupForPrefLang(aPrefLang);
NS_ASSERTION(langGroup, "null lang group for pref lang");
// lookup and add platform fonts uniquely
for (const nsString& genericFamily : genericFamilies) {
nsRefPtr<gfxFontFamily> family =
FindFamily(genericFamily, langGroup, false);
if (family) {
bool notFound = true;
for (const gfxFontFamily* f : *aGenericFamilies) {
if (f == family) {
notFound = false;
break;
}
}
if (notFound) {
aGenericFamilies->AppendElement(family);
}
}
}
#if 0 // dump out generic mappings
printf("%s ===> ", prefFontName.get());
for (uint32_t k = 0; k < aGenericFamilies->Length(); k++) {
if (k > 0) printf(", ");
printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]->Name()).get());
}
printf("\n");
#endif
}
nsTArray<nsRefPtr<gfxFontFamily>>*
gfxPlatformFontList::GetPrefFontsLangGroup(mozilla::FontFamilyType aGenericType,
eFontPrefLang aPrefLang)
{
// treat -moz-fixed as monospace
if (aGenericType == eFamily_moz_fixed) {
aGenericType = eFamily_monospace;
}
PrefFontList* prefFonts = mLangGroupPrefFonts[aPrefLang][aGenericType];
if (MOZ_UNLIKELY(!prefFonts)) {
prefFonts = new PrefFontList;
ResolveGenericFontNames(aGenericType, aPrefLang, prefFonts);
mLangGroupPrefFonts[aPrefLang][aGenericType] = prefFonts;
}
return prefFonts;
}
void
gfxPlatformFontList::AddGenericFonts(mozilla::FontFamilyType aGenericType,
nsIAtom* aLanguage,
nsTArray<gfxFontFamily*>& aFamilyList)
{
// map lang ==> langGroup
nsIAtom *langGroup = nullptr;
if (aLanguage) {
if (!mLangService) {
mLangService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
}
if (mLangService) {
nsresult rv;
langGroup = mLangService->GetLanguageGroup(aLanguage, &rv);
}
}
if (!langGroup) {
langGroup = nsGkAtoms::Unicode;
}
// langGroup ==> prefLang
eFontPrefLang prefLang = GetFontPrefLangFor(langGroup);
// lookup pref fonts
nsTArray<nsRefPtr<gfxFontFamily>>* prefFonts =
GetPrefFontsLangGroup(aGenericType, prefLang);
if (!prefFonts->IsEmpty()) {
aFamilyList.AppendElements(*prefFonts);
}
}
static nsIAtom* PrefLangToLangGroups(uint32_t aIndex)
{
// static array here avoids static constructor
static nsIAtom* gPrefLangToLangGroups[] = {
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) nsGkAtoms::atom_id_
#include "gfxFontPrefLangList.h"
#undef FONT_PREF_LANG
};
return aIndex < ArrayLength(gPrefLangToLangGroups)
? gPrefLangToLangGroups[aIndex]
: nsGkAtoms::Unicode;
}
eFontPrefLang
gfxPlatformFontList::GetFontPrefLangFor(const char* aLang)
{
if (!aLang || !aLang[0]) {
return eFontPrefLang_Others;
}
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); ++i) {
if (!PL_strcasecmp(gPrefLangNames[i], aLang)) {
return eFontPrefLang(i);
}
}
return eFontPrefLang_Others;
}
eFontPrefLang
gfxPlatformFontList::GetFontPrefLangFor(nsIAtom *aLang)
{
if (!aLang)
return eFontPrefLang_Others;
nsAutoCString lang;
aLang->ToUTF8String(lang);
return GetFontPrefLangFor(lang.get());
}
nsIAtom*
gfxPlatformFontList::GetLangGroupForPrefLang(eFontPrefLang aLang)
{
// the special CJK set pref lang should be resolved into separate
// calls to individual CJK pref langs before getting here
NS_ASSERTION(aLang != eFontPrefLang_CJKSet, "unresolved CJK set pref lang");
return PrefLangToLangGroups(uint32_t(aLang));
}
const char*
gfxPlatformFontList::GetPrefLangName(eFontPrefLang aLang)
{
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
return gPrefLangNames[uint32_t(aLang)];
}
return nullptr;
}
eFontPrefLang
gfxPlatformFontList::GetFontPrefLangFor(uint8_t aUnicodeRange)
{
switch (aUnicodeRange) {
case kRangeSetLatin: return eFontPrefLang_Western;
case kRangeCyrillic: return eFontPrefLang_Cyrillic;
case kRangeGreek: return eFontPrefLang_Greek;
case kRangeHebrew: return eFontPrefLang_Hebrew;
case kRangeArabic: return eFontPrefLang_Arabic;
case kRangeThai: return eFontPrefLang_Thai;
case kRangeKorean: return eFontPrefLang_Korean;
case kRangeJapanese: return eFontPrefLang_Japanese;
case kRangeSChinese: return eFontPrefLang_ChineseCN;
case kRangeTChinese: return eFontPrefLang_ChineseTW;
case kRangeDevanagari: return eFontPrefLang_Devanagari;
case kRangeTamil: return eFontPrefLang_Tamil;
case kRangeArmenian: return eFontPrefLang_Armenian;
case kRangeBengali: return eFontPrefLang_Bengali;
case kRangeCanadian: return eFontPrefLang_Canadian;
case kRangeEthiopic: return eFontPrefLang_Ethiopic;
case kRangeGeorgian: return eFontPrefLang_Georgian;
case kRangeGujarati: return eFontPrefLang_Gujarati;
case kRangeGurmukhi: return eFontPrefLang_Gurmukhi;
case kRangeKhmer: return eFontPrefLang_Khmer;
case kRangeMalayalam: return eFontPrefLang_Malayalam;
case kRangeOriya: return eFontPrefLang_Oriya;
case kRangeTelugu: return eFontPrefLang_Telugu;
case kRangeKannada: return eFontPrefLang_Kannada;
case kRangeSinhala: return eFontPrefLang_Sinhala;
case kRangeTibetan: return eFontPrefLang_Tibetan;
case kRangeSetCJK: return eFontPrefLang_CJKSet;
default: return eFontPrefLang_Others;
}
}
bool
gfxPlatformFontList::IsLangCJK(eFontPrefLang aLang)
{
switch (aLang) {
case eFontPrefLang_Japanese:
case eFontPrefLang_ChineseTW:
case eFontPrefLang_ChineseCN:
case eFontPrefLang_ChineseHK:
case eFontPrefLang_Korean:
case eFontPrefLang_CJKSet:
return true;
default:
return false;
}
}
void
gfxPlatformFontList::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{
if (IsLangCJK(aCharLang)) {
AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
} else {
AppendPrefLang(aPrefLangs, aLen, aCharLang);
}
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
}
void
gfxPlatformFontList::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{
// prefer the lang specified by the page *if* CJK
if (IsLangCJK(aPageLang)) {
AppendPrefLang(aPrefLangs, aLen, aPageLang);
}
// if not set up, set up the default CJK order, based on accept lang settings and locale
if (mCJKPrefLangs.Length() == 0) {
// temp array
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
uint32_t tempLen = 0;
// Add the CJK pref fonts from accept languages, the order should be same order
nsAdoptingCString list = Preferences::GetLocalizedCString("intl.accept_languages");
if (!list.IsEmpty()) {
const char kComma = ',';
const char *p, *p_end;
list.BeginReading(p);
list.EndReading(p_end);
while (p < p_end) {
while (nsCRT::IsAsciiSpace(*p)) {
if (++p == p_end)
break;
}
if (p == p_end)
break;
const char *start = p;
while (++p != p_end && *p != kComma)
/* nothing */ ;
nsAutoCString lang(Substring(start, p));
lang.CompressWhitespace(false, true);
eFontPrefLang fpl = gfxPlatformFontList::GetFontPrefLangFor(lang.get());
switch (fpl) {
case eFontPrefLang_Japanese:
case eFontPrefLang_Korean:
case eFontPrefLang_ChineseCN:
case eFontPrefLang_ChineseHK:
case eFontPrefLang_ChineseTW:
AppendPrefLang(tempPrefLangs, tempLen, fpl);
break;
default:
break;
}
p++;
}
}
do { // to allow 'break' to abort this block if a call fails
nsresult rv;
nsCOMPtr<nsILocaleService> ls =
do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
break;
nsCOMPtr<nsILocale> appLocale;
rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
if (NS_FAILED(rv))
break;
nsString localeStr;
rv = appLocale->
GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
if (NS_FAILED(rv))
break;
const nsAString& lang = Substring(localeStr, 0, 2);
if (lang.EqualsLiteral("ja")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
} else if (lang.EqualsLiteral("zh")) {
const nsAString& region = Substring(localeStr, 3, 2);
if (region.EqualsLiteral("CN")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
} else if (region.EqualsLiteral("TW")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
} else if (region.EqualsLiteral("HK")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
}
} else if (lang.EqualsLiteral("ko")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
}
} while (0);
// last resort... (the order is same as old gfx.)
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
// copy into the cached array
uint32_t j;
for (j = 0; j < tempLen; j++) {
mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
}
}
// append in cached CJK langs
uint32_t i, numCJKlangs = mCJKPrefLangs.Length();
for (i = 0; i < numCJKlangs; i++) {
AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
}
}
void
gfxPlatformFontList::AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang)
{
if (aLen >= kMaxLenPrefLangList) return;
// make sure
uint32_t i = 0;
while (i < aLen && aPrefLangs[i] != aAddLang) {
i++;
}
if (i == aLen) {
aPrefLangs[aLen] = aAddLang;
aLen++;
}
}
mozilla::FontFamilyType
gfxPlatformFontList::GetDefaultGeneric(eFontPrefLang aLang)
{
// initialize lang group pref font defaults (i.e. serif/sans-serif)
if (MOZ_UNLIKELY(mDefaultGenericsLangGroup.IsEmpty())) {
mDefaultGenericsLangGroup.AppendElements(ArrayLength(gPrefLangNames));
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); i++) {
nsAutoCString prefDefaultFontType("font.default.");
prefDefaultFontType.Append(GetPrefLangName(eFontPrefLang(i)));
nsAdoptingCString serifOrSans =
Preferences::GetCString(prefDefaultFontType.get());
if (serifOrSans.EqualsLiteral("sans-serif")) {
mDefaultGenericsLangGroup[i] = eFamily_sans_serif;
} else {
mDefaultGenericsLangGroup[i] = eFamily_serif;
}
}
}
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
return mDefaultGenericsLangGroup[uint32_t(aLang)];
}
return eFamily_serif;
}
void
gfxPlatformFontList::GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames)
{
@@ -952,6 +1371,19 @@ gfxPlatformFontList::RebuildLocalFonts()
}
}
void
gfxPlatformFontList::ClearLangGroupPrefFonts()
{
for (uint32_t i = eFontPrefLang_First;
i < eFontPrefLang_First + eFontPrefLang_Count; i++) {
auto& prefFontsLangGroup = mLangGroupPrefFonts[i];
for (uint32_t j = eFamily_generic_first;
j < eFamily_generic_first + eFamily_generic_count; j++) {
prefFontsLangGroup[j] = nullptr;
}
}
}
// Support for memory reporting
// this is also used by subclasses that hold additional font tables
@@ -1008,21 +1440,24 @@ gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
aMallocSizeOf);
}
for (uint32_t i = eFontPrefLang_First;
i < eFontPrefLang_First + eFontPrefLang_Count; i++) {
auto& prefFontsLangGroup = mLangGroupPrefFonts[i];
for (uint32_t j = eFamily_generic_first;
j < eFamily_generic_first + eFamily_generic_count; j++) {
PrefFontList* pf = prefFontsLangGroup[j];
if (pf) {
aSizes->mFontListSize +=
pf->ShallowSizeOfExcludingThis(aMallocSizeOf);
}
}
}
aSizes->mFontListSize +=
mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
aSizes->mFontListSize +=
mFontFamiliesToLoad.ShallowSizeOfExcludingThis(aMallocSizeOf);
aSizes->mFontListSize +=
mPrefFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (auto iter = mPrefFonts.ConstIter(); !iter.Done(); iter.Next()) {
// Again, we only care about the size of the array itself; we don't
// follow the refPtrs stored in it, because they point to entries
// already owned and accounted-for by the main font list.
aSizes->mFontListSize +=
iter.Data().ShallowSizeOfExcludingThis(aMallocSizeOf);
}
aSizes->mFontListSize +=
mBadUnderlineFamilyNames.SizeOfExcludingThis(aMallocSizeOf);
+61 -7
View File
@@ -13,11 +13,15 @@
#include "gfxFontUtils.h"
#include "gfxFontInfoLoader.h"
#include "gfxFont.h"
#include "gfxFontConstants.h"
#include "gfxPlatform.h"
#include "gfxFontFamilyList.h"
#include "nsIMemoryReporter.h"
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/RangedArray.h"
#include "nsILanguageAtomService.h"
class CharMapHashKey : public PLDHashEntryHdr
{
@@ -116,7 +120,7 @@ public:
void UpdateFontList();
void ClearPrefFonts() { mPrefFonts.Clear(); }
void ClearLangGroupPrefFonts();
virtual void GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray);
@@ -131,9 +135,6 @@ public:
gfxFontEntry* FindFontForFamily(const nsAString& aFamily, const gfxFontStyle* aStyle, bool& aNeedsBold);
bool GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> > *array);
void SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> >& array);
// name lookup table methods
void AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName);
@@ -199,6 +200,43 @@ public:
aLoaderState = (uint32_t) mState;
}
virtual void
AddGenericFonts(mozilla::FontFamilyType aGenericType,
nsIAtom* aLanguage,
nsTArray<gfxFontFamily*>& aFamilyList);
nsTArray<nsRefPtr<gfxFontFamily>>*
GetPrefFontsLangGroup(mozilla::FontFamilyType aGenericType,
eFontPrefLang aPrefLang);
// in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
// convert a lang group to enum constant (i.e. "zh-TW" ==> eFontPrefLang_ChineseTW)
static eFontPrefLang GetFontPrefLangFor(const char* aLang);
// convert a lang group atom to enum constant
static eFontPrefLang GetFontPrefLangFor(nsIAtom *aLang);
// convert an enum constant to a lang group atom
static nsIAtom* GetLangGroupForPrefLang(eFontPrefLang aLang);
// convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW ==> "zh-TW")
static const char* GetPrefLangName(eFontPrefLang aLang);
// map a Unicode range (based on char code) to a font language for Preferences
static eFontPrefLang GetFontPrefLangFor(uint8_t aUnicodeRange);
// returns true if a pref lang is CJK
static bool IsLangCJK(eFontPrefLang aLang);
// helper method to add a pref lang to an array, if not already in array
static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang);
// default serif/sans-serif choice based on font.default.xxx prefs
mozilla::FontFamilyType
GetDefaultGeneric(eFontPrefLang aLang);
protected:
class MemoryReporter final : public nsIMemoryReporter
{
@@ -241,6 +279,9 @@ protected:
// if system fallback is used, no need to load all cmaps
virtual bool UsesSystemFallback() { return false; }
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen,
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
// verifies that a family contains a non-zero font count
gfxFontFamily* CheckFamily(gfxFontFamily *aFamily);
@@ -287,6 +328,11 @@ protected:
void RebuildLocalFonts();
void
ResolveGenericFontNames(mozilla::FontFamilyType aGenericType,
eFontPrefLang aPrefLang,
nsTArray<nsRefPtr<gfxFontFamily>>* aGenericFamilies);
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontFamilyTable;
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontEntry> FontEntryTable;
@@ -332,9 +378,13 @@ protected:
// localized family names missed when face name loading takes a long time
nsAutoPtr<nsTHashtable<nsStringHashKey> > mOtherNamesMissed;
// cached pref font lists
// maps list of family names ==> array of family entries, one per lang group
nsDataHashtable<nsUint32HashKey, nsTArray<nsRefPtr<gfxFontFamily> > > mPrefFonts;
typedef nsTArray<nsRefPtr<gfxFontFamily>> PrefFontList;
typedef mozilla::RangedArray<nsAutoPtr<PrefFontList>,
mozilla::eFamily_generic_first,
mozilla::eFamily_generic_count> PrefFontsForLangGroup;
mozilla::RangedArray<PrefFontsForLangGroup,
eFontPrefLang_First,
eFontPrefLang_Count> mLangGroupPrefFonts;
// when system-wide font lookup fails for a character, cache it to skip future searches
gfxSparseBitSet mCodepointsWithNoFonts;
@@ -360,6 +410,10 @@ protected:
uint32_t mFontlistInitCount; // num times InitFontList called
nsTHashtable<nsPtrHashKey<gfxUserFontSet> > mUserFontSetList;
nsCOMPtr<nsILanguageAtomService> mLangService;
nsTArray<uint32_t> mCJKPrefLangs;
nsTArray<mozilla::FontFamilyType> mDefaultGenericsLangGroup;
};
#endif /* GFXPLATFORMFONTLIST_H_ */
+145 -230
View File
@@ -222,7 +222,6 @@ gfxTextRun::SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength,
if (canBreak && !charGlyphs[i].IsClusterStart()) {
// This can happen ... there is no guarantee that our linebreaking rules
// align with the platform's idea of what constitutes a cluster.
NS_WARNING("Break suggested inside cluster!");
canBreak = CompressedGlyph::FLAG_BREAK_TYPE_NONE;
}
changed |= charGlyphs[i].SetCanBreakBefore(canBreak);
@@ -515,13 +514,13 @@ HasSyntheticBold(gfxTextRun *aRun, uint32_t aStart, uint32_t aLength)
return false;
}
// returns true if color is non-opaque (i.e. alpha != 1.0) or completely transparent, false otherwise
// if true, color is set on output
// Returns true if color is neither opaque nor transparent (i.e. alpha is not 0
// or 1), and false otherwise. If true, aCurrentColorOut is set on output.
static bool
HasNonOpaqueColor(gfxContext *aContext, Color& aCurrentColorOut)
HasNonOpaqueNonTransparentColor(gfxContext *aContext, Color& aCurrentColorOut)
{
if (aContext->GetDeviceColor(aCurrentColorOut)) {
if (0.0 < aCurrentColorOut.a && aCurrentColorOut.a < 1.0) {
if (0.f < aCurrentColorOut.a && aCurrentColorOut.a < 1.f) {
return true;
}
}
@@ -532,6 +531,7 @@ HasNonOpaqueColor(gfxContext *aContext, Color& aCurrentColorOut)
struct BufferAlphaColor {
explicit BufferAlphaColor(gfxContext *aContext)
: mContext(aContext)
, mAlpha(0.0)
{
}
@@ -603,6 +603,25 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
return;
}
// synthetic bolding draws glyphs twice ==> colors with opacity won't draw
// correctly unless first drawn without alpha
BufferAlphaColor syntheticBoldBuffer(aContext);
Color currentColor;
bool needToRestore = false;
if (aDrawMode == DrawMode::GLYPH_FILL &&
HasNonOpaqueNonTransparentColor(aContext, currentColor) &&
HasSyntheticBold(this, aStart, aLength)) {
needToRestore = true;
// measure text, use the bounding box
gfxTextRun::Metrics metrics = MeasureText(aStart, aLength,
gfxFont::LOOSE_INK_EXTENTS,
aContext, aProvider);
metrics.mBoundingBox.MoveBy(aPt);
syntheticBoldBuffer.PushSolidColor(metrics.mBoundingBox, currentColor,
GetAppUnitsPerDevUnit());
}
// Set up parameters that will be constant across all glyph runs we need
// to draw, regardless of the font used.
TextRunDrawParams params;
@@ -618,25 +637,6 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
params.dt = aContext->GetDrawTarget();
params.fontSmoothingBGColor = aContext->GetFontSmoothingBackgroundColor();
// synthetic bolding draws glyphs twice ==> colors with opacity won't draw
// correctly unless first drawn without alpha
BufferAlphaColor syntheticBoldBuffer(aContext);
Color currentColor;
bool needToRestore = false;
if (aDrawMode == DrawMode::GLYPH_FILL &&
HasNonOpaqueColor(aContext, currentColor) &&
HasSyntheticBold(this, aStart, aLength)) {
needToRestore = true;
// measure text, use the bounding box
gfxTextRun::Metrics metrics = MeasureText(aStart, aLength,
gfxFont::LOOSE_INK_EXTENTS,
aContext, aProvider);
metrics.mBoundingBox.MoveBy(aPt);
syntheticBoldBuffer.PushSolidColor(metrics.mBoundingBox, currentColor,
GetAppUnitsPerDevUnit());
}
GlyphRunIterator iter(this, aStart, aLength);
gfxFloat advance = 0.0;
@@ -1247,13 +1247,16 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart,
// Copy glyph runs
GlyphRunIterator iter(aSource, aStart, aLength);
#ifdef DEBUG
gfxFont *lastFont = nullptr;
GlyphRun *prevRun = nullptr;
#endif
while (iter.NextRun()) {
gfxFont *font = iter.GetGlyphRun()->mFont;
NS_ASSERTION(font != lastFont, "Glyphruns not coalesced?");
NS_ASSERTION(!prevRun || prevRun->mFont != iter.GetGlyphRun()->mFont ||
prevRun->mMatchType != iter.GetGlyphRun()->mMatchType ||
prevRun->mOrientation != iter.GetGlyphRun()->mOrientation,
"Glyphruns not coalesced?");
#ifdef DEBUG
lastFont = font;
prevRun = iter.GetGlyphRun();
uint32_t end = iter.GetStringEnd();
#endif
uint32_t start = iter.GetStringStart();
@@ -1540,7 +1543,7 @@ gfxFontGroup::gfxFontGroup(const FontFamilyList& aFontFamilyList,
, mHyphenWidth(-1)
, mUserFontSet(aUserFontSet)
, mTextPerf(aTextPerf)
, mPageLang(gfxPlatform::GetFontPrefLangFor(aStyle->language))
, mPageLang(gfxPlatformFontList::GetFontPrefLangFor(aStyle->language))
, mSkipDrawing(false)
, mSkipUpdateUserFonts(false)
{
@@ -1554,138 +1557,6 @@ gfxFontGroup::~gfxFontGroup()
{
}
void
gfxFontGroup::FindGenericFonts(FontFamilyType aGenericType,
nsIAtom *aLanguage,
void *aClosure)
{
nsAutoTArray<nsString, 5> resolvedGenerics;
ResolveGenericFontNames(aGenericType, aLanguage, resolvedGenerics);
uint32_t g = 0, numGenerics = resolvedGenerics.Length();
for (g = 0; g < numGenerics; g++) {
FindPlatformFont(resolvedGenerics[g], false, aClosure);
}
}
/* static */ void
gfxFontGroup::ResolveGenericFontNames(FontFamilyType aGenericType,
nsIAtom *aLanguage,
nsTArray<nsString>& aGenericFamilies)
{
static const char kGeneric_serif[] = "serif";
static const char kGeneric_sans_serif[] = "sans-serif";
static const char kGeneric_monospace[] = "monospace";
static const char kGeneric_cursive[] = "cursive";
static const char kGeneric_fantasy[] = "fantasy";
// treat -moz-fixed as monospace
if (aGenericType == eFamily_moz_fixed) {
aGenericType = eFamily_monospace;
}
// type should be standard generic type at this point
NS_ASSERTION(aGenericType >= eFamily_serif &&
aGenericType <= eFamily_fantasy,
"standard generic font family type required");
// create the lang string
nsIAtom *langGroupAtom = nullptr;
nsAutoCString langGroupString;
if (aLanguage) {
if (!gLangService) {
CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService);
}
if (gLangService) {
nsresult rv;
langGroupAtom = gLangService->GetLanguageGroup(aLanguage, &rv);
}
}
if (!langGroupAtom) {
langGroupAtom = nsGkAtoms::Unicode;
}
langGroupAtom->ToUTF8String(langGroupString);
// map generic type to string
const char *generic = nullptr;
switch (aGenericType) {
case eFamily_serif:
generic = kGeneric_serif;
break;
case eFamily_sans_serif:
generic = kGeneric_sans_serif;
break;
case eFamily_monospace:
generic = kGeneric_monospace;
break;
case eFamily_cursive:
generic = kGeneric_cursive;
break;
case eFamily_fantasy:
generic = kGeneric_fantasy;
break;
default:
break;
}
if (!generic) {
return;
}
aGenericFamilies.Clear();
// load family for "font.name.generic.lang"
nsAutoCString prefFontName("font.name.");
prefFontName.Append(generic);
prefFontName.Append('.');
prefFontName.Append(langGroupString);
gfxFontUtils::AppendPrefsFontList(prefFontName.get(),
aGenericFamilies);
// if lang has pref fonts, also load fonts for "font.name-list.generic.lang"
if (!aGenericFamilies.IsEmpty()) {
nsAutoCString prefFontListName("font.name-list.");
prefFontListName.Append(generic);
prefFontListName.Append('.');
prefFontListName.Append(langGroupString);
gfxFontUtils::AppendPrefsFontList(prefFontListName.get(),
aGenericFamilies);
}
#if 0 // dump out generic mappings
printf("%s ===> ", prefFontName.get());
for (uint32_t k = 0; k < aGenericFamilies.Length(); k++) {
if (k > 0) printf(", ");
printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]).get());
}
printf("\n");
#endif
}
void gfxFontGroup::EnumerateFontList(nsIAtom *aLanguage, void *aClosure)
{
// initialize fonts in the font family list
const nsTArray<FontFamilyName>& fontlist = mFamilyList.GetFontlist();
// lookup fonts in the fontlist
uint32_t i, numFonts = fontlist.Length();
for (i = 0; i < numFonts; i++) {
const FontFamilyName& name = fontlist[i];
if (name.IsNamed()) {
FindPlatformFont(name.mName, true, aClosure);
} else {
FindGenericFonts(name.mType, aLanguage, aClosure);
}
}
// if necessary, append default generic onto the end
if (mFamilyList.GetDefaultFontType() != eFamily_none &&
!mFamilyList.HasDefaultGeneric()) {
FindGenericFonts(mFamilyList.GetDefaultFontType(),
aLanguage,
aClosure);
}
}
void
gfxFontGroup::BuildFontList()
{
@@ -1697,56 +1568,85 @@ gfxFontGroup::BuildFontList()
#elif defined(MOZ_WIDGET_QT)
enumerateFonts = false;
#endif
if (enumerateFonts) {
EnumerateFontList(mStyle.language);
if (!enumerateFonts) {
return;
}
}
void
gfxFontGroup::FindPlatformFont(const nsAString& aName,
bool aUseFontSet,
void *aClosure)
{
bool needsBold;
gfxFontFamily *family = nullptr;
gfxFontEntry *fe = nullptr;
// initialize fonts in the font family list
nsAutoTArray<gfxFontFamily*,4> fonts;
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
if (aUseFontSet) {
// First, look up in the user font set...
// If the fontSet matches the family, we must not look for a platform
// font of the same name, even if we fail to actually get a fontEntry
// here; we'll fall back to the next name in the CSS font-family list.
if (mUserFontSet) {
// Add userfonts to the fontlist whether already loaded
// or not. Loading is initiated during font matching.
family = mUserFontSet->LookupFamily(aName);
if (family) {
nsAutoTArray<gfxFontEntry*,4> userfonts;
family->FindAllFontsForStyle(mStyle, userfonts, needsBold);
// add these to the fontlist
uint32_t count = userfonts.Length();
for (uint32_t i = 0; i < count; i++) {
fe = userfonts[i];
FamilyFace ff(family, fe, needsBold);
ff.CheckState(mSkipDrawing);
mFonts.AppendElement(ff);
}
// lookup fonts in the fontlist
for (const FontFamilyName& name : mFamilyList.GetFontlist()) {
if (name.IsNamed()) {
AddPlatformFont(name.mName, fonts);
} else {
pfl->AddGenericFonts(name.mType, mStyle.language, fonts);
if (mTextPerf) {
mTextPerf->current.genericLookups++;
}
}
}
// Not known in the user font set ==> check system fonts
if (!family) {
gfxPlatformFontList *fontList = gfxPlatformFontList::PlatformFontList();
family = fontList->FindFamily(aName, mStyle.language, mStyle.systemFont);
if (family) {
fe = family->FindFontForStyle(mStyle, needsBold);
// if necessary, append default generic onto the end
if (mFamilyList.GetDefaultFontType() != eFamily_none &&
!mFamilyList.HasDefaultGeneric()) {
pfl->AddGenericFonts(mFamilyList.GetDefaultFontType(),
mStyle.language, fonts);
if (mTextPerf) {
mTextPerf->current.genericLookups++;
}
}
// add to the font group, unless it's already there
if (fe && !HasFont(fe)) {
mFonts.AppendElement(FamilyFace(family, fe, needsBold));
// build the fontlist from the specified families
for (gfxFontFamily* fontFamily : fonts) {
AddFamilyToFontList(fontFamily);
}
}
void
gfxFontGroup::AddPlatformFont(const nsAString& aName,
nsTArray<gfxFontFamily*>& aFamilyList)
{
gfxFontFamily* family = nullptr;
// First, look up in the user font set...
// If the fontSet matches the family, we must not look for a platform
// font of the same name, even if we fail to actually get a fontEntry
// here; we'll fall back to the next name in the CSS font-family list.
if (mUserFontSet) {
// Add userfonts to the fontlist whether already loaded
// or not. Loading is initiated during font matching.
family = mUserFontSet->LookupFamily(aName);
}
// Not known in the user font set ==> check system fonts
if (!family) {
gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList();
family = fontList->FindFamily(aName, mStyle.language, mStyle.systemFont);
}
if (family) {
aFamilyList.AppendElement(family);
}
}
void
gfxFontGroup::AddFamilyToFontList(gfxFontFamily* aFamily)
{
NS_ASSERTION(aFamily, "trying to add a null font family to fontlist");
nsAutoTArray<gfxFontEntry*,4> fontEntryList;
bool needsBold;
aFamily->FindAllFontsForStyle(mStyle, fontEntryList, needsBold);
// add these to the fontlist
for (gfxFontEntry* fe : fontEntryList) {
if (!HasFont(fe)) {
FamilyFace ff(aFamily, fe, needsBold);
if (fe->mIsUserFontContainer) {
ff.CheckState(mSkipDrawing);
}
mFonts.AppendElement(ff);
}
}
}
@@ -2651,9 +2551,6 @@ gfxFontGroup::FindNonItalicFaceForChar(gfxFontFamily* aFamily, uint32_t aCh)
}
nsRefPtr<gfxFont> font = fe->FindOrMakeFont(&mStyle, needsBold);
if (!font->Valid()) {
return nullptr;
}
return font.forget();
}
@@ -3008,16 +2905,40 @@ void gfxFontGroup::ComputeRanges(nsTArray<gfxTextRange>& aRanges,
aRanges[lastRangeIndex].end = aLength;
#if 0
// dump out font matching info
if (mStyle.systemFont) return;
for (size_t i = 0, i_end = aRanges.Length(); i < i_end; i++) {
const gfxTextRange& r = aRanges[i];
printf("fontmatch %zd:%zd font: %s (%d)\n",
r.start, r.end,
(r.font.get() ?
NS_ConvertUTF16toUTF8(r.font->GetName()).get() : "<null>"),
r.matchType);
#ifndef RELEASE_BUILD
PRLogModuleInfo *log = (mStyle.systemFont ?
gfxPlatform::GetLog(eGfxLog_textrunui) :
gfxPlatform::GetLog(eGfxLog_textrun));
if (MOZ_UNLIKELY(MOZ_LOG_TEST(log, LogLevel::Debug))) {
nsAutoCString lang;
mStyle.language->ToUTF8String(lang);
nsAutoString families;
mFamilyList.ToString(families);
// collect the font matched for each range
nsAutoCString fontMatches;
for (size_t i = 0, i_end = aRanges.Length(); i < i_end; i++) {
const gfxTextRange& r = aRanges[i];
fontMatches.AppendPrintf(" [%u:%u] %.200s (%s)", r.start, r.end,
(r.font.get() ?
NS_ConvertUTF16toUTF8(r.font->GetName()).get() : "<null>"),
(r.matchType == gfxTextRange::kFontGroup ?
"list" :
(r.matchType == gfxTextRange::kPrefsFallback) ?
"prefs" : "sys"));
}
MOZ_LOG(log, LogLevel::Debug,\
("(%s-fontmatching) fontgroup: [%s] default: %s lang: %s script: %d"
"%s\n",
(mStyle.systemFont ? "textrunui" : "textrun"),
NS_ConvertUTF16toUTF8(families).get(),
(mFamilyList.GetDefaultFontType() == eFamily_serif ?
"serif" :
(mFamilyList.GetDefaultFontType() == eFamily_sans_serif ?
"sans-serif" : "none")),
lang.get(), aRunScript,
fontMatches.get()));
}
#endif
}
@@ -3114,7 +3035,7 @@ struct PrefFontCallbackData {
PrefFontCallbackData *prefFontData = static_cast<PrefFontCallbackData*>(aClosure);
// map pref lang to langGroup for language-sensitive lookups
nsIAtom* lang = gfxPlatform::GetLangGroupForPrefLang(aLang);
nsIAtom* lang = gfxPlatformFontList::GetLangGroupForPrefLang(aLang);
gfxFontFamily *family =
gfxPlatformFontList::PlatformFontList()->FindFamily(aName, lang);
if (family) {
@@ -3131,7 +3052,8 @@ gfxFontGroup::WhichPrefFontSupportsChar(uint32_t aCh)
// get the pref font list if it hasn't been set up already
uint32_t unicodeRange = FindCharUnicodeRange(aCh);
eFontPrefLang charLang = gfxPlatform::GetPlatform()->GetFontPrefLangFor(unicodeRange);
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
eFontPrefLang charLang = pfl->GetFontPrefLangFor(unicodeRange);
// if the last pref font was the first family in the pref list, no need to recheck through a list of families
if (mLastPrefFont && charLang == mLastPrefLang &&
@@ -3144,29 +3066,22 @@ gfxFontGroup::WhichPrefFontSupportsChar(uint32_t aCh)
eFontPrefLang prefLangs[kMaxLenPrefLangList];
uint32_t i, numLangs = 0;
gfxPlatform::GetPlatform()->GetLangPrefs(prefLangs, numLangs, charLang, mPageLang);
pfl->GetLangPrefs(prefLangs, numLangs, charLang, mPageLang);
for (i = 0; i < numLangs; i++) {
nsAutoTArray<nsRefPtr<gfxFontFamily>, 5> families;
eFontPrefLang currentLang = prefLangs[i];
gfxPlatformFontList *fontList = gfxPlatformFontList::PlatformFontList();
// get the pref families for a single pref lang
if (!fontList->GetPrefFontFamilyEntries(currentLang, &families)) {
eFontPrefLang prefLangsToSearch[1] = { currentLang };
PrefFontCallbackData prefFontData(families);
gfxPlatform::ForEachPrefFont(prefLangsToSearch, 1, PrefFontCallbackData::AddFontFamilyEntry,
&prefFontData);
fontList->SetPrefFontFamilyEntries(currentLang, families);
}
mozilla::FontFamilyType defaultGeneric =
pfl->GetDefaultGeneric(currentLang);
nsTArray<nsRefPtr<gfxFontFamily>>* families =
pfl->GetPrefFontsLangGroup(defaultGeneric, currentLang);
NS_ASSERTION(families, "no pref font families found");
// find the first pref font that includes the character
uint32_t j, numPrefs;
numPrefs = families.Length();
numPrefs = families->Length();
for (j = 0; j < numPrefs; j++) {
// look up the appropriate face
gfxFontFamily *family = families[j];
gfxFontFamily *family = (*families)[j];
if (!family) continue;
// if a pref font is used, it's likely to be used again in the same text run.
+18 -29
View File
@@ -10,6 +10,7 @@
#include "nsString.h"
#include "gfxPoint.h"
#include "gfxFont.h"
#include "gfxFontConstants.h"
#include "nsTArray.h"
#include "gfxSkipChars.h"
#include "gfxPlatform.h"
@@ -832,18 +833,6 @@ public:
int32_t aRunScript, gfxFont *aPrevMatchedFont,
uint8_t *aMatchType);
// search through pref fonts for a character, return nullptr if no matching pref font
virtual already_AddRefed<gfxFont> WhichPrefFontSupportsChar(uint32_t aCh);
already_AddRefed<gfxFont>
WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh,
int32_t aRunScript);
template<typename T>
void ComputeRanges(nsTArray<gfxTextRange>& mRanges,
const T *aString, uint32_t aLength,
int32_t aRunScript, uint16_t aOrientation);
gfxUserFontSet* GetUserFontSet();
// With downloadable fonts, the composition of the font group can change as fonts are downloaded
@@ -884,13 +873,19 @@ public:
gfxTextRun* GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel, uint32_t aFlags,
LazyReferenceContextGetter& aRefContextGetter);
// helper method for resolving generic font families
static void
ResolveGenericFontNames(mozilla::FontFamilyType aGenericType,
nsIAtom *aLanguage,
nsTArray<nsString>& aGenericFamilies);
protected:
// search through pref fonts for a character, return nullptr if no matching pref font
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(uint32_t aCh);
already_AddRefed<gfxFont>
WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh,
int32_t aRunScript);
template<typename T>
void ComputeRanges(nsTArray<gfxTextRange>& mRanges,
const T *aString, uint32_t aLength,
int32_t aRunScript, uint16_t aOrientation);
class FamilyFace {
public:
FamilyFace() : mFamily(nullptr), mFontEntry(nullptr),
@@ -1117,18 +1112,12 @@ protected:
// helper methods for looking up fonts
// iterate over the fontlist, lookup names and expand generics
void EnumerateFontList(nsIAtom *aLanguage, void *aClosure = nullptr);
// expand a generic to a list of specific names based on prefs
void FindGenericFonts(mozilla::FontFamilyType aGenericType,
nsIAtom *aLanguage,
void *aClosure);
// lookup and add a font with a given name (i.e. *not* a generic!)
virtual void FindPlatformFont(const nsAString& aName,
bool aUseFontSet,
void *aClosure);
void AddPlatformFont(const nsAString& aName,
nsTArray<gfxFontFamily*>& aFamilyList);
// do style selection and add entries to list
void AddFamilyToFontList(gfxFontFamily* aFamily);
static nsILanguageAtomService* gLangService;
};
+11 -5
View File
@@ -140,7 +140,9 @@ public:
nsRefPtr<gfxFontEntry> fe = aFontEntry;
// remove existing entry, if already present
mAvailableFonts.RemoveElement(aFontEntry);
mAvailableFonts.AppendElement(aFontEntry);
// insert at the beginning so that the last-defined font is the first
// one in the fontlist used for matching, as per CSS Fonts spec
mAvailableFonts.InsertElementAt(0, aFontEntry);
if (aFontEntry->mFamilyName.IsEmpty()) {
aFontEntry->mFamilyName = Name();
@@ -338,7 +340,9 @@ public:
struct Key {
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mPrincipal; // use nullptr with data: URLs
gfxFontEntry* mFontEntry;
// The font entry MUST notify the cache when it is destroyed
// (by calling ForgetFont()).
gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
uint32_t mCRC32;
uint32_t mLength;
bool mPrivate;
@@ -444,8 +448,8 @@ public:
// The "real" font entry corresponding to this downloaded font.
// The font entry MUST notify the cache when it is destroyed
// (by calling Forget()).
gfxFontEntry* mFontEntry;
// (by calling ForgetFont()).
gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
// Whether this font was loaded from a private window.
bool mPrivate;
@@ -647,7 +651,9 @@ protected:
nsRefPtr<gfxFontEntry> mPlatformFontEntry;
nsTArray<gfxFontFaceSrc> mSrcList;
uint32_t mSrcIndex; // index of loading src item
nsFontFaceLoader* mLoader; // current loader for this entry, if any
// This field is managed by the nsFontFaceLoader. In the destructor and Cancel()
// methods of nsFontFaceLoader this reference is nulled out.
nsFontFaceLoader* MOZ_NON_OWNING_REF mLoader; // current loader for this entry, if any
gfxUserFontSet* mFontSet; // font-set to which the userfont entry belongs
nsCOMPtr<nsIPrincipal> mPrincipal;
};
+12 -6
View File
@@ -421,6 +421,12 @@ CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable,
PROFILER_LABEL("gfxUtils", "CreateSamplingRestricedDrawable",
js::ProfileEntry::Category::GRAPHICS);
DrawTarget* destDrawTarget = aContext->GetDrawTarget();
if ((destDrawTarget->GetBackendType() == BackendType::DIRECT2D1_1) ||
(destDrawTarget->GetBackendType() == BackendType::DIRECT2D)) {
return nullptr;
}
gfxRect clipExtents = aContext->GetClipExtents();
// Inflate by one pixel because bilinear filtering will sample at most
@@ -757,13 +763,13 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext,
CreateSamplingRestrictedDrawable(aDrawable, aContext,
aRegion, aFormat);
if (restrictedDrawable) {
drawable.swap(restrictedDrawable);
}
drawable.swap(restrictedDrawable);
// We no longer need to tile: Either we never needed to, or we already
// filled a surface with the tiled pattern; this surface can now be
// drawn without tiling.
doTile = false;
// We no longer need to tile: Either we never needed to, or we already
// filled a surface with the tiled pattern; this surface can now be
// drawn without tiling.
doTile = false;
}
#endif
}
}
+4
View File
@@ -1047,6 +1047,7 @@ LogTextPerfStats(gfxTextPerfMetrics* aTextPerf,
"word-cache-space: %d word-cache-long: %d "
"pref-fallbacks: %d system-fallbacks: %d "
"textruns-const: %d textruns-destr: %d "
"generic-lookups: %d "
"cumulative-textruns-destr: %d\n",
prefix, aTextPerf->reflowCount, aCounts.numChars,
(aURL ? aURL : ""),
@@ -1056,6 +1057,7 @@ LogTextPerfStats(gfxTextPerfMetrics* aTextPerf,
aCounts.wordCacheSpaceRules, aCounts.wordCacheLong,
aCounts.fallbackPrefs, aCounts.fallbackSystem,
aCounts.textrunConst, aCounts.textrunDestr,
aCounts.genericLookups,
aTextPerf->cumulative.textrunDestr));
} else {
MOZ_LOG(tpLog, logLevel,
@@ -1066,6 +1068,7 @@ LogTextPerfStats(gfxTextPerfMetrics* aTextPerf,
"word-cache-space: %d word-cache-long: %d "
"pref-fallbacks: %d system-fallbacks: %d "
"textruns-const: %d textruns-destr: %d "
"generic-lookups: %d "
"cumulative-textruns-destr: %d\n",
prefix, aTextPerf->reflowCount, aCounts.numChars,
aCounts.numContentTextRuns, aCounts.numChromeTextRuns,
@@ -1074,6 +1077,7 @@ LogTextPerfStats(gfxTextPerfMetrics* aTextPerf,
aCounts.wordCacheSpaceRules, aCounts.wordCacheLong,
aCounts.fallbackPrefs, aCounts.fallbackSystem,
aCounts.textrunConst, aCounts.textrunDestr,
aCounts.genericLookups,
aTextPerf->cumulative.textrunDestr));
}
}
+4 -1
View File
@@ -958,7 +958,10 @@ static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
int32_t intValue = aValue.GetIntValue();
if (0 <= intValue) {
LookAndFeel::ColorID colorID = (LookAndFeel::ColorID) intValue;
if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID, &aResult))) {
bool useStandinsForNativeColors = aPresContext &&
!aPresContext->IsChrome();
if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID,
useStandinsForNativeColors, &aResult))) {
result = true;
}
}
+3
View File
@@ -4424,6 +4424,9 @@ pref("webgl.enable-privileged-extensions", false);
pref("webgl.bypass-shader-validation", false);
pref("webgl.enable-prototype-webgl2", false);
pref("webgl.disable-fail-if-major-performance-caveat", false);
pref("webgl.disable-debug-renderer-info", false);
pref("webgl.renderer-string-override", "");
pref("webgl.vendor-string-override", "");
#ifdef RELEASE_BUILD
// Keep this disabled on Release and Beta for now. (see bug 1171228)
+9
View File
@@ -533,6 +533,15 @@ public:
*/
static nsresult GetColor(ColorID aID, nscolor* aResult);
/**
* This variant of GetColor() takes an extra Boolean parameter that allows
* the caller to ask that hard-coded color values be substituted for
* native colors (used when it is desireable to hide system colors to
* avoid system fingerprinting).
*/
static nsresult GetColor(ColorID aID, bool aUseStandinsForNativeColors,
nscolor* aResult);
/**
* GetInt() and GetFloat() return a int or float value for aID. The result
* might be distance, time, some flags or a int value which has particular
+176 -7
View File
@@ -241,6 +241,7 @@ int32_t nsXPLookAndFeel::sCachedColorBits[COLOR_CACHE_SIZE] = {0};
bool nsXPLookAndFeel::sInitialized = false;
bool nsXPLookAndFeel::sUseNativeColors = true;
bool nsXPLookAndFeel::sUseStandinsForNativeColors = false;
nsLookAndFeel* nsXPLookAndFeel::sInstance = nullptr;
bool nsXPLookAndFeel::sShutdown = false;
@@ -452,10 +453,12 @@ nsXPLookAndFeel::Init()
InitColorFromPref(i);
}
bool val;
if (NS_SUCCEEDED(Preferences::GetBool("ui.use_native_colors", &val))) {
sUseNativeColors = val;
}
Preferences::AddBoolVarCache(&sUseNativeColors,
"ui.use_native_colors",
sUseNativeColors);
Preferences::AddBoolVarCache(&sUseStandinsForNativeColors,
"ui.use_standins_for_native_colors",
sUseStandinsForNativeColors);
if (XRE_IsContentProcess()) {
mozilla::dom::ContentChild* cc =
@@ -504,6 +507,153 @@ nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor &aColor)
return false;
}
bool
nsXPLookAndFeel::ColorIsNotCSSAccessible(ColorID aID)
{
bool result = false;
switch (aID) {
case eColorID_WindowBackground:
case eColorID_WindowForeground:
case eColorID_WidgetBackground:
case eColorID_WidgetForeground:
case eColorID_WidgetSelectBackground:
case eColorID_WidgetSelectForeground:
case eColorID_Widget3DHighlight:
case eColorID_Widget3DShadow:
case eColorID_TextBackground:
case eColorID_TextForeground:
case eColorID_TextSelectBackground:
case eColorID_TextSelectForeground:
case eColorID_TextSelectBackgroundDisabled:
case eColorID_TextSelectBackgroundAttention:
case eColorID_TextHighlightBackground:
case eColorID_TextHighlightForeground:
case eColorID_IMERawInputBackground:
case eColorID_IMERawInputForeground:
case eColorID_IMERawInputUnderline:
case eColorID_IMESelectedRawTextBackground:
case eColorID_IMESelectedRawTextForeground:
case eColorID_IMESelectedRawTextUnderline:
case eColorID_IMEConvertedTextBackground:
case eColorID_IMEConvertedTextForeground:
case eColorID_IMEConvertedTextUnderline:
case eColorID_IMESelectedConvertedTextBackground:
case eColorID_IMESelectedConvertedTextForeground:
case eColorID_IMESelectedConvertedTextUnderline:
case eColorID_SpellCheckerUnderline:
result = true;
break;
default:
break;
}
return result;
}
nscolor
nsXPLookAndFeel::GetStandinForNativeColor(ColorID aID)
{
nscolor result = NS_RGB(0xFF, 0xFF, 0xFF);
// The stand-in colors are taken from the Windows 7 Aero theme
// except Mac-specific colors which are taken from Mac OS 10.7.
switch (aID) {
// CSS 2 colors:
case eColorID_activeborder: result = NS_RGB(0xB4, 0xB4, 0xB4); break;
case eColorID_activecaption: result = NS_RGB(0x99, 0xB4, 0xD1); break;
case eColorID_appworkspace: result = NS_RGB(0xAB, 0xAB, 0xAB); break;
case eColorID_background: result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID_buttonface: result = NS_RGB(0xF0, 0xF0, 0xF0); break;
case eColorID_buttonhighlight: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID_buttonshadow: result = NS_RGB(0xA0, 0xA0, 0xA0); break;
case eColorID_buttontext: result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID_captiontext: result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID_graytext: result = NS_RGB(0x6D, 0x6D, 0x6D); break;
case eColorID_highlight: result = NS_RGB(0x33, 0x99, 0xFF); break;
case eColorID_highlighttext: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID_inactiveborder: result = NS_RGB(0xF4, 0xF7, 0xFC); break;
case eColorID_inactivecaption: result = NS_RGB(0xBF, 0xCD, 0xDB); break;
case eColorID_inactivecaptiontext:
result = NS_RGB(0x43, 0x4E, 0x54); break;
case eColorID_infobackground: result = NS_RGB(0xFF, 0xFF, 0xE1); break;
case eColorID_infotext: result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID_menu: result = NS_RGB(0xF0, 0xF0, 0xF0); break;
case eColorID_menutext: result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID_scrollbar: result = NS_RGB(0xC8, 0xC8, 0xC8); break;
case eColorID_threeddarkshadow: result = NS_RGB(0x69, 0x69, 0x69); break;
case eColorID_threedface: result = NS_RGB(0xF0, 0xF0, 0xF0); break;
case eColorID_threedhighlight: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID_threedlightshadow: result = NS_RGB(0xE3, 0xE3, 0xE3); break;
case eColorID_threedshadow: result = NS_RGB(0xA0, 0xA0, 0xA0); break;
case eColorID_window: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID_windowframe: result = NS_RGB(0x64, 0x64, 0x64); break;
case eColorID_windowtext: result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID__moz_buttondefault:
result = NS_RGB(0x69, 0x69, 0x69); break;
case eColorID__moz_field: result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID__moz_fieldtext: result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID__moz_dialog: result = NS_RGB(0xF0, 0xF0, 0xF0); break;
case eColorID__moz_dialogtext: result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID__moz_dragtargetzone:
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID__moz_cellhighlight:
result = NS_RGB(0xF0, 0xF0, 0xF0); break;
case eColorID__moz_cellhighlighttext:
result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID__moz_html_cellhighlight:
result = NS_RGB(0x33, 0x99, 0xFF); break;
case eColorID__moz_html_cellhighlighttext:
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID__moz_buttonhoverface:
result = NS_RGB(0xF0, 0xF0, 0xF0); break;
case eColorID__moz_buttonhovertext:
result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID__moz_menuhover:
result = NS_RGB(0x33, 0x99, 0xFF); break;
case eColorID__moz_menuhovertext:
result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID__moz_menubartext:
result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID__moz_menubarhovertext:
result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID__moz_oddtreerow:
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID__moz_mac_chrome_active:
result = NS_RGB(0xB2, 0xB2, 0xB2); break;
case eColorID__moz_mac_chrome_inactive:
result = NS_RGB(0xE1, 0xE1, 0xE1); break;
case eColorID__moz_mac_focusring:
result = NS_RGB(0x60, 0x9D, 0xD7); break;
case eColorID__moz_mac_menuselect:
result = NS_RGB(0x38, 0x75, 0xD7); break;
case eColorID__moz_mac_menushadow:
result = NS_RGB(0xA3, 0xA3, 0xA3); break;
case eColorID__moz_mac_menutextdisable:
result = NS_RGB(0x88, 0x88, 0x88); break;
case eColorID__moz_mac_menutextselect:
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID__moz_mac_disabledtoolbartext:
result = NS_RGB(0x3F, 0x3F, 0x3F); break;
case eColorID__moz_mac_secondaryhighlight:
result = NS_RGB(0xD4, 0xD4, 0xD4); break;
case eColorID__moz_win_mediatext:
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID__moz_win_communicationstext:
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
case eColorID__moz_nativehyperlinktext:
result = NS_RGB(0x00, 0x66, 0xCC); break;
case eColorID__moz_comboboxtext:
result = NS_RGB(0x00, 0x00, 0x00); break;
case eColorID__moz_combobox:
result = NS_RGB(0xFF, 0xFF, 0xFF); break;
default:
break;
}
return result;
}
//
// All these routines will return NS_OK if they have a value,
// in which case the nsLookAndFeel should use that value;
@@ -511,7 +661,8 @@ nsXPLookAndFeel::IsSpecialColor(ColorID aID, nscolor &aColor)
// platform-specific nsLookAndFeel should use its own values instead.
//
nsresult
nsXPLookAndFeel::GetColorImpl(ColorID aID, nscolor &aResult)
nsXPLookAndFeel::GetColorImpl(ColorID aID, bool aUseStandinsForNativeColors,
nscolor &aResult)
{
if (!sInitialized)
Init();
@@ -597,7 +748,12 @@ nsXPLookAndFeel::GetColorImpl(ColorID aID, nscolor &aResult)
}
#endif // DEBUG_SYSTEM_COLOR_USE
if (IS_COLOR_CACHED(aID)) {
if (aUseStandinsForNativeColors &&
(ColorIsNotCSSAccessible(aID) || !sUseStandinsForNativeColors)) {
aUseStandinsForNativeColors = false;
}
if (!aUseStandinsForNativeColors && IS_COLOR_CACHED(aID)) {
aResult = sCachedColors[aID];
return NS_OK;
}
@@ -631,6 +787,11 @@ nsXPLookAndFeel::GetColorImpl(ColorID aID, nscolor &aResult)
return NS_OK;
}
if (sUseNativeColors && aUseStandinsForNativeColors) {
aResult = GetStandinForNativeColor(aID);
return NS_OK;
}
if (sUseNativeColors && NS_SUCCEEDED(NativeGetColor(aID, aResult))) {
if ((gfxPlatform::GetCMSMode() == eCMSMode_All) &&
!IsSpecialColor(aID, aResult)) {
@@ -727,7 +888,15 @@ namespace mozilla {
nsresult
LookAndFeel::GetColor(ColorID aID, nscolor* aResult)
{
return nsLookAndFeel::GetInstance()->GetColorImpl(aID, *aResult);
return nsLookAndFeel::GetInstance()->GetColorImpl(aID, false, *aResult);
}
nsresult
LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors,
nscolor* aResult)
{
return nsLookAndFeel::GetInstance()->GetColorImpl(aID,
aUseStandinsForNativeColors, *aResult);
}
// static
+5 -1
View File
@@ -53,7 +53,8 @@ public:
// otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
// platform-specific nsLookAndFeel should use its own values instead.
//
nsresult GetColorImpl(ColorID aID, nscolor &aResult);
nsresult GetColorImpl(ColorID aID, bool aUseStandinsForNativeColors,
nscolor &aResult);
virtual nsresult GetIntImpl(IntID aID, int32_t &aResult);
virtual nsresult GetFloatImpl(FloatID aID, float &aResult);
@@ -94,6 +95,8 @@ protected:
void InitColorFromPref(int32_t aIndex);
virtual nsresult NativeGetColor(ColorID aID, nscolor &aResult) = 0;
bool IsSpecialColor(ColorID aID, nscolor &aColor);
bool ColorIsNotCSSAccessible(ColorID aID);
nscolor GetStandinForNativeColor(ColorID aID);
static void OnPrefChanged(const char* aPref, void* aClosure);
@@ -107,6 +110,7 @@ protected:
static int32_t sCachedColors[LookAndFeel::eColorID_LAST_COLOR];
static int32_t sCachedColorBits[COLOR_CACHE_SIZE];
static bool sUseNativeColors;
static bool sUseStandinsForNativeColors;
static nsLookAndFeel* sInstance;
static bool sShutdown;