[cairo-commit] src/cairo-pdf-surface.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Sun Sep 9 00:42:32 PDT 2007


 src/cairo-pdf-surface.c |  129 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 125 insertions(+), 4 deletions(-)

New commits:
diff-tree 909e0be2416aa6833639439279583d1ae61777fc (from d62f8861689d8b9a9a837043fb78813f0407abd4)
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Sep 9 11:20:02 2007 +0930

    Add PDF support for cairo_mask()

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 1bca1f3..4d68282 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3761,13 +3761,134 @@ _cairo_pdf_surface_mask	(void			*abstrac
 			 cairo_pattern_t	*mask)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
+    cairo_pdf_resource_t mask_group;
+    cairo_pdf_resource_t group = {0}; /* squelch bogus compiler warning */
+    cairo_pdf_resource_t source_group;
+    cairo_pdf_resource_t smask;
+    cairo_pdf_resource_t gstate;
+    cairo_status_t status, status2;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
+	status = _cairo_pdf_surface_analyze_operation (surface, op, source);
+	if (status != CAIRO_STATUS_SUCCESS &&
+	    status != CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+	    return status;
 
-    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	status2 = _cairo_pdf_surface_analyze_operation (surface, op, mask);
+	if (status2 != CAIRO_STATUS_SUCCESS)
+	    return status2;
+
+	return status;
+    }
+
+    assert (_cairo_pdf_surface_operation_supported (surface, op, source));
+    assert (_cairo_pdf_surface_operation_supported (surface, op, mask));
+
+    status = _cairo_pdf_surface_set_operator (surface, op);
+    if (status)
+	return status;
+
+    /* Create mask group */
+    status = _cairo_pdf_surface_emit_pattern (surface, mask);
+    if (status)
+	return status;
+
+    _cairo_pdf_surface_pause_content_stream (surface);
+
+    _cairo_pdf_surface_open_group (surface);
+    _cairo_pdf_surface_select_pattern (surface, FALSE);
+    _cairo_output_stream_printf (surface->output,
+				 "0 0 %f %f re f\r\n",
+				 surface->width, surface->height);
+    _cairo_pdf_surface_close_group (surface, &mask_group);
+
+    if (surface->emitted_pattern.smask.id != 0) {
+	group = mask_group;
+	_cairo_pdf_surface_open_group (surface);
+	_cairo_output_stream_printf (surface->output,
+				     "/s%d gs /x%d Do\r\n",
+				     surface->emitted_pattern.smask,
+				     group.id);
+	status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+	if (status)
+	    return status;
+	status = _cairo_pdf_surface_add_xobject (surface, group);
+	if (status)
+	    return status;
+	_cairo_pdf_surface_close_group (surface, &mask_group);
+    }
 
-    ASSERT_NOT_REACHED;
+    /* Create source group */
+    status = _cairo_pdf_surface_emit_pattern (surface, source);
+    if (status)
+	return status;
+
+    _cairo_pdf_surface_pause_content_stream (surface);
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    _cairo_pdf_surface_open_group (surface);
+    _cairo_pdf_surface_select_pattern (surface, FALSE);
+    _cairo_output_stream_printf (surface->output,
+				 "0 0 %f %f re f\r\n",
+				 surface->width, surface->height);
+    _cairo_pdf_surface_close_group (surface, &source_group);
+
+    if (surface->emitted_pattern.smask.id != 0) {
+	group = source_group;
+	_cairo_pdf_surface_open_group (surface);
+	_cairo_output_stream_printf (surface->output,
+				     "/s%d gs /x%d Do\r\n",
+				     surface->emitted_pattern.smask,
+				     group.id);
+	status = _cairo_pdf_surface_add_smask (surface, surface->emitted_pattern.smask);
+	if (status)
+	    return status;
+	status = _cairo_pdf_surface_add_xobject (surface, group);
+	if (status)
+	    return status;
+	_cairo_pdf_surface_close_group (surface, &source_group);
+    }
+
+    /* Create an smask based on the alpha component of mask_group */
+    smask = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /Mask\r\n"
+				 "   /S /Alpha\r\n"
+				 "   /G %d 0 R\r\n"
+				 "   /BC [ 0.0 ]\r\n"
+				 ">>\r\n"
+				 "endobj\r\n",
+				 smask.id,
+				 mask_group.id);
+
+    /* Create a GState that uses the smask */
+    gstate = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /ExtGState\r\n"
+				 "   /SMask %d 0 R\r\n"
+				 "   /ca 1\r\n"
+				 "   /CA 1\r\n"
+				 "   /AIS false\r\n"
+				 ">>\r\n"
+				 "endobj\r\n",
+				 gstate.id,
+				 smask.id);
+
+    /* Select the GState then draw the source */
+    _cairo_pdf_surface_resume_content_stream (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "q /s%d gs /x%d Do Q\r\n",
+				 gstate.id,
+				 source_group.id);
+    status = _cairo_pdf_surface_add_smask (surface, gstate);
+    if (status)
+	return status;
+    status = _cairo_pdf_surface_add_xobject (surface, source_group);
+    if (status)
+	return status;
+
+    return _cairo_output_stream_get_status (surface->output);
 }
 
 static int


More information about the cairo-commit mailing list