Bug 549652: Properly support clearing surfaces. r=jrmuizel

This commit is contained in:
Bas Schouten 2010-03-04 20:30:05 +01:00
Родитель 40dfe937a9
Коммит 00ecc30146
2 изменённых файлов: 78 добавлений и 25 удалений

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

@ -76,8 +76,11 @@ struct _cairo_d2d_surface {
ID2D1Layer *clipLayer;
/** Mask layer used by surface_mask to push opacity masks */
ID2D1Layer *maskLayer;
/** Layer used for clipping when tiling - lazily initialized */
ID2D1Layer *tilingLayer;
/**
* Layer used for clipping when tiling, and also for clearing out geometries
* - lazily initialized
*/
ID2D1Layer *helperLayer;
/** If this layer currently is clipping, used to prevent excessive push/pops */
bool clipping;
/** Brush used for bitmaps */

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

@ -846,15 +846,15 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
D2DSurfFactory::Instance()->CreateRectangleGeometry(D2D1::RectF(0, 0, (float)width, (float)height),
&clipRect);
if (!d2dsurf->tilingLayer) {
d2dsurf->rt->CreateLayer(&d2dsurf->tilingLayer);
if (!d2dsurf->helperLayer) {
d2dsurf->rt->CreateLayer(&d2dsurf->helperLayer);
}
d2dsurf->rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(),
clipRect,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
_cairo_d2d_matrix_from_matrix(&mat)),
d2dsurf->tilingLayer);
d2dsurf->helperLayer);
*pushed_clip = true;
clipRect->Release();
}
@ -1137,6 +1137,27 @@ _cairo_d2d_create_path_geometry_for_path(cairo_path_fixed_t *path,
return d2dpath;
}
/**
* We use this to clear out a certain geometry on a surface. This will respect
* the existing clip.
*
* \param d2dsurf Surface we clear
* \param geometry Geometry of the area to clear
*/
static void _cairo_d2d_clear_geometry(cairo_d2d_surface_t *d2dsurf,
ID2D1Geometry *geometry)
{
if (!d2dsurf->helperLayer) {
d2dsurf->rt->CreateLayer(&d2dsurf->helperLayer);
}
d2dsurf->rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(),
geometry),
d2dsurf->helperLayer);
d2dsurf->rt->Clear(D2D1::ColorF(0, 0));
d2dsurf->rt->PopLayer();
}
// Implementation
static cairo_surface_t*
_cairo_d2d_create_similar(void *surface,
@ -1289,8 +1310,8 @@ _cairo_d2d_finish(void *surface)
if (d2dsurf->surface) {
d2dsurf->surface->Release();
}
if (d2dsurf->tilingLayer) {
d2dsurf->tilingLayer->Release();
if (d2dsurf->helperLayer) {
d2dsurf->helperLayer->Release();
}
if (d2dsurf->bufferTexture) {
d2dsurf->bufferTexture->Release();
@ -1610,10 +1631,7 @@ _cairo_d2d_paint(void *surface,
cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
_begin_draw_state(d2dsurf);
if (op == CAIRO_OPERATOR_CLEAR) {
cairo_solid_pattern_t *sourcePattern =
(cairo_solid_pattern_t*)source;
d2dsurf->rt->Clear(
_cairo_d2d_color_from_cairo_color(sourcePattern->color));
d2dsurf->rt->Clear(D2D1::ColorF(0, 0));
return CAIRO_INT_STATUS_SUCCESS;
}
@ -1755,14 +1773,14 @@ _cairo_d2d_stroke(void *surface,
{
cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
_begin_draw_state(d2dsurf);
if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_SOURCE &&
op != CAIRO_OPERATOR_ADD) {
/**
* We don't really support SOURCE and ADD yet. Source won't be
* too hard, true ADD support requires getting the tesselated
* mesh from D2D, and blending that using D3D which has an add
* operator available.
*/
if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_ADD &&
op != CAIRO_OPERATOR_CLEAR) {
/**
* We don't really support ADD yet. True ADD support requires getting
* the tesselated mesh from D2D, and blending that using D3D which has
* an add operator available.
*/
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -1779,6 +1797,29 @@ _cairo_d2d_stroke(void *surface,
D2D1::Matrix3x2F mat = _cairo_d2d_matrix_from_matrix(ctm);
_cairo_path_fixed_transform(path, ctm_inverse);
if (op == CAIRO_OPERATOR_CLEAR) {
ID2D1Geometry *d2dpath = _cairo_d2d_create_path_geometry_for_path(path,
CAIRO_FILL_RULE_WINDING,
D2D1_FIGURE_BEGIN_FILLED);
ID2D1PathGeometry *strokeGeometry;
D2DSurfFactory::Instance()->CreatePathGeometry(&strokeGeometry);
ID2D1GeometrySink *sink;
strokeGeometry->Open(&sink);
d2dpath->Widen((FLOAT)style->line_width, strokeStyle, mat, (FLOAT)tolerance, sink);
sink->Close();
sink->Release();
_cairo_d2d_clear_geometry(d2dsurf, strokeGeometry);
strokeGeometry->Release();
d2dpath->Release();
return CAIRO_INT_STATUS_SUCCESS;
}
d2dsurf->rt->SetTransform(mat);
unsigned int runs_remaining = 1;
@ -1862,13 +1903,12 @@ _cairo_d2d_fill(void *surface,
cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
_begin_draw_state(d2dsurf);
if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_SOURCE &&
op != CAIRO_OPERATOR_ADD) {
if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_ADD &&
op != CAIRO_OPERATOR_CLEAR) {
/**
* We don't really support SOURCE and ADD yet. Source won't be
* too hard, true ADD support requires getting the tesselated
* mesh from D2D, and blending that using D3D which has an add
* operator available.
* We don't really support ADD yet. True ADD support requires getting
* the tesselated mesh from D2D, and blending that using D3D which has
* an add operator available.
*/
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -1883,6 +1923,16 @@ _cairo_d2d_fill(void *surface,
unsigned int last_run = 0;
bool pushed_clip = false;
if (op == CAIRO_OPERATOR_CLEAR) {
ID2D1Geometry *d2dpath = _cairo_d2d_create_path_geometry_for_path(path,
fill_rule,
D2D1_FIGURE_BEGIN_FILLED);
_cairo_d2d_clear_geometry(d2dsurf, d2dpath);
d2dpath->Release();
return CAIRO_INT_STATUS_SUCCESS;
}
cairo_box_t box;
if (_cairo_path_fixed_is_box(path, &box)) {
float x1 = _cairo_fixed_to_float(box.p1.x);