PS: Add DocumentMedia/PageMedia DSC comments

Provide default DocumentMedia and PageMedia DSC comments if the user
does not specify them using cairo_ps_surface_dsc_comment(). This is
required so that PostScript viewers such as gv use the correct page
size.
This commit is contained in:
Adrian Johnson 2009-09-25 23:07:56 +09:30
parent caa9eed464
commit db5e3db0a9
2 changed files with 89 additions and 0 deletions

View file

@ -90,6 +90,7 @@ typedef struct cairo_ps_surface {
cairo_scaled_font_subsets_t *font_subsets;
cairo_list_t document_media;
cairo_array_t dsc_header_comments;
cairo_array_t dsc_setup_comments;
cairo_array_t dsc_page_setup_comments;

View file

@ -106,6 +106,13 @@ static const char * _cairo_ps_level_strings[CAIRO_PS_LEVEL_LAST] =
"PS Level 3"
};
typedef struct _cairo_page_media {
char *name;
int width;
int height;
cairo_list_t link;
} cairo_page_media_t;
static void
_cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
{
@ -149,6 +156,27 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"%%%%LanguageLevel: %d\n",
level);
if (!cairo_list_is_empty (&surface->document_media)) {
cairo_page_media_t *page;
cairo_bool_t first = TRUE;
cairo_list_foreach_entry (page, cairo_page_media_t, &surface->document_media, link) {
if (first) {
_cairo_output_stream_printf (surface->final_stream,
"%%%%DocumentMedia: ");
first = FALSE;
} else {
_cairo_output_stream_printf (surface->final_stream,
"%%%%+ ");
}
_cairo_output_stream_printf (surface->final_stream,
"%s %d %d 0 () ()\n",
page->name,
page->width,
page->height);
}
}
num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
comments = _cairo_array_index (&surface->dsc_header_comments, 0);
for (i = 0; i < num_comments; i++) {
@ -775,6 +803,39 @@ _cairo_ps_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
fill_rule);
}
static const char *
_cairo_ps_surface_get_page_media (cairo_ps_surface_t *surface)
{
int width, height;
char buf[50];
cairo_page_media_t *page;
width = _cairo_lround (surface->width);
height = _cairo_lround (surface->height);
cairo_list_foreach_entry (page, cairo_page_media_t, &surface->document_media, link) {
if (page->width == width && page->height == height)
return page->name;
}
page = malloc (sizeof (cairo_page_media_t));
if (unlikely (page == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
snprintf (buf, sizeof (buf), "p%dx%d", width , height);
page->name = strdup (buf);
if (unlikely (page->name == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
page->width = width;
page->height = height;
cairo_list_add_tail (&page->link, &surface->document_media);
return page->name;
}
static cairo_surface_t *
_cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
@ -841,6 +902,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->font_subsets);
surface->num_pages = 0;
cairo_list_init (&surface->document_media);
_cairo_array_init (&surface->dsc_header_comments, sizeof (char *));
_cairo_array_init (&surface->dsc_setup_comments, sizeof (char *));
_cairo_array_init (&surface->dsc_page_setup_comments, sizeof (char *));
@ -1392,6 +1454,17 @@ CLEANUP:
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
while (! cairo_list_is_empty (&surface->document_media)) {
cairo_page_media_t *page;
page = cairo_list_first_entry (&surface->document_media,
cairo_page_media_t,
link);
cairo_list_del (&page->link);
free (page->name);
free (page);
}
num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
comments = _cairo_array_index (&surface->dsc_header_comments, 0);
for (i = 0; i < num_comments; i++)
@ -3563,6 +3636,8 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
int i, num_comments;
char **comments;
int x1, y1, x2, y2;
cairo_bool_t has_page_media;
const char *page_media;
if (surface->eps) {
x1 = floor (_cairo_fixed_to_double (bbox->p1.x));
@ -3589,16 +3664,29 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
_cairo_output_stream_printf (surface->stream,
"%%%%BeginPageSetup\n");
has_page_media = FALSE;
num_comments = _cairo_array_num_elements (&surface->dsc_page_setup_comments);
comments = _cairo_array_index (&surface->dsc_page_setup_comments, 0);
for (i = 0; i < num_comments; i++) {
_cairo_output_stream_printf (surface->stream,
"%s\n", comments[i]);
if (strncmp (comments[i], "%%PageMedia:", 11) == 0)
has_page_media = TRUE;
free (comments[i]);
comments[i] = NULL;
}
_cairo_array_truncate (&surface->dsc_page_setup_comments, 0);
if (!has_page_media && !surface->eps) {
page_media = _cairo_ps_surface_get_page_media (surface);
if (unlikely (page_media == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_output_stream_printf (surface->stream,
"%%%%PageMedia: %s\n",
page_media);
}
_cairo_output_stream_printf (surface->stream,
"%%%%PageBoundingBox: %d %d %d %d\n",
x1, y1, x2, y2);