зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
006fe6875e
Коммит
3866d8b63e
|
@ -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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче