bug 721511 - use stack-based buffers for moderate-sized glyph runs in cairo/dwrite backend. r=bas

This commit is contained in:
Jonathan Kew 2012-01-28 08:28:56 +00:00
parent ad4fa54177
commit 7f9bb5f2a6
3 changed files with 59 additions and 44 deletions

View File

@ -3674,7 +3674,7 @@ _cairo_dwrite_manual_show_glyphs_on_d2d_surface(void *surface,
_cairo_d2d_set_clip(dst, NULL);
dst->rt->Flush();
DWRITE_GLYPH_RUN run;
AutoDWriteGlyphRun run;
_cairo_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, scaled_font, &run, &transform);
RefPtr<IDWriteGlyphRunAnalysis> analysis;
@ -3731,9 +3731,6 @@ _cairo_dwrite_manual_show_glyphs_on_d2d_surface(void *surface,
0,
0,
&analysis);
delete [] run.glyphIndices;
delete [] run.glyphAdvances;
delete [] run.glyphOffsets;
if (FAILED(hr)) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -4105,8 +4102,7 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
cairo_bool_t transform = FALSE;
DWRITE_GLYPH_RUN run;
AutoDWriteGlyphRun run;
_cairo_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, dwritesf, &run, &transform);
D2D1::Matrix3x2F mat = _cairo_d2d_matrix_from_matrix(&dwritesf->mat);
@ -4141,9 +4137,6 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
source);
if (!brush) {
delete [] run.glyphIndices;
delete [] run.glyphOffsets;
delete [] run.glyphAdvances;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -4165,10 +4158,6 @@ _cairo_dwrite_show_glyphs_on_d2d_surface(void *surface,
target_rt->SetTransform(D2D1::Matrix3x2F::Identity());
}
delete [] run.glyphIndices;
delete [] run.glyphOffsets;
delete [] run.glyphAdvances;
if (target_rt.get() != dst->rt.get()) {
return _cairo_d2d_blend_temp_surface(dst, op, target_rt, clip, &fontArea);
}

View File

@ -336,12 +336,14 @@ void
_cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
int num_glyphs,
cairo_dwrite_scaled_font_t *scaled_font,
DWRITE_GLYPH_RUN *run,
AutoDWriteGlyphRun *run,
cairo_bool_t *transformed)
{
UINT16 *indices = new UINT16[num_glyphs];
FLOAT *advances = new FLOAT[num_glyphs];
DWRITE_GLYPH_OFFSET *offsets = new DWRITE_GLYPH_OFFSET[num_glyphs];
run->allocate(num_glyphs);
UINT16 *indices = const_cast<UINT16*>(run->glyphIndices);
FLOAT *advances = const_cast<FLOAT*>(run->glyphAdvances);
DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run->glyphOffsets);
cairo_dwrite_font_face_t *dwriteff = reinterpret_cast<cairo_dwrite_font_face_t*>(scaled_font->base.font_face);
@ -349,9 +351,6 @@ _cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
run->fontFace = dwriteff->dwriteface;
run->glyphCount = num_glyphs;
run->isSideways = FALSE;
run->glyphIndices = indices;
run->glyphOffsets = offsets;
run->glyphAdvances = advances;
if (scaled_font->mat.xy == 0 && scaled_font->mat.yx == 0 &&
scaled_font->mat.xx == scaled_font->base.font_matrix.xx &&
@ -598,19 +597,17 @@ _cairo_dwrite_scaled_show_glyphs(void *scaled_font,
} else {
cairo_dwrite_scaled_font_t *dwritesf =
static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
UINT16 *indices = new UINT16[num_glyphs];
DWRITE_GLYPH_OFFSET *offsets = new DWRITE_GLYPH_OFFSET[num_glyphs];
FLOAT *advances = new FLOAT[num_glyphs];
BOOL transform = FALSE;
DWRITE_GLYPH_RUN run;
AutoDWriteGlyphRun run;
run.allocate(num_glyphs);
UINT16 *indices = const_cast<UINT16*>(run.glyphIndices);
FLOAT *advances = const_cast<FLOAT*>(run.glyphAdvances);
DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets);
run.bidiLevel = 0;
run.fontFace = ((cairo_dwrite_font_face_t*)dwritesf->base.font_face)->dwriteface;
run.glyphIndices = indices;
run.glyphCount = num_glyphs;
run.isSideways = FALSE;
run.glyphOffsets = offsets;
run.glyphAdvances = advances;
IDWriteGlyphRunAnalysis *analysis;
if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 &&
@ -1285,9 +1282,13 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
* coordinate due to accumulated rounding error. As a result strings could
* be painted shorter or longer than expected. */
UINT16 *indices = new UINT16[num_glyphs];
DWRITE_GLYPH_OFFSET *offsets = new DWRITE_GLYPH_OFFSET[num_glyphs];
FLOAT *advances = new FLOAT[num_glyphs];
AutoDWriteGlyphRun run;
run.allocate(num_glyphs);
UINT16 *indices = const_cast<UINT16*>(run.glyphIndices);
FLOAT *advances = const_cast<FLOAT*>(run.glyphAdvances);
DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets);
BOOL transform = FALSE;
/* Needed to calculate bounding box for efficient blitting */
INT32 smallestX = INT_MAX;
@ -1343,14 +1344,9 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
fontArea.bottom = dst->extents.height;
}
DWRITE_GLYPH_RUN run;
run.bidiLevel = 0;
run.fontFace = dwriteff->dwriteface;
run.glyphIndices = indices;
run.glyphCount = num_glyphs;
run.isSideways = FALSE;
run.glyphOffsets = offsets;
run.glyphAdvances = advances;
if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 &&
dwritesf->mat.xx == scaled_font->font_matrix.xx &&
dwritesf->mat.yy == scaled_font->font_matrix.yy) {
@ -1424,10 +1420,6 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
}
#endif
delete [] indices;
delete [] offsets;
delete [] advances;
return CAIRO_INT_STATUS_SUCCESS;
}

