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
This commit is contained in:
parent
9decb54e91
commit
76df446d7a
@ -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
|
||||
|
||||
55
mozilla/gfx/thebes/public/gfxAlphaRecovery.h
Normal file
55
mozilla/gfx/thebes/public/gfxAlphaRecovery.h
Normal file
@ -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 <vladimir@pobox.com>
|
||||
*
|
||||
* 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<gfxImageSurface> RecoverAlpha (gfxImageSurface *blackSurface,
|
||||
gfxImageSurface *whiteSurface,
|
||||
gfxIntSize dimensions);
|
||||
};
|
||||
|
||||
#endif /* _GFXALPHARECOVERY_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 */
|
||||
|
||||
@ -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<gfxASurface> GetSurface();
|
||||
|
||||
protected:
|
||||
cairo_pattern_t *mPattern;
|
||||
};
|
||||
|
||||
158
mozilla/gfx/thebes/public/gfxWindowsNativeDrawing.h
Normal file
158
mozilla/gfx/thebes/public/gfxWindowsNativeDrawing.h
Normal file
@ -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 <vladimir@pobox.com>
|
||||
*
|
||||
* 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 <windows.h>
|
||||
|
||||
#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<gfxContext> mContext;
|
||||
gfxRect mNativeRect;
|
||||
PRUint32 mNativeDrawFlags;
|
||||
|
||||
// what state the rendering is in
|
||||
PRUint8 mRenderState;
|
||||
|
||||
gfxPoint mDeviceOffset;
|
||||
nsRefPtr<gfxPattern> mBlackPattern, mWhitePattern;
|
||||
|
||||
enum TransformType {
|
||||
TRANSLATION_ONLY,
|
||||
AXIS_ALIGNED_SCALE,
|
||||
COMPLEX
|
||||
};
|
||||
|
||||
TransformType mTransformType;
|
||||
gfxPoint mTranslation;
|
||||
gfxSize mScale;
|
||||
XFORM mWorldTransform;
|
||||
|
||||
// saved state
|
||||
nsRefPtr<gfxWindowsSurface> mWinSurface, mBlackSurface, mWhiteSurface;
|
||||
HDC mDC;
|
||||
XFORM mOldWorldTransform;
|
||||
POINT mOrigViewportOrigin;
|
||||
gfxIntSize mTempSurfaceSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -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
|
||||
|
||||
172
mozilla/gfx/thebes/src/gfxAlphaRecovery.cpp
Normal file
172
mozilla/gfx/thebes/src/gfxAlphaRecovery.cpp
Normal file
@ -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 <vladimir@pobox.com>
|
||||
*
|
||||
* 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<gfxImageSurface>
|
||||
gfxAlphaRecovery::RecoverAlpha (gfxImageSurface *blackSurf,
|
||||
gfxImageSurface *whiteSurf,
|
||||
gfxIntSize dimensions)
|
||||
{
|
||||
|
||||
nsRefPtr<gfxImageSurface> resultSurf;
|
||||
resultSurf = new gfxImageSurface(dimensions, gfxASurface::ImageFormatARGB32);
|
||||
|
||||
// copy blackSurf into resultSurf
|
||||
nsRefPtr<gfxContext> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<gfxASurface>
|
||||
gfxPattern::GetSurface()
|
||||
{
|
||||
cairo_surface_t *surf = nsnull;
|
||||
|
||||
if (cairo_pattern_get_surface (mPattern, &surf) != CAIRO_STATUS_SUCCESS)
|
||||
return nsnull;
|
||||
|
||||
|
||||
return gfxASurface::Wrap(surf);
|
||||
}
|
||||
|
||||
310
mozilla/gfx/thebes/src/gfxWindowsNativeDrawing.cpp
Normal file
310
mozilla/gfx/thebes/src/gfxWindowsNativeDrawing.cpp
Normal file
@ -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 <vladimir@pobox.com>
|
||||
*
|
||||
* 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 <windows.h>
|
||||
|
||||
#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<gfxASurface> 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<gfxImageSurface> black = mBlackSurface->GetImageSurface();
|
||||
nsRefPtr<gfxImageSurface> white = mWhiteSurface->GetImageSurface();
|
||||
nsRefPtr<gfxImageSurface> 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<gfxPattern> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -59,11 +59,11 @@
|
||||
#include "nsWidgetAtoms.h"
|
||||
#include <malloc.h>
|
||||
|
||||
#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<gfxContext> ctx = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
|
||||
|
||||
gfxPoint offset;
|
||||
nsRefPtr<gfxASurface> 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<gfxContext> ctx = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
|
||||
|
||||
gfxPoint offset;
|
||||
nsRefPtr<gfxASurface> 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
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user