From 76df446d7a5133c3f4e38cdcf56caa4ddad84ff1 Mon Sep 17 00:00:00 2001 From: "vladimir%pobox.com" Date: Sat, 3 Mar 2007 00:18:34 +0000 Subject: [PATCH] b=using opacity with windows native widgets causes bogus rendering/lack of rendering; r=stuart git-svn-id: svn://10.0.0.236/trunk@221253 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/gfx/thebes/public/Makefile.in | 5 +- mozilla/gfx/thebes/public/gfxAlphaRecovery.h | 55 ++++ mozilla/gfx/thebes/public/gfxMatrix.h | 51 +++ mozilla/gfx/thebes/public/gfxPattern.h | 5 +- .../thebes/public/gfxWindowsNativeDrawing.h | 158 +++++++++ mozilla/gfx/thebes/src/Makefile.in | 2 + mozilla/gfx/thebes/src/gfxAlphaRecovery.cpp | 172 ++++++++++ mozilla/gfx/thebes/src/gfxPattern.cpp | 14 +- .../thebes/src/gfxWindowsNativeDrawing.cpp | 310 ++++++++++++++++++ .../widget/src/windows/nsNativeThemeWin.cpp | 258 +++++++-------- mozilla/widget/src/windows/nsNativeThemeWin.h | 2 + 11 files changed, 887 insertions(+), 145 deletions(-) create mode 100644 mozilla/gfx/thebes/public/gfxAlphaRecovery.h create mode 100644 mozilla/gfx/thebes/public/gfxWindowsNativeDrawing.h create mode 100644 mozilla/gfx/thebes/src/gfxAlphaRecovery.cpp create mode 100644 mozilla/gfx/thebes/src/gfxWindowsNativeDrawing.cpp diff --git a/mozilla/gfx/thebes/public/Makefile.in b/mozilla/gfx/thebes/public/Makefile.in index a85dc41d13b..40ebaff2caf 100644 --- a/mozilla/gfx/thebes/public/Makefile.in +++ b/mozilla/gfx/thebes/public/Makefile.in @@ -11,6 +11,7 @@ MODULE = thebes REQUIRES = cairo EXPORTS = gfxASurface.h \ + gfxAlphaRecovery.h \ gfxColor.h \ gfxContext.h \ gfxFont.h \ @@ -35,7 +36,9 @@ endif ifeq ($(MOZ_WIDGET_TOOLKIT),windows) EXPORTS += gfxWindowsFonts.h \ gfxWindowsPlatform.h \ - gfxWindowsSurface.h + gfxWindowsSurface.h \ + gfxWindowsNativeDrawing.h \ + $(NULL) EXPORTS += gfxPDFSurface.h ifdef MOZ_ENABLE_GLITZ diff --git a/mozilla/gfx/thebes/public/gfxAlphaRecovery.h b/mozilla/gfx/thebes/public/gfxAlphaRecovery.h new file mode 100644 index 00000000000..82c7e6e4245 --- /dev/null +++ b/mozilla/gfx/thebes/public/gfxAlphaRecovery.h @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Thebes gfx. + * + * The Initial Developer of the Original Code is Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GFXALPHARECOVERY_H_ +#define _GFXALPHARECOVERY_H_ + +#include "gfxContext.h" +#include "gfxImageSurface.h" + +class THEBES_API gfxAlphaRecovery { +public: + /* Given two RGB24 surfaces with the same rendering, one on a black + * background and the other on white, return a new surface + * that contains the contents with recovered alpha. + */ + static already_AddRefed RecoverAlpha (gfxImageSurface *blackSurface, + gfxImageSurface *whiteSurface, + gfxIntSize dimensions); +}; + +#endif /* _GFXALPHARECOVERY_H_ */ diff --git a/mozilla/gfx/thebes/public/gfxMatrix.h b/mozilla/gfx/thebes/public/gfxMatrix.h index 3d14de977db..fc69d4090e9 100644 --- a/mozilla/gfx/thebes/public/gfxMatrix.h +++ b/mozilla/gfx/thebes/public/gfxMatrix.h @@ -183,10 +183,61 @@ public: (xy != 0.0) || (yx != 0.0)); } + /** + * Returns true if the matrix has any transform other + * than a translation or a -1 y scale (y axis flip) + */ bool HasNonTranslationOrFlip() const { return ((xx != 1.0) || ((yy != 1.0) && (yy != -1.0)) || (xy != 0.0) || (yx != 0.0)); } + + /** + * Returns true if the matrix has any transform other + * than a translation or scale; this is, if there is + * no rotation. + */ + bool HasNonAxisAlignedTransform() const { + return ((xy != 0.0) || (yx != 0.0)); + } + + /** + * Computes the determinant of this matrix. + */ + double Determinant() const { + return xx*yy - yx*xy; + } + + /* Computes the scale factors of this matrix; that is, + * the amounts each basis vector is scaled by. + * The xMajor parameter indicates if the larger scale is + * to be assumed to be in the X direction or not. + */ + gfxSize ScaleFactors(PRBool xMajor) const { + double det = Determinant(); + + if (det == 0.0) + return gfxSize(0.0, 0.0); + + gfxSize sz((xMajor != 0 ? 1.0 : 0.0), + (xMajor != 0 ? 0.0 : 1.0)); + sz = Transform(sz); + + double major = sqrt(sz.width * sz.width + sz.height * sz.height); + double minor = 0.0; + + // ignore mirroring + if (det < 0.0) + det = - det; + + if (major) + minor = det / major; + + if (xMajor) + return gfxSize(major, minor); + + return gfxSize(minor, major); + } }; #endif /* GFX_MATRIX_H */ diff --git a/mozilla/gfx/thebes/public/gfxPattern.h b/mozilla/gfx/thebes/public/gfxPattern.h index 2e7daa517d6..807f94a1b64 100644 --- a/mozilla/gfx/thebes/public/gfxPattern.h +++ b/mozilla/gfx/thebes/public/gfxPattern.h @@ -63,8 +63,9 @@ public: cairo_pattern_t *CairoPattern(); void AddColorStop(gfxFloat offset, const gfxRGBA& c); + void SetMatrix(const gfxMatrix& matrix); - gfxMatrix CurrentMatrix() const; + gfxMatrix GetMatrix() const; enum GraphicsExtend { EXTEND_NONE, @@ -83,6 +84,8 @@ public: /* returns TRUE if it succeeded */ PRBool GetSolidColor(gfxRGBA& aColor); + already_AddRefed GetSurface(); + protected: cairo_pattern_t *mPattern; }; diff --git a/mozilla/gfx/thebes/public/gfxWindowsNativeDrawing.h b/mozilla/gfx/thebes/public/gfxWindowsNativeDrawing.h new file mode 100644 index 00000000000..2e300ef145c --- /dev/null +++ b/mozilla/gfx/thebes/public/gfxWindowsNativeDrawing.h @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Thebes gfx. + * + * The Initial Developer of the Original Code is Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GFXWINDOWSNATIVEDRAWING_H_ +#define _GFXWINDOWSNATIVEDRAWING_H_ + +#include + +#include "gfxContext.h" +#include "gfxWindowsSurface.h" + +class THEBES_API gfxWindowsNativeDrawing { +public: + + /* Flags for notifying this class what kind of operations the native + * drawing supports + */ + + enum { + /* Whether the native drawing can draw to a surface of content COLOR_ALPHA */ + CAN_DRAW_TO_COLOR_ALPHA = 1 << 0, + CANNOT_DRAW_TO_COLOR_ALPHA = 0 << 0, + + /* Whether the native drawing can be scaled using SetWorldTransform */ + CAN_AXIS_ALIGNED_SCALE = 1 << 1, + CANNOT_AXIS_ALIGNED_SCALE = 0 << 1, + + /* Whether the native drawing can be both scaled and rotated arbitrarily using SetWorldTransform */ + CAN_COMPLEX_TRANSFORM = 1 << 2, + CANNOT_COMPLEX_TRANSFORM = 0 << 2, + + /* If we have to do transforms with cairo, should we use nearest-neighbour filtering? */ + DO_NEAREST_NEIGHBOR_FILTERING = 1 << 3, + DO_BILINEAR_FILTERING = 0 << 3 + }; + + /* Create native win32 drawing for a rectangle bounded by + * nativeRect. + * + * This class assumes that native drawing can take place only if + * the destination surface has a content type of COLOR (that is, + * RGB24), and that the transformation matrix consists of only a + * translation (in which case the coordinates are munged directly) + * or a translation and scale (in which case SetWorldTransform is used). + * + * If the destination is of a non-win32 surface type, a win32 + * surface of content COLOR_ALPHA, or if there is a complex + * transform (i.e., one with rotation) set, then the native drawing + * code will fall back to alpha recovery, but will still take advantage + * of native axis-aligned scaling. + * + * Typical usage looks like: + * + * gfxWindowsNativeDrawing nativeDraw(ctx, destGfxRect); + * do { + * HDC dc = nativeDraw.BeginNativeDrawing(); + * + * RECT winRect; + * nativeDraw.TransformToNativeRect(rect, winRect); + * + * ... call win32 operations on HDC to draw to winRect ... + * + * nativeDraw.EndNativeDrawing(); + * } while (nativeDraw.ShouldRenderAgain()); + * nativeDraw.PaintToContext(); + */ + gfxWindowsNativeDrawing(gfxContext *ctx, + const gfxRect& nativeRect, + PRUint32 nativeDrawFlags = CANNOT_DRAW_TO_COLOR_ALPHA | + CANNOT_AXIS_ALIGNED_SCALE | + CANNOT_COMPLEX_TRANSFORM | + DO_BILINEAR_FILTERING); + + /* Returns a HDC which may be used for native drawing. This HDC is valid + * until EndNativeDrawing is called; if it is used for drawing after that time, + * the result is undefined. */ + HDC BeginNativeDrawing(); + + /* Transform the native rect into something valid for rendering + * to the HDC. This may or may not change RECT, depending on + * whether SetWorldTransform is used or not. */ + void TransformToNativeRect(const gfxRect& r, RECT& rout); + + /* Marks the end of native drawing */ + void EndNativeDrawing(); + + /* Returns PR_TRUE if the native drawing should be executed again */ + PRBool ShouldRenderAgain(); + + /* Places the result to the context, if necessary */ + void PaintToContext(); + +private: + + nsRefPtr mContext; + gfxRect mNativeRect; + PRUint32 mNativeDrawFlags; + + // what state the rendering is in + PRUint8 mRenderState; + + gfxPoint mDeviceOffset; + nsRefPtr mBlackPattern, mWhitePattern; + + enum TransformType { + TRANSLATION_ONLY, + AXIS_ALIGNED_SCALE, + COMPLEX + }; + + TransformType mTransformType; + gfxPoint mTranslation; + gfxSize mScale; + XFORM mWorldTransform; + + // saved state + nsRefPtr mWinSurface, mBlackSurface, mWhiteSurface; + HDC mDC; + XFORM mOldWorldTransform; + POINT mOrigViewportOrigin; + gfxIntSize mTempSurfaceSize; +}; + +#endif diff --git a/mozilla/gfx/thebes/src/Makefile.in b/mozilla/gfx/thebes/src/Makefile.in index db503f5c2d1..04ce26fedda 100644 --- a/mozilla/gfx/thebes/src/Makefile.in +++ b/mozilla/gfx/thebes/src/Makefile.in @@ -22,6 +22,7 @@ REQUIRES = \ CPPSRCS = \ gfxASurface.cpp \ + gfxAlphaRecovery.cpp \ gfxContext.cpp \ gfxImageSurface.cpp \ gfxFont.cpp \ @@ -55,6 +56,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),windows) CPPSRCS += gfxWindowsFonts.cpp \ gfxWindowsPlatform.cpp \ gfxWindowsSurface.cpp \ + gfxWindowsNativeDrawing.cpp \ nsUnicodeRange.cpp \ $(NULL) CPPSRCS += gfxPDFSurface.cpp diff --git a/mozilla/gfx/thebes/src/gfxAlphaRecovery.cpp b/mozilla/gfx/thebes/src/gfxAlphaRecovery.cpp new file mode 100644 index 00000000000..818c31891ed --- /dev/null +++ b/mozilla/gfx/thebes/src/gfxAlphaRecovery.cpp @@ -0,0 +1,172 @@ + +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Thebes gfx. + * + * The Initial Developer of the Original Code is Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "gfxAlphaRecovery.h" + +#include "gfxImageSurface.h" + + +struct gfxAlphaRecoveryResult { + gfxAlphaRecoveryResult() + : uniformColor(PR_FALSE), + uniformAlpha(PR_FALSE) + { } + PRBool uniformColor; + PRBool uniformAlpha; + gfxFloat alpha; + gfxFloat r, g, b; +}; + +static void _compute_alpha_values (unsigned int *black_data, + unsigned int *white_data, + gfxIntSize dimensions, + gfxAlphaRecoveryResult *result); + +already_AddRefed +gfxAlphaRecovery::RecoverAlpha (gfxImageSurface *blackSurf, + gfxImageSurface *whiteSurf, + gfxIntSize dimensions) +{ + + nsRefPtr resultSurf; + resultSurf = new gfxImageSurface(dimensions, gfxASurface::ImageFormatARGB32); + + // copy blackSurf into resultSurf + nsRefPtr ctx = new gfxContext(resultSurf); + ctx->SetSource(blackSurf); + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); + ctx->Paint(); + ctx = nsnull; + + gfxAlphaRecoveryResult result; + _compute_alpha_values ((unsigned int*) resultSurf->Data(), + (unsigned int*) whiteSurf->Data(), + dimensions, + &result); + + // XX use result, maybe return pattern, etc. + + NS_ADDREF(resultSurf.get()); + return resultSurf; +} + +/** from cairo-xlib-utils.c, modified */ +/** + * Given the RGB data for two image surfaces, one a source image composited + * with OVER onto a black background, and one a source image composited with + * OVER onto a white background, reconstruct the original image data into + * black_data. + * + * Consider a single color channel and a given pixel. Suppose the original + * premultiplied color value was C and the alpha value was A. Let the final + * on-black color be B and the final on-white color be W. All values range + * over 0-255. + * Then B=C and W=(255*(255 - A) + C*255)/255. Solving for A, we get + * A=255 - (W - C). Therefore it suffices to leave the black_data color + * data alone and set the alpha values using that simple formula. It shouldn't + * matter what color channel we pick for the alpha computation, but we'll + * pick green because if we went through a color channel downsample the green + * bits are likely to be the most accurate. + */ + +#define SET_ALPHA(v, a) (((v) & ~(0xFF << 24)) | ((a) << 24)) +#define GREEN_OF(v) (((v) >> 8) & 0xFF) + +static void +_compute_alpha_values (unsigned int *black_data, + unsigned int *white_data, + gfxIntSize dimensions, + gfxAlphaRecoveryResult *result) +{ + int num_pixels = dimensions.width * dimensions.height; + int i; + unsigned int first; + unsigned int deltas = 0; + unsigned char first_alpha; + + if (num_pixels == 0) { + if (result) { + result->uniformAlpha = PR_TRUE; + result->uniformColor = PR_TRUE; + /* whatever we put here will be true */ + result->alpha = 1.0; + result->r = result->g = result->b = 0.0; + } + return; + } + + first_alpha = 255 - (GREEN_OF(*white_data) - GREEN_OF(*black_data)); + /* set the alpha value of 'first' */ + first = SET_ALPHA(*black_data, first_alpha); + + for (i = 0; i < num_pixels; ++i) { + unsigned int black = *black_data; + unsigned int white = *white_data; + unsigned char pixel_alpha = 255 - (GREEN_OF(white) - GREEN_OF(black)); + + black = SET_ALPHA(black, pixel_alpha); + *black_data = black; + deltas |= (first ^ black); + + black_data++; + white_data++; + } + + if (result) { + result->uniformAlpha = (deltas >> 24) == 0; + if (result->uniformAlpha) { + result->alpha = first_alpha/255.0; + /* we only set uniformColor when the alpha is already uniform. + it's only useful in that case ... and if the alpha was nonuniform + then computing whether the color is uniform would require unpremultiplying + every pixel */ + result->uniformColor = (deltas & ~(0xFF << 24)) == 0; + if (result->uniformColor) { + if (first_alpha == 0) { + /* can't unpremultiply, this is OK */ + result->r = result->g = result->b = 0.0; + } else { + double d_first_alpha = first_alpha; + result->r = (first & 0xFF)/d_first_alpha; + result->g = ((first >> 8) & 0xFF)/d_first_alpha; + result->b = ((first >> 16) & 0xFF)/d_first_alpha; + } + } + } + } +} diff --git a/mozilla/gfx/thebes/src/gfxPattern.cpp b/mozilla/gfx/thebes/src/gfxPattern.cpp index 566a9391b24..510a5511f3f 100644 --- a/mozilla/gfx/thebes/src/gfxPattern.cpp +++ b/mozilla/gfx/thebes/src/gfxPattern.cpp @@ -96,7 +96,7 @@ gfxPattern::SetMatrix(const gfxMatrix& matrix) } gfxMatrix -gfxPattern::CurrentMatrix() const +gfxPattern::GetMatrix() const { cairo_matrix_t mat; cairo_pattern_get_matrix(mPattern, &mat); @@ -136,3 +136,15 @@ gfxPattern::GetSolidColor(gfxRGBA& aColor) &aColor.b, &aColor.a) == CAIRO_STATUS_SUCCESS; } + +already_AddRefed +gfxPattern::GetSurface() +{ + cairo_surface_t *surf = nsnull; + + if (cairo_pattern_get_surface (mPattern, &surf) != CAIRO_STATUS_SUCCESS) + return nsnull; + + + return gfxASurface::Wrap(surf); +} diff --git a/mozilla/gfx/thebes/src/gfxWindowsNativeDrawing.cpp b/mozilla/gfx/thebes/src/gfxWindowsNativeDrawing.cpp new file mode 100644 index 00000000000..61f0e3c8410 --- /dev/null +++ b/mozilla/gfx/thebes/src/gfxWindowsNativeDrawing.cpp @@ -0,0 +1,310 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Thebes gfx. + * + * The Initial Developer of the Original Code is Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "nsMathUtils.h" + +#include "gfxWindowsNativeDrawing.h" +#include "gfxWindowsSurface.h" +#include "gfxAlphaRecovery.h" + +enum { + RENDER_STATE_INIT, + + RENDER_STATE_NATIVE_DRAWING, + RENDER_STATE_NATIVE_DRAWING_DONE, + + RENDER_STATE_ALPHA_RECOVERY_BLACK, + RENDER_STATE_ALPHA_RECOVERY_BLACK_DONE, + RENDER_STATE_ALPHA_RECOVERY_WHITE, + RENDER_STATE_ALPHA_RECOVERY_WHITE_DONE, + + RENDER_STATE_DONE +}; + +gfxWindowsNativeDrawing::gfxWindowsNativeDrawing(gfxContext* ctx, + const gfxRect& nativeRect, + PRUint32 nativeDrawFlags) + : mContext(ctx), mNativeRect(nativeRect), mNativeDrawFlags(nativeDrawFlags), mRenderState(RENDER_STATE_INIT) +{ +} + +HDC +gfxWindowsNativeDrawing::BeginNativeDrawing() +{ + if (mRenderState == RENDER_STATE_INIT) { + nsRefPtr surf = mContext->CurrentSurface(&mDeviceOffset.x, &mDeviceOffset.y); + + gfxMatrix m = mContext->CurrentMatrix(); + if (!m.HasNonTranslation()) + mTransformType = TRANSLATION_ONLY; + else if (m.HasNonAxisAlignedTransform()) + mTransformType = COMPLEX; + else + mTransformType = AXIS_ALIGNED_SCALE; + + // if this is a native win32 surface, we don't have to + // redirect rendering to our own HDC; in some cases, + // we may be able to use the HDC from the surface directly. + if (surf->GetType() == gfxASurface::SurfaceTypeWin32 && + (surf->GetContentType() == gfxASurface::CONTENT_COLOR || + (surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA && + (mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA)))) + { + if (mTransformType == TRANSLATION_ONLY) { + mRenderState = RENDER_STATE_NATIVE_DRAWING; + + mTranslation = m.GetTranslation(); + + mWinSurface = NS_STATIC_CAST(gfxWindowsSurface*, NS_STATIC_CAST(gfxASurface*, surf.get())); + } else if (((mTransformType == AXIS_ALIGNED_SCALE) + && (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) || + (mNativeDrawFlags & CAN_COMPLEX_TRANSFORM)) + { + mWorldTransform.eM11 = (FLOAT) m.xx; + mWorldTransform.eM12 = (FLOAT) m.yx; + mWorldTransform.eM21 = (FLOAT) m.xy; + mWorldTransform.eM22 = (FLOAT) m.yy; + mWorldTransform.eDx = (FLOAT) m.x0; + mWorldTransform.eDy = (FLOAT) m.y0; + + mRenderState = RENDER_STATE_NATIVE_DRAWING; + mWinSurface = NS_STATIC_CAST(gfxWindowsSurface*, NS_STATIC_CAST(gfxASurface*, surf.get())); + } + } + + // If we couldn't do native drawing, then we have to do two-buffer drawing + // and do alpha recovery + if (mRenderState == RENDER_STATE_INIT) { + mRenderState = RENDER_STATE_ALPHA_RECOVERY_BLACK; + + // we only do the scale bit if we can do an axis aligned + // scale; otherwise we scale (if necessary) after + // rendering with cairo. Note that if we're doing alpha recovery, + // we cannot do a full complex transform with win32 (I mean, we could, but + // it would require more code that's not here.) + if (mTransformType == TRANSLATION_ONLY || !(mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) { + mScale = gfxSize(1.0, 1.0); + + mTempSurfaceSize.width = (PRInt32) NS_ceil(mNativeRect.size.width); + mTempSurfaceSize.height = (PRInt32) NS_ceil(mNativeRect.size.height); + } else { + // figure out the scale factors + mScale = m.ScaleFactors(PR_TRUE); + + mWorldTransform.eM11 = (FLOAT) mScale.width; + mWorldTransform.eM12 = 0.0f; + mWorldTransform.eM21 = 0.0f; + mWorldTransform.eM22 = (FLOAT) mScale.height; + mWorldTransform.eDx = 0.0f; + mWorldTransform.eDy = 0.0f; + + mTempSurfaceSize.width = (PRInt32) NS_ceil(mNativeRect.size.width * mScale.width); + mTempSurfaceSize.height = (PRInt32) NS_ceil(mNativeRect.size.height * mScale.height); + } + } + } + + if (mRenderState == RENDER_STATE_NATIVE_DRAWING) { + // we can just do native drawing directly to the context's surface + + // Need to force the clip to be set + mContext->UpdateSurfaceClip(); + + // grab the DC + mDC = mWinSurface->GetDC(); + + // do we need to use SetWorldTransform? + if (mTransformType != TRANSLATION_ONLY) { + SetGraphicsMode(mDC, GM_ADVANCED); + GetWorldTransform(mDC, &mOldWorldTransform); + SetWorldTransform(mDC, &mWorldTransform); + } + + GetViewportOrgEx(mDC, &mOrigViewportOrigin); + SetViewportOrgEx(mDC, + mOrigViewportOrigin.x + (int)mDeviceOffset.x, + mOrigViewportOrigin.y + (int)mDeviceOffset.y, + NULL); + + return mDC; + } else if (mRenderState == RENDER_STATE_ALPHA_RECOVERY_BLACK || + mRenderState == RENDER_STATE_ALPHA_RECOVERY_WHITE) + { + // we're going to use mWinSurface to create our temporary surface here + + // get us a RGB24 DIB; DIB is important, because + // we can later call GetImageSurface on it. + mWinSurface = new gfxWindowsSurface(mTempSurfaceSize); + mDC = mWinSurface->GetDC(); + + RECT r = { 0, 0, mTempSurfaceSize.width, mTempSurfaceSize.height }; + if (mRenderState == RENDER_STATE_ALPHA_RECOVERY_BLACK) + FillRect(mDC, &r, (HBRUSH)GetStockObject(BLACK_BRUSH)); + else + FillRect(mDC, &r, (HBRUSH)GetStockObject(WHITE_BRUSH)); + + if ((mTransformType != TRANSLATION_ONLY) && + (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) + { + SetGraphicsMode(mDC, GM_ADVANCED); + SetWorldTransform(mDC, &mWorldTransform); + } + + return mDC; + } else { + NS_ERROR("Bogus render state!"); + return nsnull; + } +} + +PRBool +gfxWindowsNativeDrawing::ShouldRenderAgain() +{ + switch (mRenderState) { + case RENDER_STATE_NATIVE_DRAWING_DONE: + return PR_FALSE; + + case RENDER_STATE_ALPHA_RECOVERY_BLACK_DONE: + mRenderState = RENDER_STATE_ALPHA_RECOVERY_WHITE; + return PR_TRUE; + + case RENDER_STATE_ALPHA_RECOVERY_WHITE_DONE: + return PR_FALSE; + + default: + NS_ERROR("Invalid RenderState in gfxWindowsNativeDrawing::ShouldRenderAgain"); + break; + } + + return PR_FALSE; +} + +void +gfxWindowsNativeDrawing::EndNativeDrawing() +{ + if (mRenderState == RENDER_STATE_NATIVE_DRAWING) { + // we drew directly to the HDC in the context; undo our changes + SetViewportOrgEx(mDC, mOrigViewportOrigin.x, mOrigViewportOrigin.y, NULL); + + if (mTransformType != TRANSLATION_ONLY) + SetWorldTransform(mDC, &mOldWorldTransform); + + mWinSurface->MarkDirty(); + + mRenderState = RENDER_STATE_NATIVE_DRAWING_DONE; + } else if (mRenderState == RENDER_STATE_ALPHA_RECOVERY_BLACK) { + mBlackSurface = mWinSurface; + mWinSurface = nsnull; + + mRenderState = RENDER_STATE_ALPHA_RECOVERY_BLACK_DONE; + } else if (mRenderState == RENDER_STATE_ALPHA_RECOVERY_WHITE) { + mWhiteSurface = mWinSurface; + mWinSurface = nsnull; + + mRenderState = RENDER_STATE_ALPHA_RECOVERY_WHITE_DONE; + } else { + NS_ERROR("Invalid RenderState in gfxWindowsNativeDrawing::EndNativeDrawing"); + } +} + +void +gfxWindowsNativeDrawing::PaintToContext() +{ + if (mRenderState == RENDER_STATE_NATIVE_DRAWING_DONE) { + // nothing to do, it already went to the context + mRenderState = RENDER_STATE_DONE; + } else if (mRenderState == RENDER_STATE_ALPHA_RECOVERY_WHITE_DONE) { + nsRefPtr black = mBlackSurface->GetImageSurface(); + nsRefPtr white = mWhiteSurface->GetImageSurface(); + nsRefPtr alphaSurface = + gfxAlphaRecovery::RecoverAlpha(black, white, mTempSurfaceSize); + + mContext->Save(); + mContext->MoveTo(mNativeRect.pos); + mContext->NewPath(); + mContext->Rectangle(gfxRect(gfxPoint(0.0, 0.0), mNativeRect.size)); + + nsRefPtr pat = new gfxPattern(alphaSurface); + + gfxMatrix m; + m.Scale(mScale.width, mScale.height); + pat->SetMatrix(m); + + if (mNativeDrawFlags & DO_NEAREST_NEIGHBOR_FILTERING) + pat->SetFilter(0); + + mContext->SetPattern(pat); + mContext->Fill(); + mContext->Restore(); + + mRenderState = RENDER_STATE_DONE; + } else { + NS_ERROR("Invalid RenderState in gfxWindowsNativeDrawing::PaintToContext"); + } +} + +void +gfxWindowsNativeDrawing::TransformToNativeRect(const gfxRect& r, + RECT& rout) +{ + /* If we're doing native drawing, then we're still in the coordinate space + * of the context; otherwise, we're in our own little world, + * relative to the passed-in nativeRect. + */ + if (mRenderState == RENDER_STATE_NATIVE_DRAWING) { + if (mTransformType == TRANSLATION_ONLY) { + rout.left = (LONG) (r.pos.x + NS_round(mTranslation.x)); + rout.right = (LONG) (rout.left + r.size.width); + rout.top = (LONG) (r.pos.y + NS_round(mTranslation.y)); + rout.bottom = (LONG) (rout.top + r.size.height); + } else { + rout.left = (LONG) r.pos.x; + rout.right = (LONG) (r.pos.x + r.size.width); + rout.top = (LONG) r.pos.y; + rout.bottom = (LONG) (r.pos.y + r.size.height); + } + } else { + rout.left = (LONG) (r.pos.x - NS_round(mNativeRect.pos.x)); + rout.right = (LONG) (rout.left + r.size.width); + rout.top = (LONG) (r.pos.y - NS_round(mNativeRect.pos.y)); + rout.bottom = (LONG) (rout.top + r.size.height); + } +} + + diff --git a/mozilla/widget/src/windows/nsNativeThemeWin.cpp b/mozilla/widget/src/windows/nsNativeThemeWin.cpp index 60572ba9dcf..badb030ba7a 100644 --- a/mozilla/widget/src/windows/nsNativeThemeWin.cpp +++ b/mozilla/widget/src/windows/nsNativeThemeWin.cpp @@ -59,11 +59,11 @@ #include "nsWidgetAtoms.h" #include -#ifdef MOZ_CAIRO_GFX #include "gfxContext.h" #include "gfxMatrix.h" #include "gfxWindowsSurface.h" -#endif +#include "gfxWindowsNativeDrawing.h" + /* * The following constants are used to determine how a widget is drawn using * Windows' Theme API. For more information on theme parts and states see @@ -821,99 +821,38 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext, PRInt32 p2a = dc->AppUnitsPerDevPixel(); RECT widgetRect; RECT clipRect; - nsRect tr(aRect); - nsRect cr(aClipRect); + gfxRect tr, cr; -#ifdef MOZ_CAIRO_GFX - tr.x = NSAppUnitsToIntPixels(tr.x, p2a); - tr.y = NSAppUnitsToIntPixels(tr.y, p2a); - tr.width = NSAppUnitsToIntPixels(tr.width, p2a); - tr.height = NSAppUnitsToIntPixels(tr.height, p2a); + tr.pos.x = NSAppUnitsToIntPixels(aRect.x, p2a); + tr.pos.y = NSAppUnitsToIntPixels(aRect.y, p2a); + tr.size.width = NSAppUnitsToIntPixels(aRect.width, p2a); + tr.size.height = NSAppUnitsToIntPixels(aRect.height, p2a); - cr.x = NSAppUnitsToIntPixels(cr.x, p2a); - cr.y = NSAppUnitsToIntPixels(cr.y, p2a); - cr.width = NSAppUnitsToIntPixels(cr.width, p2a); - cr.height = NSAppUnitsToIntPixels(cr.height, p2a); + cr.pos.x = NSAppUnitsToIntPixels(aClipRect.x, p2a); + cr.pos.y = NSAppUnitsToIntPixels(aClipRect.y, p2a); + cr.size.width = NSAppUnitsToIntPixels(aClipRect.width, p2a); + cr.size.height = NSAppUnitsToIntPixels(aClipRect.height, p2a); nsRefPtr ctx = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT); - gfxPoint offset; - nsRefPtr surf = ctx->CurrentSurface(&offset.x, &offset.y); + gfxWindowsNativeDrawing nativeDrawing(ctx, cr, GetWidgetNativeDrawingFlags(aWidgetType)); - HDC hdc = NS_STATIC_CAST(gfxWindowsSurface*, NS_STATIC_CAST(gfxASurface*, surf.get()))->GetDC(); +RENDER_AGAIN: - /* Need to force the clip to be set */ - ctx->UpdateSurfaceClip(); + HDC hdc = nativeDrawing.BeginNativeDrawing(); - /* Covert the current transform to a world transform */ - XFORM oldWorldTransform; - gfxMatrix m = ctx->CurrentMatrix(); - if (m.HasNonTranslation()) { - GetWorldTransform(hdc, &oldWorldTransform); - - SetGraphicsMode(hdc, GM_ADVANCED); - XFORM xform; - xform.eM11 = (FLOAT) m.xx; - xform.eM12 = (FLOAT) m.yx; - xform.eM21 = (FLOAT) m.xy; - xform.eM22 = (FLOAT) m.yy; - xform.eDx = (FLOAT) m.x0; - xform.eDy = (FLOAT) m.y0; - SetWorldTransform (hdc, &xform); - } else { - gfxPoint pos(m.GetTranslation()); - - tr.x += NSToCoordRound(pos.x); - tr.y += NSToCoordRound(pos.y); - cr.x += NSToCoordRound(pos.x); - cr.y += NSToCoordRound(pos.y); - } + nativeDrawing.TransformToNativeRect(tr, widgetRect); + nativeDrawing.TransformToNativeRect(cr, clipRect); #if 0 { - double dm[6]; - m.ToValues(&dm[0], &dm[1], &dm[2], &dm[3], &dm[4], &dm[5]); - fprintf (stderr, "xform: %f %f %f %f [%f %f]\n", dm[0], dm[1], dm[2], dm[3], dm[4], dm[5]); - fprintf (stderr, "tr: [%d %d %d %d]\ncr: [%d %d %d %d]\noff: [%f %f]\n", - tr.x, tr.y, tr.width, tr.height, cr.x, cr.y, cr.width, cr.height, - offset.x, offset.y); - fflush (stderr); + fprintf (stderr, "xform: %f %f %f %f [%f %f]\n", m.xx, m.yx, m.xy, m.yy, m.x0, m.y0); + fprintf (stderr, "tr: [%d %d %d %d]\ncr: [%d %d %d %d]\noff: [%f %f]\n", + tr.x, tr.y, tr.width, tr.height, cr.x, cr.y, cr.width, cr.height, + offset.x, offset.y); } #endif - /* Set the device offsets as appropriate */ - POINT origViewportOrigin, origBrushOrigin; - GetViewportOrgEx(hdc, &origViewportOrigin); - SetViewportOrgEx(hdc, origViewportOrigin.x + (int)offset.x, origViewportOrigin.y + (int)offset.y, NULL); - -#else /* non-MOZ_CAIRO_GFX */ - - nsTransform2D* transformMatrix; - aContext->GetCurrentTransform(transformMatrix); - - transformMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height); - transformMatrix->TransformCoord(&cr.x,&cr.y,&cr.width,&cr.height); - - HDC hdc = (HDC)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC); - if (!hdc) - return NS_ERROR_FAILURE; - -#ifndef WINCE - SetGraphicsMode(hdc, GM_ADVANCED); -#endif - -#endif /* MOZ_CAIRO_GFX */ - - GetNativeRect(tr, widgetRect); - GetNativeRect(cr, clipRect); - -#if 0 - fprintf (stderr, "widget: [%d %d %d %d]\nclip: [%d %d %d %d]\n", - widgetRect.left, widgetRect.top, widgetRect.right, widgetRect.bottom, - clipRect.left, clipRect.top, clipRect.right, clipRect.bottom); - fflush (stderr); -#endif - // For left edge and right edge tabs, we need to adjust the widget // rects and clip rects so that the edges don't get drawn. if (aWidgetType == NS_THEME_TAB_LEFT_EDGE || aWidgetType == NS_THEME_TAB_RIGHT_EDGE) { @@ -1003,14 +942,12 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext, } } -#ifdef MOZ_CAIRO_GFX - SetViewportOrgEx(hdc, origViewportOrigin.x, origViewportOrigin.y, NULL); + nativeDrawing.EndNativeDrawing(); - if (m.HasNonTranslation()) - SetWorldTransform(hdc, &oldWorldTransform); + if (nativeDrawing.ShouldRenderAgain()) + goto RENDER_AGAIN; - surf->MarkDirty(); -#endif + nativeDrawing.PaintToContext(); return NS_OK; } @@ -2000,7 +1937,7 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon PRUint8 aWidgetType, const nsRect& aRect, const nsRect& aClipRect) -{ +{ PRInt32 part, state; PRBool focused; nsresult rv; @@ -2012,61 +1949,27 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon aContext->GetDeviceContext(*getter_AddRefs(dc)); PRInt32 p2a = dc->AppUnitsPerDevPixel(); RECT widgetRect; - nsRect tr(aRect); + gfxRect tr, cr; -#ifdef MOZ_CAIRO_GFX - tr.x = NSAppUnitsToIntPixels(tr.x, p2a); - tr.y = NSAppUnitsToIntPixels(tr.y, p2a); - tr.width = NSAppUnitsToIntPixels(tr.width, p2a); - tr.height = NSAppUnitsToIntPixels(tr.height, p2a); + tr.pos.x = NSAppUnitsToIntPixels(aRect.x, p2a); + tr.pos.y = NSAppUnitsToIntPixels(aRect.y, p2a); + tr.size.width = NSAppUnitsToIntPixels(aRect.width, p2a); + tr.size.height = NSAppUnitsToIntPixels(aRect.height, p2a); + + cr.pos.x = NSAppUnitsToIntPixels(aClipRect.x, p2a); + cr.pos.y = NSAppUnitsToIntPixels(aClipRect.y, p2a); + cr.size.width = NSAppUnitsToIntPixels(aClipRect.width, p2a); + cr.size.height = NSAppUnitsToIntPixels(aClipRect.height, p2a); nsRefPtr ctx = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT); - gfxPoint offset; - nsRefPtr surf = ctx->CurrentSurface(&offset.x, &offset.y); - HDC hdc = NS_STATIC_CAST(gfxWindowsSurface*, NS_STATIC_CAST(gfxASurface*, surf.get()))->GetDC(); + gfxWindowsNativeDrawing nativeDrawing(ctx, cr, GetWidgetNativeDrawingFlags(aWidgetType)); - /* Need to force the clip to be set */ - ctx->UpdateSurfaceClip(); +RENDER_AGAIN: - /* Covert the current transform to a world transform */ - XFORM oldWorldTransform; - gfxMatrix m = ctx->CurrentMatrix(); - if (m.HasNonTranslation()) { - GetWorldTransform(hdc, &oldWorldTransform); + HDC hdc = nativeDrawing.BeginNativeDrawing(); - SetGraphicsMode(hdc, GM_ADVANCED); - XFORM xform; - xform.eM11 = (FLOAT) m.xx; - xform.eM12 = (FLOAT) m.yx; - xform.eM21 = (FLOAT) m.xy; - xform.eM22 = (FLOAT) m.yy; - xform.eDx = (FLOAT) m.x0; - xform.eDy = (FLOAT) m.y0; - SetWorldTransform (hdc, &xform); - } else { - gfxPoint pos(m.GetTranslation()); - - tr.x += NSToCoordRound(pos.x); - tr.y += NSToCoordRound(pos.y); - } - - /* Set the device offsets as appropriate */ - POINT origViewportOrigin; - GetViewportOrgEx(hdc, &origViewportOrigin); - SetViewportOrgEx(hdc, origViewportOrigin.x + (int)offset.x, origViewportOrigin.y + (int)offset.y, NULL); - -#else /* non-MOZ_CAIRO_GFX */ - - nsTransform2D* transformMatrix; - aContext->GetCurrentTransform(transformMatrix); - transformMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height); - - HDC hdc = (HDC)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC); - -#endif /* MOZ_CAIRO_GFX */ - - GetNativeRect(tr, widgetRect); + nativeDrawing.TransformToNativeRect(tr, widgetRect); rv = NS_OK; switch (aWidgetType) { @@ -2336,18 +2239,89 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon break; } -#ifdef MOZ_CAIRO_GFX - SetViewportOrgEx(hdc, origViewportOrigin.x, origViewportOrigin.y, NULL); + nativeDrawing.EndNativeDrawing(); - if (m.HasNonTranslation()) - SetWorldTransform(hdc, &oldWorldTransform); + if (NS_FAILED(rv)) + return rv; - surf->MarkDirty(); -#endif + if (nativeDrawing.ShouldRenderAgain()) + goto RENDER_AGAIN; + + nativeDrawing.PaintToContext(); return rv; } +PRUint32 +nsNativeThemeWin::GetWidgetNativeDrawingFlags(PRUint8 aWidgetType) +{ + switch (aWidgetType) { + case NS_THEME_BUTTON: + case NS_THEME_TEXTFIELD: + + case NS_THEME_DROPDOWN: + case NS_THEME_DROPDOWN_TEXTFIELD: + return + gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA | + gfxWindowsNativeDrawing::CAN_AXIS_ALIGNED_SCALE | + gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM; + + // need to check these others + case NS_THEME_SCROLLBAR_BUTTON_UP: + case NS_THEME_SCROLLBAR_BUTTON_DOWN: + case NS_THEME_SCROLLBAR_BUTTON_LEFT: + case NS_THEME_SCROLLBAR_BUTTON_RIGHT: + case NS_THEME_SCROLLBAR_THUMB_VERTICAL: + case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL: + case NS_THEME_SCROLLBAR_TRACK_VERTICAL: + case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: + case NS_THEME_SCALE_HORIZONTAL: + case NS_THEME_SCALE_VERTICAL: + case NS_THEME_SCALE_THUMB_HORIZONTAL: + case NS_THEME_SCALE_THUMB_VERTICAL: + case NS_THEME_SPINNER_UP_BUTTON: + case NS_THEME_SPINNER_DOWN_BUTTON: + case NS_THEME_LISTBOX: + case NS_THEME_TREEVIEW: + case NS_THEME_TOOLTIP: + case NS_THEME_STATUSBAR: + case NS_THEME_STATUSBAR_PANEL: + case NS_THEME_STATUSBAR_RESIZER_PANEL: + case NS_THEME_RESIZER: + case NS_THEME_PROGRESSBAR: + case NS_THEME_PROGRESSBAR_VERTICAL: + case NS_THEME_PROGRESSBAR_CHUNK: + case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL: + case NS_THEME_TAB: + case NS_THEME_TAB_LEFT_EDGE: + case NS_THEME_TAB_RIGHT_EDGE: + case NS_THEME_TAB_PANEL: + case NS_THEME_TAB_PANELS: + case NS_THEME_MENUBAR: + case NS_THEME_MENUPOPUP: + case NS_THEME_MENUITEM: + break; + + // the dropdown button /almost/ renders correctly with scaling, + // except that the graphic in the dropdown button (the downward arrow) + // doesn't get scaled up. + case NS_THEME_DROPDOWN_BUTTON: + // these are definitely no; they're all graphics that don't get scaled up + case NS_THEME_CHECKBOX: + case NS_THEME_RADIO: + case NS_THEME_CHECKMENUITEM: + case NS_THEME_RADIOMENUITEM: + return + gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA | + gfxWindowsNativeDrawing::CANNOT_AXIS_ALIGNED_SCALE | + gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM; + } + + return + gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA | + gfxWindowsNativeDrawing::CANNOT_AXIS_ALIGNED_SCALE | + gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM; +} /////////////////////////////////////////// // Creation Routine diff --git a/mozilla/widget/src/windows/nsNativeThemeWin.h b/mozilla/widget/src/windows/nsNativeThemeWin.h index 8f5f9f888c0..df4eeab0f5f 100644 --- a/mozilla/widget/src/windows/nsNativeThemeWin.h +++ b/mozilla/widget/src/windows/nsNativeThemeWin.h @@ -116,6 +116,8 @@ protected: void DrawCheckedRect(HDC hdc, const RECT& rc, PRInt32 fore, PRInt32 back, HBRUSH defaultBack); + PRUint32 GetWidgetNativeDrawingFlags(PRUint8 aWidgetType); + private: HMODULE mThemeDLL; HANDLE mButtonTheme;