View File

@ -169,6 +169,42 @@ private:
static int mRenderingMode;
};
class AutoDWriteGlyphRun : public DWRITE_GLYPH_RUN
{
static const int kNumAutoGlyphs = 256;
public:
AutoDWriteGlyphRun() {
glyphCount = 0;
}
~AutoDWriteGlyphRun() {
if (glyphCount > kNumAutoGlyphs) {
delete[] glyphIndices;
delete[] glyphAdvances;
delete[] glyphOffsets;
}
}
void allocate(int aNumGlyphs) {
glyphCount = aNumGlyphs;
if (aNumGlyphs <= kNumAutoGlyphs) {
glyphIndices = &mAutoIndices[0];
glyphAdvances = &mAutoAdvances[0];
glyphOffsets = &mAutoOffsets[0];
} else {
glyphIndices = new UINT16[aNumGlyphs];
glyphAdvances = new FLOAT[aNumGlyphs];
glyphOffsets = new DWRITE_GLYPH_OFFSET[aNumGlyphs];
}
}
private:
DWRITE_GLYPH_OFFSET mAutoOffsets[kNumAutoGlyphs];
FLOAT mAutoAdvances[kNumAutoGlyphs];
UINT16 mAutoIndices[kNumAutoGlyphs];
};
/* cairo_font_face_t implementation */
struct _cairo_dwrite_font_face {
cairo_font_face_t base;
@ -179,12 +215,10 @@ typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t;
DWRITE_MATRIX _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix);
// This will create a DWrite glyph run from cairo glyphs and a scaled_font.
// It is important to note the array members of DWRITE_GLYPH_RUN should be
// deleted by the caller.
// This will initialize a DWrite glyph run from cairo glyphs and a scaled_font.
void
_cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
int num_glyphs,
cairo_dwrite_scaled_font_t *scaled_font,
DWRITE_GLYPH_RUN *run,
AutoDWriteGlyphRun *run,
cairo_bool_t *transformed);