speed up windows text rendering by avoiding using cairo when possible. also avoid save/restore dc when doing native themes. bug 342366. r=vlad

This commit is contained in:
pavlov%pavlov.net 2006-08-09 20:25:07 +00:00
Родитель 006fe6875e
Коммит 3866d8b63e
16 изменённых файлов: 407 добавлений и 88 удалений

Просмотреть файл

@ -2451,7 +2451,8 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, PRInt32 aX, PRInt3
//mThebesContext->Rectangle(gfxRect(0, 0, aW, aH));
//mThebesContext->Clip();
mThebesContext->PushGroup(NS_GET_A(bgColor) == 0xff ? gfxContext::CONTENT_COLOR_ALPHA : gfxContext::CONTENT_COLOR_ALPHA);
// XXX vlad says this shouldn't both be COLOR_ALPHA but that it is a workaround for some bug
mThebesContext->PushGroup(NS_GET_A(bgColor) == 0xff ? gfxASurface::CONTENT_COLOR_ALPHA : gfxASurface::CONTENT_COLOR_ALPHA);
// draw background color
if (NS_GET_A(bgColor) > 0) {

Просмотреть файл

@ -1464,3 +1464,69 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_pattern_get_solid_color
* @pattern: a #cairo_pattern_t
* @r, @g, @b, @a: a double to return a color value in. must not be NULL.
*
* Gets the solid color for a solid color pattern.
*
* Return value: CAIRO_STATUS_SUCCESS, or
* CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
* color pattern.
**/
cairo_status_t
cairo_pattern_get_solid_color (cairo_pattern_t *pattern,
double *r, double *g, double *b, double *a)
{
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
assert(r && g && b && a);
if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
_cairo_color_get_rgba (&solid->color, r, g, b, a);
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_pattern_get_color_stop
* @pattern: a #cairo_pattern_t
* @stop_index: a number from 0 to 1 minus the number of color stops
* @offset: a double representing the color stop offset
* @r, @g, @b, @a: a double to return a color value in. must not be NULL.
*
* Gets the color stop from a gradient pattern. The caller should
* keep increasing stop_index until this function returns CAIRO_STATUS_INVALID_INDEX
*
* Return value: CAIRO_STATUS_SUCCESS, or CAIRO_STATUS_INVALID_INDEX if there
* is no stop at the given index. If the pattern is not a gradient pattern,
* CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
**/
cairo_status_t
cairo_pattern_get_color_stop (cairo_pattern_t *pattern,
int stop_index, double *offset,
double *r, double *g, double *b, double *a)
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
assert(offset && r && g && b && a);
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR ||
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
if (stop_index < 0 || stop_index >= gradient->n_stops)
return CAIRO_STATUS_INVALID_INDEX;
*offset = _cairo_fixed_to_double(gradient->stops[stop_index].x);
*r = gradient->stops[stop_index].color.red / (double) 0xffff;
*g = gradient->stops[stop_index].color.green / (double) 0xffff;
*b = gradient->stops[stop_index].color.blue / (double) 0xffff;
*a = gradient->stops[stop_index].color.alpha / (double) 0xffff;
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -168,6 +168,7 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_FILE_NOT_FOUND: file not found
* @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting
* @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2)
* @CAIRO_STATUS_INVALID_INDEX: invalid index value for a getter (Since 1.3+)
*
* #cairo_status_t is used to indicate errors that can occur when
* using Cairo. In some cases it is returned directly by functions.
@ -195,7 +196,8 @@ typedef enum _cairo_status {
CAIRO_STATUS_INVALID_VISUAL,
CAIRO_STATUS_FILE_NOT_FOUND,
CAIRO_STATUS_INVALID_DASH,
CAIRO_STATUS_INVALID_DSC_COMMENT
CAIRO_STATUS_INVALID_DSC_COMMENT,
CAIRO_STATUS_INVALID_INDEX
} cairo_status_t;
/**
@ -1505,6 +1507,15 @@ cairo_public void
cairo_pattern_get_matrix (cairo_pattern_t *pattern,
cairo_matrix_t *matrix);
cairo_public cairo_status_t
cairo_pattern_get_solid_color (cairo_pattern_t *pattern,
double *r, double *g, double *b, double *a);
cairo_public cairo_status_t
cairo_pattern_get_color_stop (cairo_pattern_t *pattern,
int stop_index, double *offset,
double *r, double *g, double *b, double *a);
/**
* cairo_extend_t
* @CAIRO_EXTEND_NONE: pixels outside of the source pattern

Просмотреть файл

@ -888,7 +888,7 @@ nsThebesRenderingContext::PushFilter(const nsRect& twRect, PRBool aAreaIsOpaque,
mThebes->Save();
mThebes->Clip(GFX_RECT_FROM_TWIPS_RECT(twRect));
mThebes->PushGroup(gfxContext::CONTENT_COLOR_ALPHA);
mThebes->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
return NS_OK;
}
@ -1183,6 +1183,11 @@ nsThebesRenderingContext::GetWidth(PRUnichar aC, nscoord &aWidth, PRInt32 *aFont
NS_IMETHODIMP
nsThebesRenderingContext::GetWidthInternal(const char* aString, PRUint32 aLength, nscoord& aWidth)
{
#ifdef DISABLE_TEXT
aWidth = (8 * aLength);
return NS_OK;
#endif
if (aLength == 0) {
aWidth = 0;
return NS_OK;
@ -1195,6 +1200,11 @@ NS_IMETHODIMP
nsThebesRenderingContext::GetWidthInternal(const PRUnichar *aString, PRUint32 aLength,
nscoord &aWidth, PRInt32 *aFontID)
{
#ifdef DISABLE_TEXT
aWidth = (8 * aLength);
return NS_OK;
#endif
if (aLength == 0) {
aWidth = 0;
return NS_OK;
@ -1277,6 +1287,10 @@ nsThebesRenderingContext::DrawStringInternal(const char *aString, PRUint32 aLeng
nscoord aX, nscoord aY,
const nscoord* aSpacing)
{
#ifdef DISABLE_TEXT
return NS_OK;
#endif
return mFontMetrics->DrawString(aString, aLength, aX, aY, aSpacing,
this);
}
@ -1287,6 +1301,10 @@ nsThebesRenderingContext::DrawStringInternal(const PRUnichar *aString, PRUint32
PRInt32 aFontID,
const nscoord* aSpacing)
{
#ifdef DISABLE_TEXT
return NS_OK;
#endif
return mFontMetrics->DrawString(aString, aLength, aX, aY, aFontID,
aSpacing, this);
}

Просмотреть файл

@ -79,6 +79,12 @@ public:
SurfaceTypeQuartz2
} gfxSurfaceType;
typedef enum {
CONTENT_COLOR = CAIRO_CONTENT_COLOR,
CONTENT_ALPHA = CAIRO_CONTENT_ALPHA,
CONTENT_COLOR_ALPHA = CAIRO_CONTENT_COLOR_ALPHA
} gfxContentType;
/* Wrap the given cairo surface and return a gfxASurface for it */
static already_AddRefed<gfxASurface> Wrap(cairo_surface_t *csurf);
@ -87,6 +93,8 @@ public:
gfxSurfaceType GetType() const { return (gfxSurfaceType)cairo_surface_get_type(mSurface); }
gfxContentType GetContentType() const { return (gfxContentType)cairo_surface_get_content(mSurface); }
void SetDeviceOffset (gfxFloat xOff, gfxFloat yOff) {
cairo_surface_set_device_offset(mSurface,
xOff, yOff);

Просмотреть файл

@ -319,9 +319,11 @@ public:
void SetColor(const gfxRGBA& c);
/**
* Uses a pattern for drawing.
* Gets the current color.
* returns PR_FALSE if there is something other than a color
* set as the current source (pattern, surface, etc)
*/
void SetPattern(gfxPattern *pattern);
PRBool GetColor(gfxRGBA& c);
/**
* Uses a surface for drawing. This is a shorthand for creating a
@ -331,6 +333,16 @@ public:
*/
void SetSource(gfxASurface *surface, gfxPoint offset = gfxPoint(0.0, 0.0));
/**
* Uses a pattern for drawing.
*/
void SetPattern(gfxPattern *pattern);
/**
* Get the source pattern (solid color, normal pattern, surface, etc)
*/
already_AddRefed<gfxPattern> GetPattern();
/**
** Painting
**/
@ -494,13 +506,7 @@ public:
/**
* Groups
*/
enum SurfaceContent {
CONTENT_COLOR = CAIRO_CONTENT_COLOR,
CONTENT_ALPHA = CAIRO_CONTENT_ALPHA,
CONTENT_COLOR_ALPHA = CAIRO_CONTENT_COLOR_ALPHA
};
void PushGroup(SurfaceContent content = CONTENT_COLOR_ALPHA);
void PushGroup(gfxASurface::gfxContentType content = gfxASurface::CONTENT_COLOR);
already_AddRefed<gfxPattern> PopGroup();
void PopGroupToSource();

Просмотреть файл

@ -134,7 +134,6 @@ public:
gfxFloat strikeoutOffset;
gfxFloat underlineSize;
gfxFloat underlineOffset;
gfxFloat height;
gfxFloat internalLeading;
gfxFloat externalLeading;

Просмотреть файл

@ -89,7 +89,7 @@ protected:
class THEBES_API gfxPangoTextRun : public gfxTextRun {
public:
gfxPangoTextRun(const nsAString& aString, gfxPangoFontGroup *aFontGroup);
gfxPangoTextRun(const nsAString *aString, gfxPangoFontGroup *aFontGroup);
~gfxPangoTextRun();
virtual void Draw(gfxContext *aContext, gfxPoint pt);
@ -100,6 +100,7 @@ public:
private:
nsString mString;
gfxPangoFontGroup *mGroup;
PangoLayout *mPangoLayout;

Просмотреть файл

@ -53,6 +53,14 @@ class THEBES_API gfxPattern {
THEBES_INLINE_DECL_REFCOUNTING(gfxPattern)
public:
gfxPattern(cairo_pattern_t *aPattern) {
mPattern = cairo_pattern_reference(aPattern);
}
gfxPattern(gfxRGBA aColor) {
mPattern = cairo_pattern_create_rgba(aColor.r, aColor.g, aColor.b, aColor.a);
}
// from another surface
gfxPattern(gfxASurface* surface) {
mPattern = cairo_pattern_create_for_surface(surface->CairoSurface());
@ -110,8 +118,17 @@ public:
return (int)cairo_pattern_get_filter(mPattern);
}
/* returns TRUE if it succeeded */
PRBool GetSolidColor(gfxRGBA& aColor) {
return cairo_pattern_get_solid_color(mPattern,
&aColor.r,
&aColor.g,
&aColor.b,
&aColor.a) == CAIRO_STATUS_SUCCESS;
}
protected:
gfxPattern(cairo_pattern_t *pattern) : mPattern(pattern) {}
cairo_pattern_t *mPattern;
};

Просмотреть файл

@ -40,6 +40,7 @@
#include "prtypes.h"
#include "gfxTypes.h"
#include "gfxColor.h"
#include "gfxFont.h"
#include "gfxMatrix.h"
@ -476,6 +477,7 @@ public:
private:
double MeasureOrDrawFast(gfxContext *aContext, PRBool aDraw, gfxPoint pt);
double MeasureOrDrawReallyFast(gfxContext *aContext, PRBool aDraw, gfxPoint pt, gfxRGBA color);
double MeasureOrDrawUniscribe(gfxContext *aContext, PRBool aDraw, gfxPoint pt);
gfxWindowsFontGroup *mGroup;
@ -488,6 +490,9 @@ private:
const PRBool mIsASCII;
nsRefPtr<gfxWindowsFont> mFallbackFont;
/* cached values */
double mLength;
};
#endif /* GFX_WINDOWSFONTS_H */

Просмотреть файл

@ -566,10 +566,14 @@ gfxContext::SetColor(const gfxRGBA& c)
cairo_set_source_rgba(mCairo, c.r, c.g, c.b, c.a);
}
void
gfxContext::SetPattern(gfxPattern *pattern)
PRBool
gfxContext::GetColor(gfxRGBA& c)
{
cairo_set_source(mCairo, pattern->CairoPattern());
return cairo_pattern_get_solid_color(cairo_get_source(mCairo),
&c.r,
&c.g,
&c.b,
&c.a) == CAIRO_STATUS_SUCCESS;
}
void
@ -578,6 +582,29 @@ gfxContext::SetSource(gfxASurface *surface, gfxPoint offset)
cairo_set_source_surface(mCairo, surface->CairoSurface(), offset.x, offset.y);
}
void
gfxContext::SetPattern(gfxPattern *pattern)
{
cairo_set_source(mCairo, pattern->CairoPattern());
}
already_AddRefed<gfxPattern>
gfxContext::GetPattern()
{
cairo_pattern_t *pat = cairo_get_source(mCairo);
NS_ASSERTION(pat, "I was told this couldn't be null");
gfxPattern *wrapper = nsnull;
if (pat)
wrapper = new gfxPattern(pat);
else
wrapper = new gfxPattern(gfxRGBA(0,0,0,0));
NS_ADDREF(wrapper);
return wrapper;
}
// masking
void
@ -609,7 +636,7 @@ gfxContext::Paint(gfxFloat alpha)
// groups
void
gfxContext::PushGroup(SurfaceContent content)
gfxContext::PushGroup(gfxASurface::gfxContentType content)
{
cairo_push_group_with_content(mCairo, (cairo_content_t) content);
}

Просмотреть файл

@ -168,7 +168,13 @@ gfxPangoFontGroup::~gfxPangoFontGroup()
gfxTextRun*
gfxPangoFontGroup::MakeTextRun(const nsAString& aString)
{
return new gfxPangoTextRun(aString, this);
return new gfxPangoTextRun(&aString, this);
}
gfxTextRun*
gfxPangoFontGroup::MakeTextRun(const nsACString& aString)
{
return new gfxPangoTextRun(&aString, this);
}
/**
@ -420,7 +426,6 @@ gfxPangoFont::GetMetrics()
mMetrics.maxDescent = xftFont->descent;
double lineHeight = mMetrics.maxAscent + mMetrics.maxDescent;
mMetrics.height = lineHeight;
if (lineHeight > mMetrics.emHeight)
mMetrics.internalLeading = lineHeight - mMetrics.emHeight;
@ -496,7 +501,6 @@ gfxPangoFont::GetMetrics()
mMetrics.maxDescent = pango_font_metrics_get_descent(pfm) / FLOAT_PANGO_SCALE;
gfxFloat lineHeight = mMetrics.maxAscent + mMetrics.maxDescent;
mMetrics.height = lineHeight; // XXX should go away
if (lineHeight > mMetrics.emHeight)
mMetrics.externalLeading = lineHeight - mMetrics.emHeight;
@ -538,7 +542,7 @@ gfxPangoFont::GetMetrics()
fprintf (stderr, "Font: %s\n", NS_ConvertUTF16toUTF8(mName).get());
fprintf (stderr, " emHeight: %f emAscent: %f emDescent: %f\n", mMetrics.emHeight, mMetrics.emAscent, mMetrics.emDescent);
fprintf (stderr, " maxAscent: %f maxDescent: %f\n", mMetrics.maxAscent, mMetrics.maxDescent);
fprintf (stderr, " height: %f internalLeading: %f externalLeading: %f\n", mMetrics.height, mMetrics.externalLeading, mMetrics.internalLeading);
fprintf (stderr, " internalLeading: %f externalLeading: %f\n", mMetrics.externalLeading, mMetrics.internalLeading);
fprintf (stderr, " spaceWidth: %f aveCharWidth: %f xHeight: %f\n", mMetrics.spaceWidth, mMetrics.aveCharWidth, mMetrics.xHeight);
fprintf (stderr, " uOff: %f uSize: %f stOff: %f stSize: %f suOff: %f suSize: %f\n", mMetrics.underlineOffset, mMetrics.underlineSize, mMetrics.strikeoutOffset, mMetrics.strikeoutSize, mMetrics.superscriptOffset, mMetrics.subscriptOffset);
#endif
@ -607,7 +611,7 @@ DrawCairoGlyphs(gfxContext* ctx,
}
#endif
gfxPangoTextRun::gfxPangoTextRun(const nsAString& aString, gfxPangoFontGroup *aGroup)
gfxPangoTextRun::gfxPangoTextRun(const nsAString *aString, gfxPangoFontGroup *aGroup)
: mString(aString), mGroup(aGroup), mPangoLayout(nsnull), mWidth(-1), mHeight(-1)
{
}

Просмотреть файл

@ -442,12 +442,12 @@ gfxWindowsFontGroup::MakeTextRun(const nsACString& aString)
**********************************************************************/
gfxWindowsTextRun::gfxWindowsTextRun(const nsAString *aString, gfxWindowsFontGroup *aFontGroup)
: mGroup(aFontGroup), mString(aString), mCString(nsnull), mIsASCII(PR_FALSE)
: mGroup(aFontGroup), mString(aString), mCString(nsnull), mIsASCII(PR_FALSE), mLength(-1.0)
{
}
gfxWindowsTextRun::gfxWindowsTextRun(const nsACString *aString, gfxWindowsFontGroup *aFontGroup)
: mGroup(aFontGroup), mString(nsnull), mCString(aString), mIsASCII(PR_TRUE)
: mGroup(aFontGroup), mString(nsnull), mCString(aString), mIsASCII(PR_TRUE), mLength(-1.0)
{
}
@ -469,12 +469,19 @@ gfxWindowsTextRun::Draw(gfxContext *aContext, gfxPoint pt)
gfxFloat
gfxWindowsTextRun::Measure(gfxContext *aContext)
{
double ret = MeasureOrDrawFast(aContext, PR_FALSE, gfxPoint(0,0));
if (ret >= 0.0) {
return ROUND(ret);
static const gfxPoint kZeroZero(0, 0);
if (mLength < 0.0) {
mLength = MeasureOrDrawFast(aContext, PR_FALSE, kZeroZero);
if (mLength >= 0.0) {
return mLength;
}
mLength = MeasureOrDrawUniscribe(aContext, PR_FALSE, kZeroZero);
}
ret = MeasureOrDrawUniscribe(aContext, PR_FALSE, gfxPoint(0,0));
return ROUND(ret);
return mLength;
}
void
@ -490,9 +497,10 @@ gfxWindowsTextRun::GetSpacing() const
}
double
gfxWindowsTextRun::MeasureOrDrawFast(gfxContext *aContext,
PRBool aDraw,
gfxPoint pt)
gfxWindowsTextRun::MeasureOrDrawReallyFast(gfxContext *aContext,
PRBool aDraw,
gfxPoint pt,
gfxRGBA color)
{
double length = 0;
@ -519,13 +527,123 @@ gfxWindowsTextRun::MeasureOrDrawFast(gfxContext *aContext,
HDC aDC = GetDCFromSurface(surf);
NS_ASSERTION(aDC, "No DC");
PRBool needsSave = aContext->CurrentMatrix().HasNonTranslation();
nsRefPtr<gfxWindowsFont> currentFont = mGroup->GetFontAt(0);
HFONT hfont = currentFont->GetHFONT();
SelectObject(aDC, hfont);
/* check to see if all the glyphs are in this font or not */
WORD glyphBuf[512];
LPWORD glyphs = glyphBuf;
if (aLength > sizeof(glyphBuf) / sizeof(WORD))
glyphs = (LPWORD)malloc(aLength * sizeof(WORD));
DWORD ret;
if (mIsASCII)
ret = GetGlyphIndicesA(aDC, aCString, aLength, glyphs, GGI_MARK_NONEXISTING_GLYPHS);
else
ret = GetGlyphIndicesW(aDC, aWString, aLength, glyphs, GGI_MARK_NONEXISTING_GLYPHS);
if (ret == GDI_ERROR) {
NS_WARNING("GetGlyphIndicies failed\n");
if (glyphs != glyphBuf)
free(glyphs);
return 0; // return 0 length
}
for (DWORD i = 0; i < ret; ++i) {
if (glyphs[i] == 0xffff) {
if (glyphs != glyphBuf)
free(glyphs);
return -1; // try uniscribe instead
}
}
if (glyphs != glyphBuf)
free(glyphs);
if (!aDraw) {
/* measure */
SIZE len;
if (mIsASCII)
GetTextExtentPoint32A(aDC, aCString, aLength, &len);
else
GetTextExtentPoint32W(aDC, aWString, aLength, &len);
length = len.cx;
} else {
/* draw */
SetTextAlign(aDC, TA_BASELINE | TA_LEFT);
SetBkMode(aDC, TRANSPARENT);
SetTextColor(aDC, RGB(color.r * 255.0, color.g * 255.0, color.b * 255.0));
aContext->UpdateSurfaceClip();
gfxPoint offset;
nsRefPtr<gfxASurface> surf = aContext->CurrentSurface(&offset.x, &offset.y);
gfxPoint p = aContext->CurrentMatrix().Transform(pt) + offset;
/* add support for spacing */
if (mIsASCII)
ExtTextOutA(aDC, (int)p.x, (int)p.y, 0, nsnull, aCString, aLength, nsnull);
else
ExtTextOutW(aDC, (int)p.x, (int)p.y, 0, nsnull, aWString, aLength, nsnull);
}
if (aDraw)
surf->MarkDirty();
return length;
}
double
gfxWindowsTextRun::MeasureOrDrawFast(gfxContext *aContext,
PRBool aDraw,
gfxPoint pt)
{
double length = 0;
if (!aContext->CurrentMatrix().HasNonTranslation()) {
/* need to not call this if the color isn't solid
or the pattern isn't a color
or the destination has alpha
*/
if (mSpacing.IsEmpty()) { // XXX remove this once we make MeasureOrDrawReallyFast handle spacing
gfxRGBA color;
if (mContext->GetColor(color) && color.a == 1.0) {
// we can measure with 32bpp surfaces, but we can't draw to them using this API
nsRefPtr<gfxASurface> currentSurface = aContext->CurrentSurface();
if (!aDraw || currentSurface->GetContentType() == gfxASurface::CONTENT_COLOR)
return MeasureOrDrawReallyFast(aContext, aDraw, pt, color);
}
}
}
/* this function doesn't handle RTL text. */
if (IsRightToLeft()) {
return -1;
}
const char *aCString;
const PRUnichar *aWString;
PRUint32 aLength;
if (mIsASCII) {
aCString = mCString->BeginReading();
aLength = mCString->Length();
} else {
aWString = mString->BeginReading();
aLength = mString->Length();
if (ScriptIsComplex(aWString, aLength, SIC_COMPLEX) == S_OK)
return -1; // try uniscribe instead
}
nsRefPtr<gfxASurface> surf = aContext->CurrentSurface();
HDC aDC = GetDCFromSurface(surf);
NS_ASSERTION(aDC, "No DC");
XFORM savedxform;
if (needsSave) {
// cairo munges it underneath us
GetWorldTransform(aDC, &savedxform);
}
// cairo munges it underneath us
GetWorldTransform(aDC, &savedxform);
cairo_t *cr = aContext->GetCairo();
@ -537,8 +655,7 @@ gfxWindowsTextRun::MeasureOrDrawFast(gfxContext *aContext,
cairo_set_font_face(cr, fontFace);
cairo_set_font_size(cr, mGroup->mStyle.size);
if (needsSave)
SaveDC(aDC);
SaveDC(aDC);
cairo_win32_scaled_font_select_font(scaledFont, aDC);
@ -627,8 +744,7 @@ gfxWindowsTextRun::MeasureOrDrawFast(gfxContext *aContext,
}
}
if (needsSave)
SetWorldTransform(aDC, &savedxform);
SetWorldTransform(aDC, &savedxform);
cairo_show_glyphs(cr, cglyphs, numGlyphs);
@ -642,8 +758,7 @@ gfxWindowsTextRun::MeasureOrDrawFast(gfxContext *aContext,
cairo_win32_scaled_font_done_font(scaledFont);
if (needsSave)
RestoreDC(aDC, -1);
RestoreDC(aDC, -1);
if (aDraw)
surf->MarkDirty();
@ -774,8 +889,8 @@ public:
mContext(aContext), mDC(aDC),
mString(aString), mLength(aLength), mScriptItem(aItem), mGroup(aGroup),
mGlyphs(nsnull), mClusters(nsnull), mAttr(nsnull),
mNumGlyphs(0), mMaxGlyphs((1.5 * aLength) + 16),
mOffsets(nsnull), mAdvances(nsnull),
mNumGlyphs(0), mMaxGlyphs((int)(1.5 * aLength) + 16),
mOffsets(nsnull), mAdvances(nsnull), mSpacing(nsnull),
mFontIndex(0), mTriedPrefFonts(0), mTriedOtherFonts(0), mFontSelected(PR_FALSE)
{
mGlyphs = (WORD *)malloc(mMaxGlyphs * sizeof(WORD));
@ -827,6 +942,28 @@ public:
return PR_TRUE;
}
#ifdef DEBUG_pavlov
HRESULT Break() {
HRESULT rv;
SCRIPT_LOGATTR *logAttrs = (SCRIPT_LOGATTR*)malloc(sizeof(SCRIPT_LOGATTR) * mLength);
rv = ScriptBreak(mString, mLength, &mScriptItem->a, logAttrs);
for (PRUint32 i = 0; i < mLength; ++i) {
PR_LOG(gFontLog, PR_LOG_DEBUG, ("0x%04x - %d %d %d %d %d",
mString[i],
logAttrs[i].fSoftBreak,
logAttrs[i].fWhiteSpace,
logAttrs[i].fCharStop,
logAttrs[i].fWordStop,
logAttrs[i].fInvalid));
}
free(logAttrs);
return rv;
}
#endif
/* possible return values:
E_PENDING -- means script cache lookup failed, DC needs to be set and font selected in to it.
@ -1174,7 +1311,7 @@ public:
}
UniscribeItem *GetItem(PRUint32 i, gfxWindowsFontGroup *aGroup) {
NS_ASSERTION(i < mNumItems, "Trying to get out of bounds item");
NS_ASSERTION(i < (PRUint32)mNumItems, "Trying to get out of bounds item");
UniscribeItem *item = new UniscribeItem(mContext, mDC,
mString + mItems[i].iCharPos,
@ -1294,6 +1431,10 @@ gfxWindowsTextRun::MeasureOrDrawUniscribe(gfxContext *aContext,
SCRIPT_PLACE:
NS_ASSERTION(SUCCEEDED(rv), "Failed to shape -- we should never hit this");
#ifdef DEBUG_pavlov
item->Break();
#endif
rv = item->Place();
if (FAILED(rv)) {
if (PR_LOG_TEST(gFontLog, PR_LOG_WARNING))

Просмотреть файл

@ -789,9 +789,9 @@ void nsDisplayOpacity::Paint(nsDisplayListBuilder* aBuilder,
ctx->Clip();
if (mNeedAlpha)
ctx->PushGroup(gfxContext::CONTENT_COLOR_ALPHA);
ctx->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
else
ctx->PushGroup(gfxContext::CONTENT_COLOR);
ctx->PushGroup(gfxASurface::CONTENT_COLOR);
nsDisplayWrapList::Paint(aBuilder, aCtx, bounds);

Просмотреть файл

@ -842,29 +842,35 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
nsRefPtr<gfxContext> ctx = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
gfxFloat xoff, yoff;
nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&xoff, &yoff);
gfxPoint offset;
nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&offset.x, &offset.y);
HDC hdc = NS_STATIC_CAST(gfxWindowsSurface*, NS_STATIC_CAST(gfxASurface*, surf.get()))->GetDC();
SaveDC(hdc);
SetGraphicsMode(hdc, GM_ADVANCED);
/* Need to force the clip to be set */
ctx->UpdateSurfaceClip();
/* Covert the current transform to a world transform */
XFORM oldWorldTransform;
gfxMatrix m = ctx->CurrentMatrix();
XFORM xform;
double dm[6];
m.ToValues(&dm[0], &dm[1], &dm[2], &dm[3], &dm[4], &dm[5]);
if (m.HasNonTranslation()) {
GetWorldTransform(hdc, &oldWorldTransform);
xform.eM11 = (FLOAT) dm[0];
xform.eM12 = (FLOAT) dm[1];
xform.eM21 = (FLOAT) dm[2];
xform.eM22 = (FLOAT) dm[3];
xform.eDx = (FLOAT) dm[4];
xform.eDy = (FLOAT) dm[5];
SetWorldTransform (hdc, &xform);
SetGraphicsMode(hdc, GM_ADVANCED);
XFORM xform;
double dm[6];
m.ToValues(&dm[0], &dm[1], &dm[2], &dm[3], &dm[4], &dm[5]);
xform.eM11 = (FLOAT) dm[0];
xform.eM12 = (FLOAT) dm[1];
xform.eM21 = (FLOAT) dm[2];
xform.eM22 = (FLOAT) dm[3];
xform.eDx = (FLOAT) dm[4];
xform.eDy = (FLOAT) dm[5];
SetWorldTransform (hdc, &xform);
} else {
offset = m.Transform(offset);
}
#if 0
fprintf (stderr, "xform: %f %f %f %f [%f %f]\n", dm[0], dm[1], dm[2], dm[3], dm[4], dm[5]);
@ -877,7 +883,7 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
/* Set the device offsets as appropriate */
POINT origViewportOrigin, origBrushOrigin;
GetViewportOrgEx(hdc, &origViewportOrigin);
SetViewportOrgEx(hdc, origViewportOrigin.x + (int) xoff, origViewportOrigin.y + (int) yoff, NULL);
SetViewportOrgEx(hdc, origViewportOrigin.x + (int)offset.x, origViewportOrigin.y + (int)offset.y, NULL);
#else /* non-MOZ_CAIRO_GFX */
@ -891,8 +897,6 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
if (!hdc)
return NS_ERROR_FAILURE;
SaveDC(hdc);
#ifndef WINCE
SetGraphicsMode(hdc, GM_ADVANCED);
#endif
@ -998,9 +1002,12 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
}
}
RestoreDC(hdc, -1);
#ifdef MOZ_CAIRO_GFX
SetViewportOrgEx(hdc, origViewportOrigin.x, origViewportOrigin.y, NULL);
if (m.HasNonTranslation())
SetWorldTransform(hdc, &oldWorldTransform);
surf->MarkDirty();
#endif
@ -2009,32 +2016,38 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
nsRefPtr<gfxContext> ctx = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
gfxFloat xoff, yoff;
nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&xoff, &yoff);
gfxPoint offset;
nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&offset.x, &offset.y);
HDC hdc = NS_STATIC_CAST(gfxWindowsSurface*, NS_STATIC_CAST(gfxASurface*, surf.get()))->GetDC();
SaveDC(hdc);
SetGraphicsMode(hdc, GM_ADVANCED);
/* Need to force the clip to be set */
ctx->UpdateSurfaceClip();
/* Covert the current transform to a world transform */
XFORM oldWorldTransform;
gfxMatrix m = ctx->CurrentMatrix();
XFORM xform;
double dm[6];
m.ToValues(&dm[0], &dm[1], &dm[2], &dm[3], &dm[4], &dm[5]);
xform.eM11 = (FLOAT) dm[0];
xform.eM12 = (FLOAT) dm[1];
xform.eM21 = (FLOAT) dm[2];
xform.eM22 = (FLOAT) dm[3];
xform.eDx = (FLOAT) dm[4];
xform.eDy = (FLOAT) dm[5];
SetWorldTransform (hdc, &xform);
if (m.HasNonTranslation()) {
GetWorldTransform(hdc, &oldWorldTransform);
SetGraphicsMode(hdc, GM_ADVANCED);
XFORM xform;
double dm[6];
m.ToValues(&dm[0], &dm[1], &dm[2], &dm[3], &dm[4], &dm[5]);
xform.eM11 = (FLOAT) dm[0];
xform.eM12 = (FLOAT) dm[1];
xform.eM21 = (FLOAT) dm[2];
xform.eM22 = (FLOAT) dm[3];
xform.eDx = (FLOAT) dm[4];
xform.eDy = (FLOAT) dm[5];
SetWorldTransform (hdc, &xform);
} else {
offset = m.Transform(offset);
}
/* Set the device offsets as appropriate */
POINT origViewportOrigin;
GetViewportOrgEx(hdc, &origViewportOrigin);
SetViewportOrgEx(hdc, origViewportOrigin.x + (int) xoff, origViewportOrigin.y + (int) yoff, NULL);
SetViewportOrgEx(hdc, origViewportOrigin.x + (int)offset.x, origViewportOrigin.y + (int)offset.y, NULL);
#else /* non-MOZ_CAIRO_GFX */
@ -2044,8 +2057,6 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
HDC hdc = (HDC)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
SaveDC(hdc);
#endif /* MOZ_CAIRO_GFX */
GetNativeRect(tr, widgetRect);
@ -2317,9 +2328,13 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
rv = NS_ERROR_FAILURE;
break;
}
RestoreDC(hdc, -1);
#ifdef MOZ_CAIRO_GFX
SetViewportOrgEx(hdc, origViewportOrigin.x, origViewportOrigin.y, NULL);
if (m.HasNonTranslation())
SetWorldTransform(hdc, &oldWorldTransform);
surf->MarkDirty();
#endif

Просмотреть файл

@ -5701,7 +5701,7 @@ PRBool nsWindow::OnPaint(HDC aDC)
thebesContext->SetOperator(gfxContext::OPERATOR_OVER);
} else {
// If we're not doing translucency, then double buffer
thebesContext->PushGroup(gfxContext::CONTENT_COLOR);
thebesContext->PushGroup(gfxASurface::CONTENT_COLOR);
}
#endif