~ubuntu-branches/ubuntu/intrepid/libcairo/intrepid

« back to all changes in this revision

Viewing changes to src/cairo-ps-surface.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher, Fabien Tassin
  • Date: 2007-12-21 11:46:45 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20071221114645-v1bx91voavqus4uw
Tags: 1.5.4-0ubuntu1
* debian/rules:
  - updated shlibs version

[ Fabien Tassin ]
* new upstream snapshot: 1.5.4
* Drop patches no longer useful:
  - debian/patches/91_malloc-overflow-fixes.dpatch
  - debian/patches/90_from_git_fix_zero_sized_bitmap_handling.dpatch
  - debian/patches/90_from_git_fix_not_available_glyph_handling.dpatch
* Replace Ubuntu's lcd patch by patch from Freedesktop bug #10301
  - drop debian/patches/02-cairo-1.4.8-lcd-filter-2.dpatch
  - add debian/patches/02-lcd_filter_freedesktop_bug10301.patch
* Move from 16.16 to 24.8 fixed point precision
  - add debian/patches/01-fixed_point_24.8_precision.dpatch
* Add libpixman-1-dev (>= 0.9.4) to Build-deps
  - update debian/control
* Update debian/patches/00list

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *
3
3
 * Copyright © 2003 University of Southern California
4
4
 * Copyright © 2005 Red Hat, Inc
 
5
 * Copyright © 2007 Adrian Johnson
5
6
 *
6
7
 * This library is free software; you can redistribute it and/or
7
8
 * modify it either under the terms of the GNU Lesser General Public
35
36
 *      Carl D. Worth <cworth@cworth.org>
36
37
 *      Kristian Høgsberg <krh@redhat.com>
37
38
 *      Keith Packard <keithp@keithp.com>
 
39
 *      Adrian Johnson <ajohnson@redneon.com>
38
40
 */
39
41
 
40
42
#include "cairoint.h"
49
51
#include <time.h>
50
52
#include <zlib.h>
51
53
 
 
54
#define DEBUG_PS 0
 
55
 
 
56
typedef enum _cairo_image_transparency {
 
57
    CAIRO_IMAGE_IS_OPAQUE,
 
58
    CAIRO_IMAGE_HAS_BILEVEL_ALPHA,
 
59
    CAIRO_IMAGE_HAS_ALPHA
 
60
} cairo_image_transparency_t;
 
61
 
52
62
static const cairo_surface_backend_t cairo_ps_surface_backend;
53
63
static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
54
64
 
 
65
static const cairo_ps_level_t _cairo_ps_levels[] =
 
66
{
 
67
    CAIRO_PS_LEVEL_2,
 
68
    CAIRO_PS_LEVEL_3
 
69
};
 
70
 
 
71
#define CAIRO_PS_LEVEL_LAST ARRAY_LENGTH (_cairo_ps_levels)
 
72
 
 
73
static const char * _cairo_ps_level_strings[CAIRO_PS_LEVEL_LAST] =
 
74
{
 
75
    "PS Level 2",
 
76
    "PS Level 3"
 
77
};
 
78
 
55
79
/* A word wrap stream can be used as a filter to do word wrapping on
56
80
 * top of an existing output stream. The word wrapping is quite
57
81
 * simple, using isspace to determine characters that separate
147
171
    word_wrap_stream_t *stream;
148
172
 
149
173
    stream = malloc (sizeof (word_wrap_stream_t));
150
 
    if (stream == NULL)
 
174
    if (stream == NULL) {
 
175
        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
151
176
        return (cairo_output_stream_t *) &_cairo_output_stream_nil;
 
177
    }
152
178
 
153
179
    _cairo_output_stream_init (&stream->base,
154
180
                               _word_wrap_stream_write,
178
204
    path_info->has_sub_path = FALSE;
179
205
 
180
206
    _cairo_output_stream_printf (path_info->stream,
181
 
                                 "%f %f moveto ",
 
207
                                 "%f %f M ",
182
208
                                 _cairo_fixed_to_double (point->x),
183
209
                                 _cairo_fixed_to_double (point->y));
184
210
 
201
227
    path_info->has_sub_path = TRUE;
202
228
 
203
229
    _cairo_output_stream_printf (path_info->stream,
204
 
                                 "%f %f lineto ",
 
230
                                 "%f %f L ",
205
231
                                 _cairo_fixed_to_double (point->x),
206
232
                                 _cairo_fixed_to_double (point->y));
207
233
 
219
245
    path_info->has_sub_path = TRUE;
220
246
 
221
247
    _cairo_output_stream_printf (path_info->stream,
222
 
                                 "%f %f %f %f %f %f curveto ",
 
248
                                 "%f %f %f %f %f %f C ",
223
249
                                 _cairo_fixed_to_double (b->x),
224
250
                                 _cairo_fixed_to_double (b->y),
225
251
                                 _cairo_fixed_to_double (c->x),
242
268
    }
243
269
 
244
270
    _cairo_output_stream_printf (path_info->stream,
245
 
                                 "closepath\n");
 
271
                                 "P\n");
246
272
 
247
273
    return CAIRO_STATUS_SUCCESS;
248
274
}
267
293
    ps_path_info_t path_info;
268
294
 
269
295
    word_wrap = _word_wrap_stream_create (stream, 79);
 
296
    status = _cairo_output_stream_get_status (word_wrap);
 
297
    if (status)
 
298
        return status;
270
299
 
271
300
    path_info.surface = surface;
272
301
    path_info.stream = word_wrap;
279
308
                                          _cairo_ps_surface_path_close_path,
280
309
                                          &path_info);
281
310
 
282
 
    if (status == CAIRO_STATUS_SUCCESS)
283
 
        status = _cairo_output_stream_get_status (word_wrap);
284
311
    status2 = _cairo_output_stream_destroy (word_wrap);
285
312
    if (status == CAIRO_STATUS_SUCCESS)
286
313
        status = status2;
294
321
    time_t now;
295
322
    char **comments;
296
323
    int i, num_comments;
 
324
    const char *level;
 
325
    const char *eps_header = "";
297
326
 
298
327
    now = time (NULL);
299
328
 
 
329
    if (surface->ps_level == CAIRO_PS_LEVEL_2)
 
330
        level = "2";
 
331
    else
 
332
        level = "3";
 
333
 
 
334
    if (surface->eps)
 
335
        eps_header = " EPSF-3.0";
 
336
 
300
337
    _cairo_output_stream_printf (surface->final_stream,
301
 
                                 "%%!PS-Adobe-3.0\n"
 
338
                                 "%%!PS-Adobe-3.0%s\n"
302
339
                                 "%%%%Creator: cairo %s (http://cairographics.org)\n"
303
340
                                 "%%%%CreationDate: %s"
304
341
                                 "%%%%Pages: %d\n"
305
342
                                 "%%%%BoundingBox: %d %d %d %d\n",
306
 
                                 cairo_version_string (),
 
343
                                 eps_header,
 
344
                                 cairo_version_string (),
307
345
                                 ctime (&now),
308
346
                                 surface->num_pages,
309
 
                                 0, 0,
310
 
                                 (int) ceil (surface->max_width),
311
 
                                 (int) ceil (surface->max_height));
 
347
                                 surface->bbox_x1,
 
348
                                 surface->bbox_y1,
 
349
                                 surface->bbox_x2,
 
350
                                 surface->bbox_y2);
312
351
 
313
352
    _cairo_output_stream_printf (surface->final_stream,
314
353
                                 "%%%%DocumentData: Clean7Bit\n"
315
 
                                 "%%%%LanguageLevel: 2\n");
 
354
                                 "%%%%LanguageLevel: %s\n",
 
355
                                 level);
316
356
 
317
357
    num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
318
358
    comments = _cairo_array_index (&surface->dsc_header_comments, 0);
327
367
                                 "%%%%EndComments\n");
328
368
 
329
369
    _cairo_output_stream_printf (surface->final_stream,
330
 
                                 "%%%%BeginProlog\n"
 
370
                                 "%%%%BeginProlog\n");
 
371
 
 
372
    if (surface->eps) {
 
373
        _cairo_output_stream_printf (surface->final_stream,
 
374
                                     "/cairo_eps_state save def\n"
 
375
                                     "/dict_count countdictstack def\n"
 
376
                                     "/op_count count 1 sub def\n"
 
377
                                     "userdict begin\n");
 
378
    }
 
379
 
 
380
    _cairo_output_stream_printf (surface->final_stream,
331
381
                                 "/C{curveto}bind def\n"
332
382
                                 "/F{fill}bind def\n"
333
383
                                 "/G{setgray}bind def\n"
379
429
 
380
430
    /* FIXME: Figure out document structure convention for fonts */
381
431
 
 
432
#if DEBUG_PS
382
433
    _cairo_output_stream_printf (surface->final_stream,
383
434
                                 "%% _cairo_ps_surface_emit_type1_font_subset\n");
 
435
#endif
384
436
 
385
437
    length = subset.header_length + subset.data_length + subset.trailer_length;
386
438
    _cairo_output_stream_write (surface->final_stream, subset.data, length);
408
460
 
409
461
    /* FIXME: Figure out document structure convention for fonts */
410
462
 
 
463
#if DEBUG_PS
411
464
    _cairo_output_stream_printf (surface->final_stream,
412
465
                                 "%% _cairo_ps_surface_emit_type1_font_fallback\n");
 
466
#endif
413
467
 
414
468
    length = subset.header_length + subset.data_length + subset.trailer_length;
415
469
    _cairo_output_stream_write (surface->final_stream, subset.data, length);
435
489
 
436
490
    /* FIXME: Figure out document structure convention for fonts */
437
491
 
 
492
#if DEBUG_PS
438
493
    _cairo_output_stream_printf (surface->final_stream,
439
494
                                 "%% _cairo_ps_surface_emit_truetype_font_subset\n");
 
495
#endif
440
496
 
441
497
    _cairo_output_stream_printf (surface->final_stream,
442
498
                                 "11 dict begin\n"
452
508
 
453
509
    /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
454
510
 
455
 
    for (i = 1; i < font_subset->num_glyphs; i++)
456
 
        _cairo_output_stream_printf (surface->final_stream,
457
 
                                     "Encoding %d /g%d put\n", i, i);
 
511
    for (i = 1; i < font_subset->num_glyphs; i++) {
 
512
        if (font_subset->glyph_names != NULL) {
 
513
            _cairo_output_stream_printf (surface->final_stream,
 
514
                                         "Encoding %d /%s put\n",
 
515
                                         i, font_subset->glyph_names[i]);
 
516
        } else {
 
517
            _cairo_output_stream_printf (surface->final_stream,
 
518
                                         "Encoding %d /g%d put\n", i, i);
 
519
        }
 
520
    }
458
521
 
459
522
    _cairo_output_stream_printf (surface->final_stream,
460
523
                                 "/CharStrings %d dict dup begin\n"
461
524
                                 "/.notdef 0 def\n",
462
525
                                 font_subset->num_glyphs);
463
526
 
464
 
    for (i = 1; i < font_subset->num_glyphs; i++)
465
 
        _cairo_output_stream_printf (surface->final_stream,
466
 
                                     "/g%d %d def\n", i, i);
 
527
    for (i = 1; i < font_subset->num_glyphs; i++) {
 
528
        if (font_subset->glyph_names != NULL) {
 
529
            _cairo_output_stream_printf (surface->final_stream,
 
530
                                         "/%s %d def\n",
 
531
                                         font_subset->glyph_names[i], i);
 
532
        } else {
 
533
            _cairo_output_stream_printf (surface->final_stream,
 
534
                                         "/g%d %d def\n", i, i);
 
535
        }
 
536
    }
467
537
 
468
538
    _cairo_output_stream_printf (surface->final_stream,
469
539
                                 "end readonly def\n");
541
611
    cairo_image_surface_t *image;
542
612
    unsigned char *row, *byte;
543
613
    int rows, cols;
 
614
    double x_advance, y_advance;
544
615
 
545
616
    status = _cairo_scaled_glyph_lookup (scaled_font,
546
617
                                         glyph_index,
550
621
    if (status)
551
622
        return status;
552
623
 
 
624
    x_advance = scaled_glyph->metrics.x_advance;
 
625
    y_advance = scaled_glyph->metrics.y_advance;
 
626
    cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
 
627
 
553
628
    image = scaled_glyph->surface;
554
629
    if (image->format != CAIRO_FORMAT_A1) {
555
630
        image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
558
633
    }
559
634
 
560
635
    _cairo_output_stream_printf (surface->final_stream,
561
 
                                 "0 0 %f %f %f %f setcachedevice\n",
 
636
                                 "%f 0 %f %f %f %f setcachedevice\n",
 
637
                                 x_advance,
562
638
                                 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
563
 
                                 - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
 
639
                                 _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
564
640
                                 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
565
 
                                 - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
 
641
                                 _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
566
642
 
567
643
    _cairo_output_stream_printf (surface->final_stream,
568
644
                                 "<<\n"
574
650
                                 "   /BitsPerComponent 1\n",
575
651
                                 image->width,
576
652
                                 image->height,
577
 
                                 image->base.device_transform_inverse.xx,
578
 
                                 image->base.device_transform_inverse.yx,
579
 
                                 image->base.device_transform_inverse.xy,
580
 
                                 image->base.device_transform_inverse.yy,
581
 
                                 image->base.device_transform_inverse.x0,
582
 
                                 image->base.device_transform_inverse.y0);
 
653
                                 image->base.device_transform.xx,
 
654
                                 image->base.device_transform.yx,
 
655
                                 image->base.device_transform.xy,
 
656
                                 image->base.device_transform.yy,
 
657
                                 image->base.device_transform.x0,
 
658
                                 image->base.device_transform.y0);
583
659
 
584
660
    _cairo_output_stream_printf (surface->final_stream,
585
661
                                 "   /DataSource   {<");
610
686
                              unsigned long              scaled_font_glyph_index,
611
687
                              unsigned int               subset_glyph_index)
612
688
{
613
 
    cairo_status_t          status;
 
689
    cairo_status_t          status = CAIRO_STATUS_SUCCESS;
614
690
 
615
691
    _cairo_output_stream_printf (surface->final_stream,
616
692
                                 "\t\t{ %% %d\n", subset_glyph_index);
617
693
 
618
 
    status = _cairo_ps_surface_emit_outline_glyph_data (surface,
619
 
                                                        scaled_font,
620
 
                                                        scaled_font_glyph_index);
621
 
    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
622
 
        status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
623
 
                                                           scaled_font,
624
 
                                                           scaled_font_glyph_index);
 
694
    if (subset_glyph_index != 0) {
 
695
        status = _cairo_ps_surface_emit_outline_glyph_data (surface,
 
696
                                                            scaled_font,
 
697
                                                            scaled_font_glyph_index);
 
698
        if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 
699
            status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
 
700
                                                               scaled_font,
 
701
                                                               scaled_font_glyph_index);
 
702
    }
625
703
 
626
704
    _cairo_output_stream_printf (surface->final_stream,
627
705
                                 "\t\t}\n");
628
706
 
629
707
    if (status)
630
 
        _cairo_surface_set_error (&surface->base, status);
 
708
        status = _cairo_surface_set_error (&surface->base, status);
631
709
 
632
710
    return status;
633
711
}
642
720
    cairo_matrix_t matrix;
643
721
    unsigned int i;
644
722
 
 
723
#if DEBUG_PS
645
724
    _cairo_output_stream_printf (surface->final_stream,
646
725
                                 "%% _cairo_ps_surface_emit_type3_font_subset\n");
647
 
 
648
 
    _cairo_output_stream_printf (surface->final_stream,
649
 
                                 "/CairoFont-%d-%d <<\n",
650
 
                                 font_subset->font_id,
651
 
                                 font_subset->subset_id);
 
726
#endif
652
727
 
653
728
    matrix = font_subset->scaled_font->scale;
654
729
    status = cairo_matrix_invert (&matrix);
655
730
    /* _cairo_scaled_font_init ensures the matrix is invertible */
656
731
    assert (status == CAIRO_STATUS_SUCCESS);
657
732
    _cairo_output_stream_printf (surface->final_stream,
658
 
                                 "\t/FontType\t3\n"
659
 
                                 "\t/FontMatrix\t[%f %f %f %f 0 0]\n"
660
 
                                 "\t/Encoding\t[0]\n"
661
 
                                 "\t/FontBBox\t[0 0 10 10]\n"
662
 
                                 "\t/Glyphs [\n",
 
733
                                 "8 dict begin\n"
 
734
                                 "/FontType 3 def\n"
 
735
                                 "/FontMatrix [%f %f %f %f 0 0] def\n"
 
736
                                 "/FontBBox [0 0 0 0] def\n"
 
737
                                 "/Encoding 256 array def\n"
 
738
                                 "0 1 255 { Encoding exch /.notdef put } for\n",
663
739
                                 matrix.xx,
664
740
                                 matrix.yx,
665
741
                                 -matrix.xy,
666
742
                                 -matrix.yy);
667
743
 
 
744
    for (i = 1; i < font_subset->num_glyphs; i++) {
 
745
        if (font_subset->glyph_names != NULL) {
 
746
            _cairo_output_stream_printf (surface->final_stream,
 
747
                                         "Encoding %d /%s put\n",
 
748
                                         i, font_subset->glyph_names[i]);
 
749
        } else {
 
750
            _cairo_output_stream_printf (surface->final_stream,
 
751
                                         "Encoding %d /g%d put\n", i, i);
 
752
        }
 
753
    }
 
754
 
 
755
    _cairo_output_stream_printf (surface->final_stream,
 
756
                                 "/Glyphs [\n");
 
757
 
668
758
    for (i = 0; i < font_subset->num_glyphs; i++) {
669
759
        status = _cairo_ps_surface_emit_glyph (surface,
670
760
                                               font_subset->scaled_font,
674
764
    }
675
765
 
676
766
    _cairo_output_stream_printf (surface->final_stream,
677
 
                                 "\t]\n"
678
 
                                 "\t/BuildChar {\n"
679
 
                                 "\t\texch /Glyphs get\n"
680
 
                                 "\t\texch get exec\n"
681
 
                                 "\t}\n"
682
 
                                 ">> definefont pop\n");
 
767
                                 "] def\n"
 
768
                                 "/BuildChar {\n"
 
769
                                 "  exch /Glyphs get\n"
 
770
                                 "  exch get exec\n"
 
771
                                 "} bind def\n"
 
772
                                 "currentdict\n"
 
773
                                 "end\n"
 
774
                                 "/CairoFont-%d-%d exch definefont pop\n",
 
775
                                 font_subset->font_id,
 
776
                                 font_subset->subset_id);
683
777
 
684
778
    return CAIRO_STATUS_SUCCESS;
685
779
}
686
780
 
687
 
 
688
 
static void
 
781
static cairo_status_t
689
782
_cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
690
783
                                            void                        *closure)
691
784
{
692
785
    cairo_ps_surface_t *surface = closure;
693
786
    cairo_status_t status;
694
787
 
 
788
 
 
789
    status = _cairo_scaled_font_subset_create_glyph_names (font_subset);
 
790
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 
791
        return status;
 
792
 
695
793
#if CAIRO_HAS_FT_FONT
696
794
    status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset);
697
795
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
698
 
        return;
 
796
        return status;
699
797
#endif
700
798
 
701
799
    status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset);
702
800
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
703
 
        return;
 
801
        return status;
704
802
 
705
803
    status = _cairo_ps_surface_emit_type1_font_fallback (surface, font_subset);
706
804
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
707
 
        return;
 
805
        return status;
 
806
 
 
807
    return CAIRO_STATUS_SUCCESS;
708
808
}
709
809
 
710
 
static void
 
810
static cairo_status_t
711
811
_cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
712
812
                                           void                       *closure)
713
813
{
714
814
    cairo_ps_surface_t *surface = closure;
715
815
    cairo_status_t status;
716
816
 
 
817
    status = _cairo_scaled_font_subset_create_glyph_names (font_subset);
 
818
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 
819
        return status;
 
820
 
717
821
    status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
718
822
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
719
 
        return;
 
823
        return status;
 
824
 
 
825
    return CAIRO_STATUS_SUCCESS;
720
826
}
721
827
 
722
828
static cairo_status_t
724
830
{
725
831
    cairo_status_t status;
726
832
 
 
833
#if DEBUG_PS
727
834
    _cairo_output_stream_printf (surface->final_stream,
728
835
                                 "%% _cairo_ps_surface_emit_font_subsets\n");
 
836
#endif
729
837
 
730
838
    status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
731
839
                                                          _cairo_ps_surface_emit_unscaled_font_subset,
732
840
                                                          surface);
 
841
    if (status)
 
842
        goto BAIL;
 
843
 
733
844
    status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
734
845
                                                        _cairo_ps_surface_emit_scaled_font_subset,
735
846
                                                        surface);
 
847
 
 
848
BAIL:
736
849
    _cairo_scaled_font_subsets_destroy (surface->font_subsets);
737
850
    surface->font_subsets = NULL;
738
851
 
754
867
_cairo_ps_surface_emit_footer (cairo_ps_surface_t *surface)
755
868
{
756
869
    _cairo_output_stream_printf (surface->final_stream,
757
 
                                 "%%%%Trailer\n"
 
870
                                 "%%%%Trailer\n");
 
871
 
 
872
    if (surface->eps) {
 
873
        _cairo_output_stream_printf (surface->final_stream,
 
874
                                     "count op_count sub {pop} repeat\n"
 
875
                                     "countdictstack dict_count sub {end} repeat\n"
 
876
                                     "cairo_eps_state restore\n");
 
877
    }
 
878
 
 
879
    _cairo_output_stream_printf (surface->final_stream,
758
880
                                 "%%%%EOF\n");
759
881
}
760
882
 
764
886
                                              double                 height)
765
887
{
766
888
    cairo_status_t status;
767
 
    cairo_ps_surface_t *surface = NULL;
 
889
    cairo_ps_surface_t *surface;
768
890
 
769
891
    surface = malloc (sizeof (cairo_ps_surface_t));
770
892
    if (surface == NULL) {
771
 
        status = CAIRO_STATUS_NO_MEMORY;
 
893
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
772
894
        goto CLEANUP;
773
895
    }
774
896
 
790
912
    if (! surface->font_subsets)
791
913
        goto CLEANUP_OUTPUT_STREAM;
792
914
 
 
915
    surface->eps = FALSE;
 
916
    surface->ps_level = CAIRO_PS_LEVEL_3;
793
917
    surface->width  = width;
794
918
    surface->height = height;
795
 
    surface->max_width = width;
796
 
    surface->max_height = height;
797
919
    surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
798
920
    surface->force_fallbacks = FALSE;
 
921
    surface->content = CAIRO_CONTENT_COLOR_ALPHA;
799
922
 
800
923
    surface->num_pages = 0;
801
924
 
805
928
 
806
929
    surface->dsc_comment_target = &surface->dsc_header_comments;
807
930
 
808
 
    return _cairo_paginated_surface_create (&surface->base,
809
 
                                            CAIRO_CONTENT_COLOR_ALPHA,
810
 
                                            width, height,
811
 
                                            &cairo_ps_surface_paginated_backend);
 
931
    surface->paginated_surface = _cairo_paginated_surface_create (
 
932
                                           &surface->base,
 
933
                                           CAIRO_CONTENT_COLOR_ALPHA,
 
934
                                           width, height,
 
935
                                           &cairo_ps_surface_paginated_backend);
 
936
    if (surface->paginated_surface->status == CAIRO_STATUS_SUCCESS)
 
937
        return surface->paginated_surface;
812
938
 
 
939
    _cairo_scaled_font_subsets_destroy (surface->font_subsets);
813
940
 CLEANUP_OUTPUT_STREAM:
814
941
    status = _cairo_output_stream_destroy (surface->stream);
815
942
    /* Ignore status---we're already on a failure path. */
818
945
 CLEANUP_SURFACE:
819
946
    free (surface);
820
947
 CLEANUP:
821
 
    _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
948
    /* destroy stream on behalf of caller */
 
949
    status = _cairo_output_stream_destroy (stream);
 
950
    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
822
951
    return (cairo_surface_t*) &_cairo_surface_nil;
823
952
}
824
953
 
856
985
 
857
986
    stream = _cairo_output_stream_create_for_filename (filename);
858
987
    status = _cairo_output_stream_get_status (stream);
859
 
    if (status) {
860
 
        _cairo_error (status);
 
988
    if (status)
861
989
        return (status == CAIRO_STATUS_WRITE_ERROR) ?
862
990
                (cairo_surface_t*) &_cairo_surface_nil_write_error :
863
991
                (cairo_surface_t*) &_cairo_surface_nil;
864
 
    }
865
992
 
866
993
    return _cairo_ps_surface_create_for_stream_internal (stream,
867
994
                                                         width_in_points,
904
1031
 
905
1032
    stream = _cairo_output_stream_create (write_func, NULL, closure);
906
1033
    status = _cairo_output_stream_get_status (stream);
907
 
    if (status) {
908
 
        _cairo_error (status);
 
1034
    if (status)
909
1035
        return (cairo_surface_t*) &_cairo_surface_nil;
910
 
    }
911
1036
 
912
1037
    return _cairo_ps_surface_create_for_stream_internal (stream,
913
1038
                                                         width_in_points,
931
1056
    cairo_surface_t *target;
932
1057
 
933
1058
    if (! _cairo_surface_is_paginated (surface))
934
 
        return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
 
1059
        return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
935
1060
 
936
1061
    target = _cairo_paginated_surface_get_target (surface);
937
1062
 
938
1063
    if (! _cairo_surface_is_ps (target))
939
 
        return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
 
1064
        return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
940
1065
 
941
1066
    *ps_surface = (cairo_ps_surface_t *) target;
942
1067
 
944
1069
}
945
1070
 
946
1071
/**
 
1072
 * cairo_ps_surface_restrict_to_level:
 
1073
 * @surface: a PostScript #cairo_surface_t
 
1074
 * @level: PostScript level
 
1075
 *
 
1076
 * Restricts the generated PostSript file to @level. See
 
1077
 * cairo_ps_get_levels() for a list of available level values that
 
1078
 * can be used here.
 
1079
 *
 
1080
 * This function should only be called before any drawing operations
 
1081
 * have been performed on the given surface. The simplest way to do
 
1082
 * this is to call this function immediately after creating the
 
1083
 * surface.
 
1084
 *
 
1085
 * Since: 1.6
 
1086
 **/
 
1087
void
 
1088
cairo_ps_surface_restrict_to_level (cairo_surface_t  *surface,
 
1089
                                    cairo_ps_level_t  level)
 
1090
{
 
1091
    cairo_ps_surface_t *ps_surface = NULL;
 
1092
    cairo_status_t status;
 
1093
 
 
1094
    status = _extract_ps_surface (surface, &ps_surface);
 
1095
    if (status) {
 
1096
        status = _cairo_surface_set_error (surface, status);
 
1097
        return;
 
1098
    }
 
1099
 
 
1100
    if (level < CAIRO_PS_LEVEL_LAST)
 
1101
        ps_surface->ps_level = level;
 
1102
}
 
1103
 
 
1104
/**
 
1105
 * cairo_ps_get_levels:
 
1106
 * @levels: supported level list
 
1107
 * @num_levels: list length
 
1108
 *
 
1109
 * Used to retrieve the list of supported levels. See
 
1110
 * cairo_ps_surface_restrict_to_level().
 
1111
 *
 
1112
 * Since: 1.6
 
1113
 **/
 
1114
void
 
1115
cairo_ps_get_levels (cairo_ps_level_t const     **levels,
 
1116
                     int                         *num_levels)
 
1117
{
 
1118
    if (levels != NULL)
 
1119
        *levels = _cairo_ps_levels;
 
1120
 
 
1121
    if (num_levels != NULL)
 
1122
        *num_levels = CAIRO_PS_LEVEL_LAST;
 
1123
}
 
1124
 
 
1125
/**
 
1126
 * cairo_ps_level_to_string:
 
1127
 * @level: a level id
 
1128
 *
 
1129
 * Get the string representation of the given @level id. This function
 
1130
 * will return NULL if @level id isn't valid. See cairo_ps_get_levels()
 
1131
 * for a way to get the list of valid level ids.
 
1132
 *
 
1133
 * Return value: the string associated to given level.
 
1134
 *
 
1135
 * Since: 1.6
 
1136
 **/
 
1137
const char *
 
1138
cairo_ps_level_to_string (cairo_ps_level_t level)
 
1139
{
 
1140
    if (level >= CAIRO_PS_LEVEL_LAST)
 
1141
        return NULL;
 
1142
 
 
1143
    return _cairo_ps_level_strings[level];
 
1144
}
 
1145
 
 
1146
/**
 
1147
 * cairo_ps_surface_set_eps:
 
1148
 * @surface: a PostScript cairo_surface_t
 
1149
 * @eps: TRUE to output EPS format PostScript
 
1150
 *
 
1151
 * If @eps is TRUE, the PostScript surface will output Encapsulated
 
1152
 * PostScript.
 
1153
 *
 
1154
 * This function should only be called before any drawing operations
 
1155
 * have been performed on the current page. The simplest way to do
 
1156
 * this is to call this function immediately after creating the
 
1157
 * surface. An Encapsulated Postscript file should never contain more
 
1158
 * than one page.
 
1159
 *
 
1160
 * Since: 1.6
 
1161
 **/
 
1162
void
 
1163
cairo_ps_surface_set_eps (cairo_surface_t       *surface,
 
1164
                          cairo_bool_t           eps)
 
1165
{
 
1166
    cairo_ps_surface_t *ps_surface = NULL;
 
1167
    cairo_status_t status;
 
1168
 
 
1169
    status = _extract_ps_surface (surface, &ps_surface);
 
1170
    if (status) {
 
1171
        status = _cairo_surface_set_error (surface, status);
 
1172
        return;
 
1173
    }
 
1174
 
 
1175
    ps_surface->eps = eps;
 
1176
}
 
1177
 
 
1178
/**
 
1179
 * cairo_ps_surface_get_eps:
 
1180
 * @surface: a PostScript cairo_surface_t
 
1181
 *
 
1182
 * Check whether the PostScript surface will output Encapsulated PostScript.
 
1183
 *
 
1184
 * Return value: TRUE if the surface will output Encapsulated PostScript.
 
1185
 *
 
1186
 * Since: 1.6
 
1187
 **/
 
1188
cairo_public cairo_bool_t
 
1189
cairo_ps_surface_get_eps (cairo_surface_t       *surface)
 
1190
{
 
1191
    cairo_ps_surface_t *ps_surface = NULL;
 
1192
    cairo_status_t status;
 
1193
 
 
1194
    status = _extract_ps_surface (surface, &ps_surface);
 
1195
    if (status) {
 
1196
        status = _cairo_surface_set_error (surface, status);
 
1197
        return FALSE;
 
1198
    }
 
1199
 
 
1200
    return ps_surface->eps;
 
1201
}
 
1202
 
 
1203
/**
947
1204
 * cairo_ps_surface_set_size:
948
1205
 * @surface: a PostScript cairo_surface_t
949
1206
 * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
965
1222
                           double                width_in_points,
966
1223
                           double                height_in_points)
967
1224
{
968
 
    cairo_ps_surface_t *ps_surface;
 
1225
    cairo_ps_surface_t *ps_surface = NULL;
969
1226
    cairo_status_t status;
970
1227
 
971
1228
    status = _extract_ps_surface (surface, &ps_surface);
972
1229
    if (status) {
973
 
        _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
1230
        status = _cairo_surface_set_error (surface, status);
974
1231
        return;
975
1232
    }
976
1233
 
977
1234
    ps_surface->width = width_in_points;
978
1235
    ps_surface->height = height_in_points;
 
1236
    status = _cairo_paginated_surface_set_size (ps_surface->paginated_surface,
 
1237
                                                width_in_points,
 
1238
                                                height_in_points);
 
1239
    if (status)
 
1240
        status = _cairo_surface_set_error (surface, status);
979
1241
}
980
1242
 
981
1243
/**
1070
1332
cairo_ps_surface_dsc_comment (cairo_surface_t   *surface,
1071
1333
                              const char        *comment)
1072
1334
{
1073
 
    cairo_ps_surface_t *ps_surface;
 
1335
    cairo_ps_surface_t *ps_surface = NULL;
1074
1336
    cairo_status_t status;
1075
1337
    char *comment_copy;
1076
1338
 
1077
1339
    status = _extract_ps_surface (surface, &ps_surface);
1078
1340
    if (status) {
1079
 
        _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
1341
        status = _cairo_surface_set_error (surface, status);
1080
1342
        return;
1081
1343
    }
1082
1344
 
1083
1345
    /* A couple of sanity checks on the comment value. */
1084
1346
    if (comment == NULL) {
1085
 
        _cairo_surface_set_error (surface, CAIRO_STATUS_NULL_POINTER);
 
1347
        status = _cairo_surface_set_error (surface, CAIRO_STATUS_NULL_POINTER);
1086
1348
        return;
1087
1349
    }
1088
1350
 
1089
1351
    if (comment[0] != '%' || strlen (comment) > 255) {
1090
 
        _cairo_surface_set_error (surface, CAIRO_STATUS_INVALID_DSC_COMMENT);
 
1352
        status = _cairo_surface_set_error (surface, CAIRO_STATUS_INVALID_DSC_COMMENT);
1091
1353
        return;
1092
1354
    }
1093
1355
 
1094
1356
    /* Then, copy the comment and store it in the appropriate array. */
1095
1357
    comment_copy = strdup (comment);
1096
1358
    if (comment_copy == NULL) {
1097
 
        _cairo_surface_set_error (surface, CAIRO_STATUS_NO_MEMORY);
 
1359
        status = _cairo_surface_set_error (surface, CAIRO_STATUS_NO_MEMORY);
1098
1360
        return;
1099
1361
    }
1100
1362
 
1101
1363
    status = _cairo_array_append (ps_surface->dsc_comment_target, &comment_copy);
1102
1364
    if (status) {
1103
1365
        free (comment_copy);
1104
 
        _cairo_surface_set_error (surface, status);
 
1366
        status = _cairo_surface_set_error (surface, status);
1105
1367
        return;
1106
1368
    }
1107
1369
}
1125
1387
void
1126
1388
cairo_ps_surface_dsc_begin_setup (cairo_surface_t *surface)
1127
1389
{
1128
 
    cairo_ps_surface_t *ps_surface;
 
1390
    cairo_ps_surface_t *ps_surface = NULL;
1129
1391
    cairo_status_t status;
1130
1392
 
1131
1393
    status = _extract_ps_surface (surface, &ps_surface);
1132
1394
    if (status) {
1133
 
        _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
1395
        status = _cairo_surface_set_error (surface, status);
1134
1396
        return;
1135
1397
    }
1136
1398
 
1160
1422
void
1161
1423
cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface)
1162
1424
{
1163
 
    cairo_ps_surface_t *ps_surface;
 
1425
    cairo_ps_surface_t *ps_surface = NULL;
1164
1426
    cairo_status_t status;
1165
1427
 
1166
1428
    status = _extract_ps_surface (surface, &ps_surface);
1167
1429
    if (status) {
1168
 
        _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 
1430
        status = _cairo_surface_set_error (surface, status);
1169
1431
        return;
1170
1432
    }
1171
1433
 
1176
1438
    }
1177
1439
}
1178
1440
 
 
1441
static cairo_surface_t *
 
1442
_cairo_ps_surface_create_similar (void                  *abstract_surface,
 
1443
                                  cairo_content_t        content,
 
1444
                                  int                    width,
 
1445
                                  int                    height)
 
1446
{
 
1447
    return _cairo_meta_surface_create (content, width, height);
 
1448
}
 
1449
 
1179
1450
static cairo_status_t
1180
1451
_cairo_ps_surface_finish (void *abstract_surface)
1181
1452
{
1186
1457
 
1187
1458
    _cairo_ps_surface_emit_header (surface);
1188
1459
 
1189
 
    _cairo_ps_surface_emit_font_subsets (surface);
 
1460
    status = _cairo_ps_surface_emit_font_subsets (surface);
1190
1461
 
1191
1462
    _cairo_ps_surface_emit_body (surface);
1192
1463
 
1193
1464
    _cairo_ps_surface_emit_footer (surface);
1194
1465
 
1195
 
    status = _cairo_output_stream_destroy (surface->stream);
 
1466
    status2 = _cairo_output_stream_destroy (surface->stream);
 
1467
    if (status == CAIRO_STATUS_SUCCESS)
 
1468
        status = status2;
1196
1469
 
1197
1470
    fclose (surface->tmpfile);
1198
1471
 
1225
1498
_cairo_ps_surface_start_page (void *abstract_surface)
1226
1499
{
1227
1500
    cairo_ps_surface_t *surface = abstract_surface;
1228
 
    int i, num_comments;
1229
 
    char **comments;
1230
1501
 
1231
1502
    /* Increment before print so page numbers start at 1. */
1232
1503
    surface->num_pages++;
1233
 
    _cairo_output_stream_printf (surface->stream,
1234
 
                                 "%%%%Page: %d %d\n",
1235
 
                                 surface->num_pages,
1236
 
                                 surface->num_pages);
1237
 
 
1238
 
    _cairo_output_stream_printf (surface->stream,
1239
 
                                 "%%%%BeginPageSetup\n");
1240
 
 
1241
 
    num_comments = _cairo_array_num_elements (&surface->dsc_page_setup_comments);
1242
 
    comments = _cairo_array_index (&surface->dsc_page_setup_comments, 0);
1243
 
    for (i = 0; i < num_comments; i++) {
1244
 
        _cairo_output_stream_printf (surface->stream,
1245
 
                                     "%s\n", comments[i]);
1246
 
        free (comments[i]);
1247
 
        comments[i] = NULL;
1248
 
    }
1249
 
    _cairo_array_truncate (&surface->dsc_page_setup_comments, 0);
1250
 
 
1251
 
    _cairo_output_stream_printf (surface->stream,
1252
 
                                 "%%%%PageBoundingBox: %d %d %d %d\n",
1253
 
                                 0, 0,
1254
 
                                 (int) ceil (surface->width),
1255
 
                                 (int) ceil (surface->height));
1256
 
 
1257
 
    _cairo_output_stream_printf (surface->stream,
1258
 
                                 "gsave %f %f translate 1.0 -1.0 scale \n",
1259
 
                                 0.0, surface->height);
1260
 
 
1261
 
    _cairo_output_stream_printf (surface->stream,
1262
 
                                 "%%%%EndPageSetup\n");
1263
 
 
1264
 
    if (surface->width > surface->max_width)
1265
 
        surface->max_width = surface->width;
1266
 
    if (surface->height > surface->max_height)
1267
 
        surface->max_height = surface->height;
1268
 
 
1269
 
    return _cairo_output_stream_get_status (surface->stream);
 
1504
 
 
1505
    return CAIRO_STATUS_SUCCESS;
1270
1506
}
1271
1507
 
1272
1508
static void
1273
1509
_cairo_ps_surface_end_page (cairo_ps_surface_t *surface)
1274
1510
{
1275
1511
    _cairo_output_stream_printf (surface->stream,
1276
 
                                 "grestore\n");
1277
 
}
1278
 
 
1279
 
static cairo_int_status_t
1280
 
_cairo_ps_surface_copy_page (void *abstract_surface)
1281
 
{
1282
 
    cairo_ps_surface_t *surface = abstract_surface;
1283
 
 
1284
 
    _cairo_ps_surface_end_page (surface);
1285
 
 
1286
 
    _cairo_output_stream_printf (surface->stream, "copypage\n");
1287
 
 
1288
 
    return CAIRO_STATUS_SUCCESS;
 
1512
                                 "grestore grestore\n");
1289
1513
}
1290
1514
 
1291
1515
static cairo_int_status_t
1301
1525
}
1302
1526
 
1303
1527
static cairo_bool_t
1304
 
color_is_gray (cairo_color_t *color)
 
1528
color_is_gray (double red, double green, double blue)
1305
1529
{
1306
1530
    const double epsilon = 0.00001;
1307
1531
 
1308
 
    return (fabs (color->red - color->green) < epsilon &&
1309
 
            fabs (color->red - color->blue) < epsilon);
 
1532
    return (fabs (red - green) < epsilon &&
 
1533
            fabs (red - blue) < epsilon);
 
1534
}
 
1535
 
 
1536
static cairo_status_t
 
1537
_analyze_image_transparency (cairo_image_surface_t      *image,
 
1538
                             cairo_image_transparency_t *transparency)
 
1539
{
 
1540
    cairo_status_t status;
 
1541
    int x, y;
 
1542
 
 
1543
    if (image->format == CAIRO_FORMAT_RGB24) {
 
1544
        *transparency = CAIRO_IMAGE_IS_OPAQUE;
 
1545
        return CAIRO_STATUS_SUCCESS;
 
1546
    }
 
1547
 
 
1548
    if (image->format != CAIRO_FORMAT_ARGB32) {
 
1549
        /* If the PS surface does not support the image format, assume
 
1550
         * that it does have alpha. The image will be converted to
 
1551
         * rgb24 when the PS surface blends the image into the page
 
1552
         * color to remove the transparency. */
 
1553
        *transparency = CAIRO_IMAGE_HAS_ALPHA;
 
1554
        return CAIRO_STATUS_SUCCESS;
 
1555
    }
 
1556
 
 
1557
    *transparency = CAIRO_IMAGE_IS_OPAQUE;
 
1558
    for (y = 0; y < image->height; y++) {
 
1559
        int a;
 
1560
        uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
 
1561
 
 
1562
        for (x = 0; x < image->width; x++, pixel++) {
 
1563
            a = (*pixel & 0xff000000) >> 24;
 
1564
            if (a > 0 && a < 255) {
 
1565
                *transparency = CAIRO_IMAGE_HAS_ALPHA;
 
1566
                return CAIRO_STATUS_SUCCESS;
 
1567
            } else if (a == 0) {
 
1568
                *transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
 
1569
            }
 
1570
        }
 
1571
    }
 
1572
    status = CAIRO_STATUS_SUCCESS;
 
1573
 
 
1574
    return status;
 
1575
}
 
1576
 
 
1577
static cairo_int_status_t
 
1578
_cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t      *surface,
 
1579
                                                       cairo_surface_pattern_t *pattern)
 
1580
{
 
1581
    cairo_image_surface_t  *image;
 
1582
    void                   *image_extra;
 
1583
    cairo_int_status_t      status;
 
1584
    cairo_image_transparency_t transparency;
 
1585
 
 
1586
    status = _cairo_surface_acquire_source_image (pattern->surface,
 
1587
                                                  &image,
 
1588
                                                  &image_extra);
 
1589
    if (status)
 
1590
        return status;
 
1591
 
 
1592
    if (image->base.status)
 
1593
        return image->base.status;
 
1594
 
 
1595
    status = _analyze_image_transparency (image, &transparency);
 
1596
    if (status)
 
1597
        goto RELEASE_SOURCE;
 
1598
 
 
1599
    switch (transparency) {
 
1600
    case CAIRO_IMAGE_IS_OPAQUE:
 
1601
        status = CAIRO_STATUS_SUCCESS;
 
1602
        break;
 
1603
 
 
1604
    case CAIRO_IMAGE_HAS_BILEVEL_ALPHA:
 
1605
        if (surface->ps_level == CAIRO_PS_LEVEL_2)
 
1606
            status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 
1607
        else
 
1608
            status = CAIRO_STATUS_SUCCESS;
 
1609
        break;
 
1610
 
 
1611
    case CAIRO_IMAGE_HAS_ALPHA:
 
1612
        status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 
1613
        break;
 
1614
    }
 
1615
 
 
1616
RELEASE_SOURCE:
 
1617
    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
1618
 
 
1619
    return status;
1310
1620
}
1311
1621
 
1312
1622
static cairo_bool_t
1313
 
surface_pattern_supported (const cairo_surface_pattern_t *pattern)
 
1623
surface_pattern_supported (cairo_surface_pattern_t *pattern)
1314
1624
{
1315
1625
    cairo_extend_t extend;
1316
1626
 
 
1627
    if (_cairo_surface_is_meta (pattern->surface))
 
1628
        return TRUE;
 
1629
 
1317
1630
    if (pattern->surface->backend->acquire_source_image == NULL)
1318
1631
        return FALSE;
1319
1632
 
1347
1660
}
1348
1661
 
1349
1662
static cairo_bool_t
1350
 
pattern_supported (const cairo_pattern_t *pattern)
 
1663
_gradient_pattern_supported (cairo_ps_surface_t    *surface,
 
1664
                             cairo_pattern_t *pattern)
 
1665
{
 
1666
    cairo_extend_t extend;
 
1667
 
 
1668
    if (surface->ps_level == CAIRO_PS_LEVEL_2)
 
1669
        return FALSE;
 
1670
 
 
1671
    extend = cairo_pattern_get_extend (pattern);
 
1672
 
 
1673
    if (extend == CAIRO_EXTEND_REPEAT ||
 
1674
        extend == CAIRO_EXTEND_REFLECT) {
 
1675
        return FALSE;
 
1676
    }
 
1677
 
 
1678
    /* Radial gradients are currently only supported when one circle
 
1679
     * is inside the other. */
 
1680
    if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
 
1681
        double x1, y1, x2, y2, r1, r2, d;
 
1682
        cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
 
1683
 
 
1684
        x1 = _cairo_fixed_to_double (radial->c1.x);
 
1685
        y1 = _cairo_fixed_to_double (radial->c1.y);
 
1686
        r1 = _cairo_fixed_to_double (radial->r1);
 
1687
        x2 = _cairo_fixed_to_double (radial->c2.x);
 
1688
        y2 = _cairo_fixed_to_double (radial->c2.y);
 
1689
        r2 = _cairo_fixed_to_double (radial->r2);
 
1690
 
 
1691
        d = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
 
1692
        if (d > fabs(r2 - r1)) {
 
1693
            return FALSE;
 
1694
        }
 
1695
    }
 
1696
 
 
1697
    return TRUE;
 
1698
}
 
1699
 
 
1700
static cairo_bool_t
 
1701
pattern_supported (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
1351
1702
{
1352
1703
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
1353
1704
        return TRUE;
1354
1705
 
 
1706
    if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
 
1707
        pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
 
1708
        return _gradient_pattern_supported (surface, pattern);
 
1709
 
1355
1710
    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
1356
 
        return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
 
1711
        return surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
1357
1712
 
1358
1713
    return FALSE;
1359
1714
}
1360
1715
 
1361
1716
static cairo_int_status_t
1362
 
_cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface,
1363
 
                      cairo_operator_t op,
1364
 
                      const cairo_pattern_t *pattern)
1365
 
{
1366
 
    if (surface->force_fallbacks)
1367
 
        return FALSE;
1368
 
 
1369
 
    if (! pattern_supported (pattern))
1370
 
        return FALSE;
1371
 
 
1372
 
    if (_cairo_operator_always_opaque (op))
 
1717
_cairo_ps_surface_analyze_operation (cairo_ps_surface_t    *surface,
 
1718
                                     cairo_operator_t       op,
 
1719
                                     cairo_pattern_t       *pattern)
 
1720
{
 
1721
    if (surface->force_fallbacks && surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 
1722
        return CAIRO_INT_STATUS_UNSUPPORTED;
 
1723
 
 
1724
    if (! pattern_supported (surface, pattern))
 
1725
        return CAIRO_INT_STATUS_UNSUPPORTED;
 
1726
 
 
1727
    if (!(op == CAIRO_OPERATOR_SOURCE ||
 
1728
          op == CAIRO_OPERATOR_OVER))
 
1729
        return CAIRO_INT_STATUS_UNSUPPORTED;
 
1730
 
 
1731
    if (op == CAIRO_OPERATOR_SOURCE)
 
1732
        return CAIRO_STATUS_SUCCESS;
 
1733
 
 
1734
    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 
1735
        cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
 
1736
 
 
1737
        if ( _cairo_surface_is_meta (surface_pattern->surface))
 
1738
            return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
 
1739
        else
 
1740
            return _cairo_ps_surface_analyze_surface_pattern_transparency (surface,
 
1741
                                                                           surface_pattern);
 
1742
    }
 
1743
 
 
1744
    /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If
 
1745
     * the pattern contains transparency, we return
 
1746
     * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis
 
1747
     * surface. If the analysis surface determines that there is
 
1748
     * anything drawn under this operation, a fallback image will be
 
1749
     * used. Otherwise the operation will be replayed during the
 
1750
     * render stage and we blend the transarency into the white
 
1751
     * background to convert the pattern to opaque.
 
1752
     */
 
1753
 
 
1754
    if (_cairo_pattern_is_opaque (pattern))
 
1755
        return CAIRO_STATUS_SUCCESS;
 
1756
    else
 
1757
        return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 
1758
}
 
1759
 
 
1760
static cairo_bool_t
 
1761
_cairo_ps_surface_operation_supported (cairo_ps_surface_t    *surface,
 
1762
                                       cairo_operator_t       op,
 
1763
                                       cairo_pattern_t       *pattern)
 
1764
{
 
1765
    if (_cairo_ps_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED)
1373
1766
        return TRUE;
1374
 
 
1375
 
    if (_cairo_operator_always_translucent (op))
 
1767
    else
1376
1768
        return FALSE;
1377
 
 
1378
 
    return _cairo_pattern_is_opaque (pattern);
1379
 
}
1380
 
 
1381
 
static cairo_int_status_t
1382
 
_cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
1383
 
                    cairo_operator_t op,
1384
 
                    const cairo_pattern_t *pattern)
1385
 
{
1386
 
    if (_cairo_ps_surface_operation_supported (surface, op, pattern))
1387
 
        return CAIRO_STATUS_SUCCESS;
1388
 
    else
1389
 
        return CAIRO_INT_STATUS_UNSUPPORTED;
1390
1769
}
1391
1770
 
1392
1771
/* The "standard" implementation limit for PostScript string sizes is
1496
1875
    string_array_stream_t *stream;
1497
1876
 
1498
1877
    stream = malloc (sizeof (string_array_stream_t));
1499
 
    if (stream == NULL)
 
1878
    if (stream == NULL) {
 
1879
        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1500
1880
        return (cairo_output_stream_t *) &_cairo_output_stream_nil;
 
1881
    }
1501
1882
 
1502
1883
    _cairo_output_stream_init (&stream->base,
1503
1884
                               _string_array_stream_write,
1513
1894
 * surface we can render natively in PS. */
1514
1895
 
1515
1896
static cairo_status_t
1516
 
_cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
1517
 
            cairo_image_surface_t *image,
1518
 
            const char            *name)
 
1897
_cairo_ps_surface_flatten_image_transparency (cairo_ps_surface_t    *surface,
 
1898
                                              cairo_image_surface_t *image,
 
1899
                                              cairo_image_surface_t **opaque_image)
1519
1900
{
1520
 
    cairo_status_t status, status2;
1521
 
    unsigned char *rgb, *compressed;
1522
 
    unsigned long rgb_size, compressed_size;
 
1901
    const cairo_color_t *background_color;
1523
1902
    cairo_surface_t *opaque;
1524
 
    cairo_image_surface_t *opaque_image;
1525
1903
    cairo_pattern_union_t pattern;
 
1904
    cairo_status_t status;
 
1905
 
 
1906
    if (surface->content == CAIRO_CONTENT_COLOR_ALPHA)
 
1907
        background_color = CAIRO_COLOR_WHITE;
 
1908
    else
 
1909
        background_color = CAIRO_COLOR_BLACK;
 
1910
 
 
1911
    opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
 
1912
                                         image->width,
 
1913
                                         image->height);
 
1914
    if (opaque->status) {
 
1915
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1916
        return status;
 
1917
    }
 
1918
 
 
1919
    _cairo_pattern_init_for_surface (&pattern.surface, &image->base);
 
1920
 
 
1921
    status = _cairo_surface_fill_rectangle (opaque,
 
1922
                                            CAIRO_OPERATOR_SOURCE,
 
1923
                                            background_color,
 
1924
                                            0, 0,
 
1925
                                            image->width, image->height);
 
1926
    if (status)
 
1927
        goto fail;
 
1928
 
 
1929
    status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
 
1930
                                       &pattern.base,
 
1931
                                       NULL,
 
1932
                                       opaque,
 
1933
                                       0, 0,
 
1934
                                       0, 0,
 
1935
                                       0, 0,
 
1936
                                       image->width,
 
1937
                                       image->height);
 
1938
    if (status)
 
1939
        goto fail;
 
1940
 
 
1941
    _cairo_pattern_fini (&pattern.base);
 
1942
    *opaque_image = (cairo_image_surface_t *) opaque;
 
1943
 
 
1944
    return CAIRO_STATUS_SUCCESS;
 
1945
 
 
1946
fail:
 
1947
    _cairo_pattern_fini (&pattern.base);
 
1948
    cairo_surface_destroy (opaque);
 
1949
 
 
1950
    return status;
 
1951
}
 
1952
 
 
1953
static cairo_status_t
 
1954
_cairo_ps_surface_emit_base85_string (cairo_ps_surface_t    *surface,
 
1955
                                      unsigned char         *data,
 
1956
                                      unsigned long          length)
 
1957
{
 
1958
    cairo_output_stream_t *base85_stream, *string_array_stream;
 
1959
    cairo_status_t status, status2;
 
1960
 
 
1961
    string_array_stream = _string_array_stream_create (surface->stream);
 
1962
    status = _cairo_output_stream_get_status (string_array_stream);
 
1963
    if (status)
 
1964
        return status;
 
1965
 
 
1966
    base85_stream = _cairo_base85_stream_create (string_array_stream);
 
1967
    status = _cairo_output_stream_get_status (base85_stream);
 
1968
    if (status) {
 
1969
        status2 = _cairo_output_stream_destroy (string_array_stream);
 
1970
        return status;
 
1971
    }
 
1972
 
 
1973
    _cairo_output_stream_write (base85_stream, data, length);
 
1974
 
 
1975
    status = _cairo_output_stream_destroy (base85_stream);
 
1976
    status2 = _cairo_output_stream_destroy (string_array_stream);
 
1977
    if (status == CAIRO_STATUS_SUCCESS)
 
1978
        status = status2;
 
1979
 
 
1980
    return status;
 
1981
}
 
1982
 
 
1983
static cairo_status_t
 
1984
_cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
 
1985
                              cairo_image_surface_t *image,
 
1986
                              const char            *name,
 
1987
                              cairo_operator_t       op)
 
1988
{
 
1989
    cairo_status_t status;
 
1990
    unsigned char *rgb, *rgb_compressed;
 
1991
    unsigned long rgb_size, rgb_compressed_size;
 
1992
    unsigned char *mask = NULL, *mask_compressed = NULL;
 
1993
    unsigned long mask_size = 0, mask_compressed_size = 0;
 
1994
    cairo_image_surface_t *opaque_image = NULL;
1526
1995
    int x, y, i;
1527
 
    cairo_output_stream_t *base85_stream, *string_array_stream;
 
1996
    cairo_image_transparency_t transparency;
 
1997
    cairo_bool_t use_mask;
 
1998
 
 
1999
    if (image->base.status)
 
2000
        return image->base.status;
 
2001
 
 
2002
    status = _analyze_image_transparency (image, &transparency);
 
2003
    if (status)
 
2004
        return status;
1528
2005
 
1529
2006
    /* PostScript can not represent the alpha channel, so we blend the
1530
 
       current image over a white RGB surface to eliminate it. */
1531
 
 
1532
 
    if (image->base.status)
1533
 
        return image->base.status;
1534
 
 
1535
 
    if (image->format != CAIRO_FORMAT_RGB24) {
1536
 
        opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
1537
 
                                             image->width,
1538
 
                                             image->height);
1539
 
        if (opaque->status) {
1540
 
            status = CAIRO_STATUS_NO_MEMORY;
1541
 
            goto bail0;
1542
 
        }
1543
 
 
1544
 
        _cairo_pattern_init_for_surface (&pattern.surface, &image->base);
1545
 
 
1546
 
        status = _cairo_surface_fill_rectangle (opaque,
1547
 
                                                CAIRO_OPERATOR_SOURCE,
1548
 
                                                CAIRO_COLOR_WHITE,
1549
 
                                                0, 0,
1550
 
                                                image->width, image->height);
1551
 
        if (status) {
1552
 
            _cairo_pattern_fini (&pattern.base);
1553
 
            goto bail0;
1554
 
        }
1555
 
 
1556
 
        status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
1557
 
                                           &pattern.base,
1558
 
                                           NULL,
1559
 
                                           opaque,
1560
 
                                           0, 0,
1561
 
                                           0, 0,
1562
 
                                           0, 0,
1563
 
                                           image->width,
1564
 
                                           image->height);
1565
 
        if (status) {
1566
 
            _cairo_pattern_fini (&pattern.base);
1567
 
            goto bail0;
1568
 
        }
1569
 
 
1570
 
        _cairo_pattern_fini (&pattern.base);
1571
 
        opaque_image = (cairo_image_surface_t *) opaque;
1572
 
    } else {
1573
 
        opaque = &image->base;
 
2007
       current image over a white (or black for CONTENT_COLOR
 
2008
       surfaces) RGB surface to eliminate it. */
 
2009
 
 
2010
    if (op == CAIRO_OPERATOR_SOURCE ||
 
2011
        transparency == CAIRO_IMAGE_HAS_ALPHA ||
 
2012
        (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA &&
 
2013
         surface->ps_level == CAIRO_PS_LEVEL_2)) {
 
2014
        _cairo_ps_surface_flatten_image_transparency (surface,
 
2015
                                                      image,
 
2016
                                                      &opaque_image);
 
2017
        use_mask = FALSE;
 
2018
    } else if (transparency == CAIRO_IMAGE_IS_OPAQUE) {
1574
2019
        opaque_image = image;
 
2020
        use_mask = FALSE;
 
2021
    } else {
 
2022
        use_mask = TRUE;
1575
2023
    }
1576
2024
 
1577
 
    rgb_size = 3 * opaque_image->width * opaque_image->height;
 
2025
    rgb_size = 3 * image->width * image->height;
1578
2026
    rgb = malloc (rgb_size);
1579
2027
    if (rgb == NULL) {
1580
 
        status = CAIRO_STATUS_NO_MEMORY;
 
2028
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1581
2029
        goto bail1;
1582
2030
    }
1583
2031
 
1584
 
    i = 0;
1585
 
    for (y = 0; y < opaque_image->height; y++) {
1586
 
        pixman_bits_t *pixel = (pixman_bits_t *) (opaque_image->data + y * opaque_image->stride);
1587
 
        for (x = 0; x < opaque_image->width; x++, pixel++) {
1588
 
            rgb[i++] = (*pixel & 0x00ff0000) >> 16;
1589
 
            rgb[i++] = (*pixel & 0x0000ff00) >>  8;
1590
 
            rgb[i++] = (*pixel & 0x000000ff) >>  0;
 
2032
    if (use_mask) {
 
2033
        mask_size = (image->width * image->height + 7)/8;
 
2034
        mask = malloc (mask_size);
 
2035
        if (mask == NULL) {
 
2036
            status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
2037
            goto bail2;
 
2038
        }
 
2039
    }
 
2040
 
 
2041
    if (use_mask) {
 
2042
        int byte = 0;
 
2043
        int bit = 7;
 
2044
        i = 0;
 
2045
        for (y = 0; y < image->height; y++) {
 
2046
            uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
 
2047
            for (x = 0; x < image->width; x++, pixel++) {
 
2048
                if (bit == 7)
 
2049
                    mask[byte] = 0;
 
2050
                if (((*pixel & 0xff000000) >> 24) > 0x80)
 
2051
                    mask[byte] |= (1 << bit);
 
2052
                bit--;
 
2053
                if (bit < 0) {
 
2054
                    bit = 7;
 
2055
                    byte++;
 
2056
                }
 
2057
                rgb[i++] = (*pixel & 0x00ff0000) >> 16;
 
2058
                rgb[i++] = (*pixel & 0x0000ff00) >>  8;
 
2059
                rgb[i++] = (*pixel & 0x000000ff) >>  0;
 
2060
            }
 
2061
        }
 
2062
    } else {
 
2063
        i = 0;
 
2064
        for (y = 0; y < opaque_image->height; y++) {
 
2065
            uint32_t *pixel = (uint32_t *) (opaque_image->data + y * opaque_image->stride);
 
2066
            for (x = 0; x < opaque_image->width; x++, pixel++) {
 
2067
                rgb[i++] = (*pixel & 0x00ff0000) >> 16;
 
2068
                rgb[i++] = (*pixel & 0x0000ff00) >>  8;
 
2069
                rgb[i++] = (*pixel & 0x000000ff) >>  0;
 
2070
            }
1591
2071
        }
1592
2072
    }
1593
2073
 
1594
2074
    /* XXX: Should fix cairo-lzw to provide a stream-based interface
1595
2075
     * instead. */
1596
 
    compressed_size = rgb_size;
1597
 
    compressed = _cairo_lzw_compress (rgb, &compressed_size);
1598
 
    if (compressed == NULL) {
1599
 
        status = CAIRO_STATUS_NO_MEMORY;
1600
 
        goto bail2;
 
2076
    rgb_compressed_size = rgb_size;
 
2077
    rgb_compressed = _cairo_lzw_compress (rgb, &rgb_compressed_size);
 
2078
    if (rgb_compressed == NULL) {
 
2079
        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
2080
        goto bail3;
1601
2081
    }
1602
2082
 
1603
2083
    /* First emit the image data as a base85-encoded string which will
1605
2085
    _cairo_output_stream_printf (surface->stream,
1606
2086
                                 "/%sData [\n", name);
1607
2087
 
1608
 
    string_array_stream = _string_array_stream_create (surface->stream);
1609
 
    base85_stream = _cairo_base85_stream_create (string_array_stream);
1610
 
 
1611
 
    _cairo_output_stream_write (base85_stream, compressed, compressed_size);
1612
 
 
1613
 
    status = _cairo_output_stream_destroy (base85_stream);
1614
 
    status2 = _cairo_output_stream_destroy (string_array_stream);
1615
 
    if (status == CAIRO_STATUS_SUCCESS)
1616
 
        status = status2;
 
2088
    status = _cairo_ps_surface_emit_base85_string (surface,
 
2089
                                                   rgb_compressed,
 
2090
                                                   rgb_compressed_size);
1617
2091
    if (status)
1618
 
        goto bail3;
 
2092
        goto bail4;
1619
2093
 
1620
2094
    _cairo_output_stream_printf (surface->stream,
1621
2095
                                 "] def\n");
1622
2096
    _cairo_output_stream_printf (surface->stream,
1623
2097
                                 "/%sDataIndex 0 def\n", name);
1624
2098
 
1625
 
    _cairo_output_stream_printf (surface->stream,
1626
 
                                 "/%s {\n"
1627
 
                                 "    /DeviceRGB setcolorspace\n"
1628
 
                                 "    <<\n"
1629
 
                                 "      /ImageType 1\n"
1630
 
                                 "      /Width %d\n"
1631
 
                                 "      /Height %d\n"
1632
 
                                 "      /BitsPerComponent 8\n"
1633
 
                                 "      /Decode [ 0 1 0 1 0 1 ]\n"
1634
 
                                 "      /DataSource {\n"
1635
 
                                 "          %sData %sDataIndex get\n"
1636
 
                                 "          /%sDataIndex %sDataIndex 1 add def\n"
1637
 
                                 "          %sDataIndex %sData length 1 sub gt { /%sDataIndex 0 def } if\n"
1638
 
                                 "      } /ASCII85Decode filter /LZWDecode filter\n"
1639
 
                                 "      /ImageMatrix [ 1 0 0 1 0 0 ]\n"
1640
 
                                 "    >>\n"
1641
 
                                 "    image\n"
1642
 
                                 "} def\n",
1643
 
                                 name,
1644
 
                                 opaque_image->width,
1645
 
                                 opaque_image->height,
1646
 
                                 name, name, name, name, name, name, name);
 
2099
    /* Emit the mask data as a base85-encoded string which will
 
2100
     * be used as the mask source for the image operator later. */
 
2101
    if (mask) {
 
2102
        mask_compressed_size = mask_size;
 
2103
        mask_compressed = _cairo_lzw_compress (mask, &mask_compressed_size);
 
2104
        if (mask_compressed == NULL) {
 
2105
            status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
2106
            goto bail4;
 
2107
        }
 
2108
 
 
2109
        _cairo_output_stream_printf (surface->stream,
 
2110
                                     "/%sMask [\n", name);
 
2111
 
 
2112
        status = _cairo_ps_surface_emit_base85_string (surface,
 
2113
                                                       mask_compressed,
 
2114
                                                       mask_compressed_size);
 
2115
        if (status)
 
2116
            goto bail5;
 
2117
 
 
2118
        _cairo_output_stream_printf (surface->stream,
 
2119
                                     "] def\n");
 
2120
        _cairo_output_stream_printf (surface->stream,
 
2121
                                     "/%sMaskIndex 0 def\n", name);
 
2122
    }
 
2123
 
 
2124
    if (mask) {
 
2125
        _cairo_output_stream_printf (surface->stream,
 
2126
                                     "/%s {\n"
 
2127
                                     "    /DeviceRGB setcolorspace\n"
 
2128
                                     "    <<\n"
 
2129
                                     "  /ImageType 3\n"
 
2130
                                     "  /InterleaveType 3\n"
 
2131
                                     "  /DataDict <<\n"
 
2132
                                     "          /ImageType 1\n"
 
2133
                                     "          /Width %d\n"
 
2134
                                     "          /Height %d\n"
 
2135
                                     "          /BitsPerComponent 8\n"
 
2136
                                     "          /Decode [ 0 1 0 1 0 1 ]\n"
 
2137
                                     "          /DataSource {\n"
 
2138
                                     "                  %sData %sDataIndex get\n"
 
2139
                                     "                  /%sDataIndex %sDataIndex 1 add def\n"
 
2140
                                     "                  %sDataIndex %sData length 1 sub gt { /%sDataIndex 0 def } if\n"
 
2141
                                     "          } /ASCII85Decode filter /LZWDecode filter\n"
 
2142
                                     "          /ImageMatrix [ 1 0 0 1 0 0 ]\n"
 
2143
                                     "  >>\n"
 
2144
                                     "  /MaskDict <<\n"
 
2145
                                     "          /ImageType 1\n"
 
2146
                                     "          /Width %d\n"
 
2147
                                     "          /Height %d\n"
 
2148
                                     "          /BitsPerComponent 1\n"
 
2149
                                     "          /Decode [ 1 0 ]\n"
 
2150
                                     "          /DataSource {\n"
 
2151
                                     "                  %sMask %sMaskIndex get\n"
 
2152
                                     "                  /%sMaskIndex %sMaskIndex 1 add def\n"
 
2153
                                     "                  %sMaskIndex %sMask length 1 sub gt { /%sMaskIndex 0 def } if\n"
 
2154
                                     "          } /ASCII85Decode filter /LZWDecode filter\n"
 
2155
                                     "          /ImageMatrix [ 1 0 0 1 0 0 ]\n"
 
2156
                                     "  >>\n"
 
2157
                                     "    >>\n"
 
2158
                                     "    image\n"
 
2159
                                     "} def\n",
 
2160
                                     name,
 
2161
                                     image->width,
 
2162
                                     image->height,
 
2163
                                     name, name, name, name, name, name, name,
 
2164
                                     image->width,
 
2165
                                     image->height,
 
2166
                                     name, name, name, name, name, name, name);
 
2167
    } else {
 
2168
        _cairo_output_stream_printf (surface->stream,
 
2169
                                     "/%s {\n"
 
2170
                                     "    /DeviceRGB setcolorspace\n"
 
2171
                                     "    <<\n"
 
2172
                                     "  /ImageType 1\n"
 
2173
                                     "  /Width %d\n"
 
2174
                                     "  /Height %d\n"
 
2175
                                     "  /BitsPerComponent 8\n"
 
2176
                                     "  /Decode [ 0 1 0 1 0 1 ]\n"
 
2177
                                     "  /DataSource {\n"
 
2178
                                     "      %sData %sDataIndex get\n"
 
2179
                                     "      /%sDataIndex %sDataIndex 1 add def\n"
 
2180
                                     "      %sDataIndex %sData length 1 sub gt { /%sDataIndex 0 def } if\n"
 
2181
                                     "  } /ASCII85Decode filter /LZWDecode filter\n"
 
2182
                                     "  /ImageMatrix [ 1 0 0 1 0 0 ]\n"
 
2183
                                     "    >>\n"
 
2184
                                     "    image\n"
 
2185
                                     "} def\n",
 
2186
                                     name,
 
2187
                                     opaque_image->width,
 
2188
                                     opaque_image->height,
 
2189
                                     name, name, name, name, name, name, name);
 
2190
    }
1647
2191
 
1648
2192
    status = CAIRO_STATUS_SUCCESS;
1649
2193
 
1650
 
 bail3:
1651
 
    free (compressed);
1652
 
 bail2:
 
2194
bail5:
 
2195
    if (use_mask)
 
2196
        free (mask_compressed);
 
2197
bail4:
 
2198
    free (rgb_compressed);
 
2199
 
 
2200
bail3:
 
2201
    if (use_mask)
 
2202
        free (mask);
 
2203
bail2:
1653
2204
    free (rgb);
1654
 
 bail1:
1655
 
    if (opaque_image != image)
1656
 
        cairo_surface_destroy (opaque);
1657
 
 bail0:
1658
 
    return status;
1659
 
}
1660
 
 
1661
 
static void
1662
 
_cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
1663
 
                    cairo_solid_pattern_t *pattern)
1664
 
{
1665
 
    if (color_is_gray (&pattern->color))
 
2205
 
 
2206
bail1:
 
2207
    if (!use_mask && opaque_image != image)
 
2208
        cairo_surface_destroy (&opaque_image->base);
 
2209
 
 
2210
    return status;
 
2211
}
 
2212
 
 
2213
static cairo_status_t
 
2214
_cairo_ps_surface_emit_image_surface (cairo_ps_surface_t      *surface,
 
2215
                                      cairo_surface_pattern_t *pattern,
 
2216
                                      int                     *width,
 
2217
                                      int                     *height,
 
2218
                                      cairo_operator_t         op)
 
2219
{
 
2220
    cairo_image_surface_t  *image;
 
2221
    void                   *image_extra;
 
2222
    cairo_status_t          status;
 
2223
 
 
2224
    status = _cairo_surface_acquire_source_image (pattern->surface,
 
2225
                                                  &image,
 
2226
                                                  &image_extra);
 
2227
    if (status)
 
2228
        return status;
 
2229
 
 
2230
    _cairo_ps_surface_emit_image (surface, image, "CairoPattern", op);
 
2231
    if (status)
 
2232
        goto fail;
 
2233
 
 
2234
    *width = image->width;
 
2235
    *height = image->height;
 
2236
 
 
2237
fail:
 
2238
    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
2239
 
 
2240
    return status;
 
2241
}
 
2242
 
 
2243
static cairo_status_t
 
2244
_cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t  *surface,
 
2245
                                     cairo_surface_t      *meta_surface)
 
2246
{
 
2247
    double old_width, old_height;
 
2248
    cairo_content_t old_content;
 
2249
    cairo_rectangle_int_t meta_extents;
 
2250
    cairo_status_t status;
 
2251
 
 
2252
    status = _cairo_surface_get_extents (meta_surface, &meta_extents);
 
2253
    if (status)
 
2254
        return status;
 
2255
 
 
2256
    old_content = surface->content;
 
2257
    old_width = surface->width;
 
2258
    old_height = surface->height;
 
2259
    surface->width = meta_extents.width;
 
2260
    surface->height = meta_extents.height;
 
2261
    _cairo_output_stream_printf (surface->stream,
 
2262
                                 "/CairoPattern {\n"
 
2263
                                 "gsave\n");
 
2264
 
 
2265
    if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
 
2266
        surface->content = CAIRO_CONTENT_COLOR;
 
2267
        _cairo_output_stream_printf (surface->stream,
 
2268
                                     "0 G 0 0 %f %f rectfill\n",
 
2269
                                     surface->width,
 
2270
                                     surface->height);
 
2271
    }
 
2272
 
 
2273
    status = _cairo_meta_surface_replay (meta_surface, &surface->base);
 
2274
    if (status)
 
2275
        return status;
 
2276
 
 
2277
    _cairo_output_stream_printf (surface->stream,
 
2278
                                 "grestore\n"
 
2279
                                 "} bind def\n");
 
2280
    surface->content = old_content;
 
2281
    surface->width = old_width;
 
2282
    surface->height = old_height;
 
2283
 
 
2284
    return CAIRO_STATUS_SUCCESS;
 
2285
}
 
2286
 
 
2287
static void
 
2288
_cairo_ps_surface_flatten_transparency (cairo_ps_surface_t      *surface,
 
2289
                                        const cairo_color_t     *color,
 
2290
                                        double                  *red,
 
2291
                                        double                  *green,
 
2292
                                        double                  *blue)
 
2293
{
 
2294
    *red = color->red;
 
2295
    *green = color->green;
 
2296
    *blue = color->blue;
 
2297
 
 
2298
    if (!CAIRO_COLOR_IS_OPAQUE(color)) {
 
2299
        if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
 
2300
            uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8);
 
2301
 
 
2302
            *red   = ((color->red_short   >> 8) + one_minus_alpha) / 255.0;
 
2303
            *green = ((color->green_short >> 8) + one_minus_alpha) / 255.0;
 
2304
            *blue  = ((color->blue_short  >> 8) + one_minus_alpha) / 255.0;
 
2305
        } else {
 
2306
            *red   = (color->red_short   >> 8) / 255.0;
 
2307
            *green = (color->green_short >> 8) / 255.0;
 
2308
            *blue  = (color->blue_short  >> 8) / 255.0;
 
2309
        }
 
2310
    }
 
2311
}
 
2312
 
 
2313
static void
 
2314
_cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t    *surface,
 
2315
                                      cairo_solid_pattern_t *pattern)
 
2316
{
 
2317
    double red, green, blue;
 
2318
 
 
2319
    _cairo_ps_surface_flatten_transparency (surface, &pattern->color, &red, &green, &blue);
 
2320
 
 
2321
    if (color_is_gray (red, green, blue))
1666
2322
        _cairo_output_stream_printf (surface->stream,
1667
2323
                                     "%f G\n",
1668
 
                                     pattern->color.red);
 
2324
                                     red);
1669
2325
    else
1670
2326
        _cairo_output_stream_printf (surface->stream,
1671
2327
                                     "%f %f %f R\n",
1672
 
                                     pattern->color.red,
1673
 
                                     pattern->color.green,
1674
 
                                     pattern->color.blue);
 
2328
                                     red, green, blue);
1675
2329
}
1676
2330
 
1677
2331
static cairo_status_t
1678
 
_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
1679
 
                      cairo_surface_pattern_t *pattern)
 
2332
_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t      *surface,
 
2333
                                        cairo_surface_pattern_t *pattern,
 
2334
                                        cairo_operator_t         op)
1680
2335
{
1681
2336
    cairo_status_t status;
1682
 
    double bbox_width, bbox_height;
 
2337
    int pattern_width = 0; /* squelch bogus compiler warning */
 
2338
    int pattern_height = 0; /* squelch bogus compiler warning */
1683
2339
    double xstep, ystep;
1684
2340
    cairo_matrix_t inverse = pattern->base.matrix;
1685
2341
 
1688
2344
    assert (status == CAIRO_STATUS_SUCCESS);
1689
2345
 
1690
2346
    if (_cairo_surface_is_meta (pattern->surface)) {
1691
 
        _cairo_output_stream_printf (surface->stream, "/MyPattern {\n");
 
2347
        cairo_surface_t *meta_surface = pattern->surface;
 
2348
        cairo_rectangle_int_t pattern_extents;
1692
2349
 
1693
 
        status = _cairo_meta_surface_replay (pattern->surface, &surface->base);
 
2350
        status = _cairo_ps_surface_emit_meta_surface (surface,
 
2351
                                                      meta_surface);
 
2352
        status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
1694
2353
        if (status)
1695
2354
            return status;
1696
 
 
1697
 
        bbox_width = surface->width;
1698
 
        bbox_height = surface->height;
1699
 
        xstep = surface->width;
1700
 
        ystep = surface->height;
1701
 
        _cairo_output_stream_printf (surface->stream, "} bind def\n");
 
2355
        pattern_width = pattern_extents.width;
 
2356
        pattern_height = pattern_extents.height;
1702
2357
    } else {
1703
 
        cairo_image_surface_t   *image;
1704
 
        void                    *image_extra;
1705
 
        cairo_status_t          status;
1706
 
 
1707
 
        status = _cairo_surface_acquire_source_image (pattern->surface,
1708
 
                                                      &image,
1709
 
                                                      &image_extra);
1710
 
        assert (status == CAIRO_STATUS_SUCCESS);
1711
 
 
1712
 
        _cairo_ps_surface_emit_image (surface, image, "MyPattern");
1713
 
 
1714
 
        bbox_width = image->width;
1715
 
        bbox_height = image->height;
1716
 
 
1717
 
        switch (pattern->base.extend) {
 
2358
        status = _cairo_ps_surface_emit_image_surface (surface,
 
2359
                                                       pattern,
 
2360
                                                       &pattern_width,
 
2361
                                                       &pattern_height,
 
2362
                                                       op);
 
2363
        if (status)
 
2364
            return status;
 
2365
    }
 
2366
 
 
2367
    switch (pattern->base.extend) {
1718
2368
        /* We implement EXTEND_PAD like EXTEND_NONE for now */
1719
 
        case CAIRO_EXTEND_PAD:
1720
 
        case CAIRO_EXTEND_NONE:
1721
 
        {
1722
 
            /* In PS/PDF, (as far as I can tell), all patterns are
1723
 
             * repeating. So we support cairo's EXTEND_NONE semantics
1724
 
             * by setting the repeat step size to a size large enough
1725
 
             * to guarantee that no more than a single occurrence will
1726
 
             * be visible.
1727
 
             *
1728
 
             * First, map the surface extents into pattern space (since
1729
 
             * xstep and ystep are in pattern space).  Then use an upper
1730
 
             * bound on the length of the diagonal of the pattern image
1731
 
             * and the surface as repeat size.  This guarantees to never
1732
 
             * repeat visibly.
1733
 
             */
1734
 
            double x1 = 0.0, y1 = 0.0;
1735
 
            double x2 = surface->width, y2 = surface->height;
1736
 
            _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
1737
 
                                                  &x1, &y1, &x2, &y2,
1738
 
                                                  NULL);
 
2369
    case CAIRO_EXTEND_PAD:
 
2370
    case CAIRO_EXTEND_NONE:
 
2371
    {
 
2372
        /* In PS/PDF, (as far as I can tell), all patterns are
 
2373
         * repeating. So we support cairo's EXTEND_NONE semantics
 
2374
         * by setting the repeat step size to a size large enough
 
2375
         * to guarantee that no more than a single occurrence will
 
2376
         * be visible.
 
2377
         *
 
2378
         * First, map the surface extents into pattern space (since
 
2379
         * xstep and ystep are in pattern space).  Then use an upper
 
2380
         * bound on the length of the diagonal of the pattern image
 
2381
         * and the surface as repeat size.  This guarantees to never
 
2382
         * repeat visibly.
 
2383
         */
 
2384
        double x1 = 0.0, y1 = 0.0;
 
2385
        double x2 = surface->width, y2 = surface->height;
 
2386
        _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
 
2387
                                              &x1, &y1, &x2, &y2,
 
2388
                                              NULL);
1739
2389
 
1740
 
            /* Rather than computing precise bounds of the union, just
1741
 
             * add the surface extents unconditionally. We only
1742
 
             * required an answer that's large enough, we don't really
1743
 
             * care if it's not as tight as possible.*/
1744
 
            xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
1745
 
                                  image->width + image->height);
1746
 
            break;
1747
 
        }
1748
 
        case CAIRO_EXTEND_REPEAT:
1749
 
        case CAIRO_EXTEND_REFLECT:
1750
 
            xstep = image->width;
1751
 
            ystep = image->height;
1752
 
            break;
 
2390
        /* Rather than computing precise bounds of the union, just
 
2391
         * add the surface extents unconditionally. We only
 
2392
         * required an answer that's large enough, we don't really
 
2393
         * care if it's not as tight as possible.*/
 
2394
        xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
 
2395
                              pattern_width + pattern_height);
 
2396
        break;
 
2397
    }
 
2398
    case CAIRO_EXTEND_REPEAT:
 
2399
    case CAIRO_EXTEND_REFLECT:
 
2400
        xstep = pattern_width;
 
2401
        ystep = pattern_height;
 
2402
        break;
1753
2403
        /* All the rest (if any) should have been analyzed away, so these
1754
2404
         * cases should be unreachable. */
1755
 
        default:
1756
 
            ASSERT_NOT_REACHED;
1757
 
            xstep = 0;
1758
 
            ystep = 0;
1759
 
        }
 
2405
    default:
 
2406
        ASSERT_NOT_REACHED;
 
2407
        xstep = 0;
 
2408
        ystep = 0;
 
2409
    }
1760
2410
 
1761
 
        _cairo_surface_release_source_image (pattern->surface, image,
1762
 
                                             image_extra);
1763
 
    }
1764
2411
    _cairo_output_stream_printf (surface->stream,
1765
2412
                                 "<< /PatternType 1\n"
1766
2413
                                 "   /PaintType 1\n"
1767
2414
                                 "   /TilingType 1\n");
1768
2415
    _cairo_output_stream_printf (surface->stream,
1769
 
                                 "   /BBox [0 0 %f %f]\n",
1770
 
                                 bbox_width, bbox_height);
 
2416
                                 "   /BBox [0 0 %d %d]\n",
 
2417
                                 pattern_width, pattern_height);
1771
2418
    _cairo_output_stream_printf (surface->stream,
1772
2419
                                 "   /XStep %f /YStep %f\n",
1773
2420
                                 xstep, ystep);
1774
2421
    _cairo_output_stream_printf (surface->stream,
1775
 
                                 "   /PaintProc { MyPattern } bind\n"
1776
 
                                 ">>\n");
1777
 
    _cairo_output_stream_printf (surface->stream,
1778
 
                                 "[ %f %f %f %f %f %f ]\n",
1779
 
                                 inverse.xx, inverse.yx,
1780
 
                                 inverse.xy, inverse.yy,
1781
 
                                 inverse.x0, inverse.y0);
1782
 
    _cairo_output_stream_printf (surface->stream,
1783
 
                                 "makepattern setpattern\n");
1784
 
 
1785
 
    return CAIRO_STATUS_SUCCESS;
1786
 
}
1787
 
 
1788
 
static void
1789
 
_cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface,
1790
 
                     cairo_linear_pattern_t *pattern)
1791
 
{
1792
 
    /* XXX: NYI */
1793
 
}
1794
 
 
1795
 
static void
1796
 
_cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
1797
 
                     cairo_radial_pattern_t *pattern)
1798
 
{
1799
 
    /* XXX: NYI */
1800
 
}
1801
 
 
1802
 
static cairo_status_t
1803
 
_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
 
2422
                                 "   /PaintProc { CairoPattern } bind\n"
 
2423
                                 ">>\n");
 
2424
    _cairo_output_stream_printf (surface->stream,
 
2425
                                 "[ %f %f %f %f %f %f ]\n",
 
2426
                                 inverse.xx, inverse.yx,
 
2427
                                 inverse.xy, inverse.yy,
 
2428
                                 inverse.x0, inverse.y0);
 
2429
    _cairo_output_stream_printf (surface->stream,
 
2430
                                 "makepattern setpattern\n");
 
2431
 
 
2432
    return CAIRO_STATUS_SUCCESS;
 
2433
}
 
2434
 
 
2435
typedef struct _cairo_ps_color_stop {
 
2436
    double offset;
 
2437
    double color[3];
 
2438
} cairo_ps_color_stop_t;
 
2439
 
 
2440
static void
 
2441
_cairo_ps_surface_emit_linear_colorgradient (cairo_ps_surface_t     *surface,
 
2442
                                             cairo_ps_color_stop_t  *stop1,
 
2443
                                             cairo_ps_color_stop_t  *stop2)
 
2444
{
 
2445
    _cairo_output_stream_printf (surface->stream,
 
2446
                                 "<< /FunctionType 2\n"
 
2447
                                 "   /Domain [ 0 1 ]\n"
 
2448
                                 "   /C0 [ %f %f %f ]\n"
 
2449
                                 "   /C1 [ %f %f %f ]\n"
 
2450
                                 "   /N 1\n"
 
2451
                                 ">>\n",
 
2452
                                 stop1->color[0],
 
2453
                                 stop1->color[1],
 
2454
                                 stop1->color[2],
 
2455
                                 stop2->color[0],
 
2456
                                 stop2->color[1],
 
2457
                                 stop2->color[2]);
 
2458
}
 
2459
 
 
2460
static void
 
2461
_cairo_ps_surface_emit_stitched_colorgradient (cairo_ps_surface_t    *surface,
 
2462
                                               unsigned int           n_stops,
 
2463
                                               cairo_ps_color_stop_t  stops[])
 
2464
{
 
2465
    unsigned int i;
 
2466
 
 
2467
    _cairo_output_stream_printf (surface->stream,
 
2468
                                 "      << /FunctionType 3\n"
 
2469
                                 "         /Domain [ 0 1 ]\n"
 
2470
                                 "         /Functions [\n");
 
2471
    for (i = 0; i < n_stops - 1; i++)
 
2472
        _cairo_ps_surface_emit_linear_colorgradient (surface, &stops[i], &stops[i+1]);
 
2473
 
 
2474
    _cairo_output_stream_printf (surface->stream, "         ]\n");
 
2475
 
 
2476
    _cairo_output_stream_printf (surface->stream, "         /Bounds [ ");
 
2477
    for (i = 1; i < n_stops-1; i++)
 
2478
        _cairo_output_stream_printf (surface->stream, "%f ", stops[i].offset);
 
2479
    _cairo_output_stream_printf (surface->stream, "]\n");
 
2480
 
 
2481
    _cairo_output_stream_printf (surface->stream, "         /Encode [ ");
 
2482
    for (i = 1; i < n_stops; i++)
 
2483
        _cairo_output_stream_printf (surface->stream, "0 1 ");
 
2484
    _cairo_output_stream_printf (surface->stream,  "]\n");
 
2485
 
 
2486
    _cairo_output_stream_printf (surface->stream, "      >>\n");
 
2487
}
 
2488
 
 
2489
#define COLOR_STOP_EPSILON 1e-6
 
2490
 
 
2491
static cairo_status_t
 
2492
_cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t       *surface,
 
2493
                                      cairo_gradient_pattern_t *pattern)
 
2494
{
 
2495
    cairo_ps_color_stop_t *allstops, *stops;
 
2496
    unsigned int i, n_stops;
 
2497
 
 
2498
    allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_ps_color_stop_t));
 
2499
    if (allstops == NULL)
 
2500
        return CAIRO_STATUS_NO_MEMORY;
 
2501
 
 
2502
    stops = &allstops[1];
 
2503
    n_stops = pattern->n_stops;
 
2504
 
 
2505
    for (i = 0; i < n_stops; i++) {
 
2506
        double red, green, blue;
 
2507
 
 
2508
        _cairo_ps_surface_flatten_transparency (surface,
 
2509
                                                &pattern->stops[i].color,
 
2510
                                                &red, &green, &blue);
 
2511
        stops[i].color[0] = red;
 
2512
        stops[i].color[1] = green;
 
2513
        stops[i].color[2] = blue;
 
2514
        stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
 
2515
    }
 
2516
 
 
2517
    /* make sure first offset is 0.0 and last offset is 1.0 */
 
2518
    if (stops[0].offset > COLOR_STOP_EPSILON) {
 
2519
        memcpy (allstops, stops, sizeof (cairo_ps_color_stop_t));
 
2520
        stops = allstops;
 
2521
        n_stops++;
 
2522
    }
 
2523
    stops[0].offset = 0.0;
 
2524
 
 
2525
    if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
 
2526
        memcpy (&stops[n_stops],
 
2527
                &stops[n_stops - 1],
 
2528
                sizeof (cairo_ps_color_stop_t));
 
2529
        n_stops++;
 
2530
    }
 
2531
    stops[n_stops-1].offset = 1.0;
 
2532
 
 
2533
    if (n_stops == 2) {
 
2534
        /* no need for stitched function */
 
2535
        _cairo_ps_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]);
 
2536
    } else {
 
2537
        /* multiple stops: stitch. XXX possible optimization: regulary spaced
 
2538
         * stops do not require stitching. XXX */
 
2539
        _cairo_ps_surface_emit_stitched_colorgradient (surface, n_stops,stops);
 
2540
    }
 
2541
 
 
2542
    free (allstops);
 
2543
 
 
2544
    return CAIRO_STATUS_SUCCESS;
 
2545
}
 
2546
 
 
2547
static cairo_status_t
 
2548
_cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t     *surface,
 
2549
                                       cairo_linear_pattern_t *pattern)
 
2550
{
 
2551
    double x1, y1, x2, y2;
 
2552
    cairo_extend_t extend;
 
2553
    cairo_status_t status;
 
2554
    cairo_matrix_t inverse = pattern->base.base.matrix;
 
2555
 
 
2556
    extend = cairo_pattern_get_extend (&pattern->base.base);
 
2557
 
 
2558
    status = cairo_matrix_invert (&inverse);
 
2559
    if (status)
 
2560
        return status;
 
2561
 
 
2562
    x1 = _cairo_fixed_to_double (pattern->p1.x);
 
2563
    y1 = _cairo_fixed_to_double (pattern->p1.y);
 
2564
    x2 = _cairo_fixed_to_double (pattern->p2.x);
 
2565
    y2 = _cairo_fixed_to_double (pattern->p2.y);
 
2566
 
 
2567
    _cairo_output_stream_printf (surface->stream,
 
2568
                                 "<< /PatternType 2\n"
 
2569
                                 "   /Shading\n"
 
2570
                                 "   << /ShadingType 2\n"
 
2571
                                 "      /ColorSpace /DeviceRGB\n"
 
2572
                                 "      /Coords [ %f %f %f %f ]\n"
 
2573
                                 "      /Function\n",
 
2574
                                 x1, y1, x2, y2);
 
2575
 
 
2576
    status = _cairo_ps_surface_emit_pattern_stops (surface, &pattern->base);
 
2577
    if (status)
 
2578
        return status;
 
2579
 
 
2580
    if (extend == CAIRO_EXTEND_PAD) {
 
2581
        _cairo_output_stream_printf (surface->stream,
 
2582
                                     "      /Extend [ true true ]\r\n");
 
2583
    } else {
 
2584
        _cairo_output_stream_printf (surface->stream,
 
2585
                                     "      /Extend [ false false ]\r\n");
 
2586
    }
 
2587
 
 
2588
    _cairo_output_stream_printf (surface->stream,
 
2589
                                 "   >>\n"
 
2590
                                 ">>\n");
 
2591
    _cairo_output_stream_printf (surface->stream,
 
2592
                                 "[ %f %f %f %f %f %f ]\n",
 
2593
                                 inverse.xx, inverse.yx,
 
2594
                                 inverse.xy, inverse.yy,
 
2595
                                 inverse.x0, inverse.y0);
 
2596
    _cairo_output_stream_printf (surface->stream,
 
2597
                                 "makepattern setpattern\n");
 
2598
 
 
2599
    return status;
 
2600
}
 
2601
 
 
2602
static cairo_status_t
 
2603
_cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t     *surface,
 
2604
                                       cairo_radial_pattern_t *pattern)
 
2605
{
 
2606
    double x1, y1, x2, y2, r1, r2;
 
2607
    cairo_extend_t extend;
 
2608
    cairo_status_t status;
 
2609
    cairo_matrix_t inverse = pattern->base.base.matrix;
 
2610
 
 
2611
    extend = cairo_pattern_get_extend (&pattern->base.base);
 
2612
 
 
2613
    status = cairo_matrix_invert (&inverse);
 
2614
    if (status)
 
2615
        return status;
 
2616
 
 
2617
    x1 = _cairo_fixed_to_double (pattern->c1.x);
 
2618
    y1 = _cairo_fixed_to_double (pattern->c1.y);
 
2619
    r1 = _cairo_fixed_to_double (pattern->r1);
 
2620
    x2 = _cairo_fixed_to_double (pattern->c2.x);
 
2621
    y2 = _cairo_fixed_to_double (pattern->c2.y);
 
2622
    r2 = _cairo_fixed_to_double (pattern->r2);
 
2623
 
 
2624
    _cairo_output_stream_printf (surface->stream,
 
2625
                                 "<< /PatternType 2\n"
 
2626
                                 "   /Shading\n"
 
2627
                                 "   << /ShadingType 3\n"
 
2628
                                 "      /ColorSpace /DeviceRGB\n"
 
2629
                                 "      /Coords [ %f %f %f %f %f %f ]\n"
 
2630
                                 "      /Function\n",
 
2631
                                 x1, y1, r1, x2, y2, r2);
 
2632
 
 
2633
    status = _cairo_ps_surface_emit_pattern_stops (surface, &pattern->base);
 
2634
    if (status)
 
2635
        return status;
 
2636
 
 
2637
    if (extend == CAIRO_EXTEND_PAD) {
 
2638
        _cairo_output_stream_printf (surface->stream,
 
2639
                                     "      /Extend [ true true ]\r\n");
 
2640
    } else {
 
2641
        _cairo_output_stream_printf (surface->stream,
 
2642
                                     "      /Extend [ false false ]\r\n");
 
2643
    }
 
2644
 
 
2645
    _cairo_output_stream_printf (surface->stream,
 
2646
                                 "   >>\n"
 
2647
                                 ">>\n");
 
2648
    _cairo_output_stream_printf (surface->stream,
 
2649
                                 "[ %f %f %f %f %f %f ]\n",
 
2650
                                 inverse.xx, inverse.yx,
 
2651
                                 inverse.xy, inverse.yy,
 
2652
                                 inverse.x0, inverse.y0);
 
2653
    _cairo_output_stream_printf (surface->stream,
 
2654
                                 "makepattern setpattern\n");
 
2655
 
 
2656
    return status;
 
2657
}
 
2658
 
 
2659
static cairo_status_t
 
2660
_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
 
2661
                                cairo_pattern_t *pattern,
 
2662
                                cairo_operator_t op)
1804
2663
{
1805
2664
    /* FIXME: We should keep track of what pattern is currently set in
1806
2665
     * the postscript file and only emit code if we're setting a
1814
2673
 
1815
2674
    case CAIRO_PATTERN_TYPE_SURFACE:
1816
2675
        status = _cairo_ps_surface_emit_surface_pattern (surface,
1817
 
                                                         (cairo_surface_pattern_t *) pattern);
 
2676
                                                         (cairo_surface_pattern_t *) pattern,
 
2677
                                                         op);
1818
2678
        if (status)
1819
2679
            return status;
1820
2680
        break;
1846
2706
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
1847
2707
        return CAIRO_STATUS_SUCCESS;
1848
2708
 
 
2709
#if DEBUG_PS
1849
2710
    _cairo_output_stream_printf (stream,
1850
2711
                                 "%% _cairo_ps_surface_intersect_clip_path\n");
 
2712
#endif
1851
2713
 
1852
2714
    if (path == NULL) {
1853
 
        _cairo_output_stream_printf (stream, "initclip\n");
 
2715
        _cairo_output_stream_printf (stream, "grestore gsave\n");
1854
2716
        return CAIRO_STATUS_SUCCESS;
1855
2717
    }
1856
2718
 
1878
2740
 
1879
2741
static cairo_int_status_t
1880
2742
_cairo_ps_surface_get_extents (void                    *abstract_surface,
1881
 
                               cairo_rectangle_int16_t *rectangle)
 
2743
                               cairo_rectangle_int_t   *rectangle)
1882
2744
{
1883
2745
    cairo_ps_surface_t *surface = abstract_surface;
1884
2746
 
1913
2775
{
1914
2776
    cairo_ps_surface_t *surface = abstract_surface;
1915
2777
    cairo_output_stream_t *stream = surface->stream;
1916
 
    cairo_rectangle_int16_t extents, pattern_extents;
 
2778
    cairo_rectangle_int_t extents, pattern_extents;
1917
2779
    cairo_status_t status;
1918
2780
 
1919
2781
    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
1920
2782
        return _cairo_ps_surface_analyze_operation (surface, op, source);
1921
2783
 
1922
 
    /* XXX: It would be nice to be able to assert this condition
1923
 
     * here. But, we actually allow one 'cheat' that is used when
1924
 
     * painting the final image-based fallbacks. The final fallbacks
1925
 
     * do have alpha which we support by blending with white. This is
1926
 
     * possible only because there is nothing between the fallback
1927
 
     * images and the paper, nor is anything painted above. */
1928
 
    /*
1929
 
    assert (_cairo_ps_surface_operation_supported (op, source));
1930
 
    */
 
2784
    assert (_cairo_ps_surface_operation_supported (surface, op, source));
1931
2785
 
 
2786
#if DEBUG_PS
1932
2787
    _cairo_output_stream_printf (stream,
1933
2788
                                 "%% _cairo_ps_surface_paint\n");
 
2789
#endif
1934
2790
 
1935
2791
    status = _cairo_surface_get_extents (&surface->base, &extents);
1936
2792
    if (status)
1942
2798
 
1943
2799
    _cairo_rectangle_intersect (&extents, &pattern_extents);
1944
2800
 
1945
 
    status = _cairo_ps_surface_emit_pattern (surface, source);
 
2801
    status = _cairo_ps_surface_emit_pattern (surface, source, op);
1946
2802
    if (status)
1947
2803
        return status;
1948
2804
 
2017
2873
 
2018
2874
    assert (_cairo_ps_surface_operation_supported (surface, op, source));
2019
2875
 
2020
 
 
 
2876
#if DEBUG_PS
2021
2877
    _cairo_output_stream_printf (stream,
2022
2878
                                 "%% _cairo_ps_surface_stroke\n");
 
2879
#endif
2023
2880
 
2024
2881
    /* PostScript has "special needs" when it comes to zero-length
2025
2882
     * dash segments with butt caps. It apparently (at least
2037
2894
         * can modify some of the values.
2038
2895
         */
2039
2896
        if (num_dashes % 2) {
2040
 
            dash = malloc (2 * num_dashes * sizeof (double));
 
2897
            dash = _cairo_malloc_abc (num_dashes, 2, sizeof (double));
2041
2898
            if (dash == NULL)
2042
 
                return CAIRO_STATUS_NO_MEMORY;
 
2899
                return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2043
2900
 
2044
2901
            memcpy (dash, style->dash, num_dashes * sizeof (double));
2045
2902
            memcpy (dash + num_dashes, style->dash, num_dashes * sizeof (double));
2084
2941
        }
2085
2942
    }
2086
2943
 
2087
 
    _cairo_ps_surface_emit_pattern (surface, source);
 
2944
    status = _cairo_ps_surface_emit_pattern (surface, source, op);
 
2945
    if (status)
 
2946
        return status;
2088
2947
 
2089
2948
    _cairo_output_stream_printf (stream,
2090
2949
                                 "gsave\n");
2148
3007
 
2149
3008
    assert (_cairo_ps_surface_operation_supported (surface, op, source));
2150
3009
 
 
3010
#if DEBUG_PS
2151
3011
    _cairo_output_stream_printf (stream,
2152
3012
                                 "%% _cairo_ps_surface_fill\n");
 
3013
#endif
2153
3014
 
2154
 
    _cairo_ps_surface_emit_pattern (surface, source);
 
3015
    status = _cairo_ps_surface_emit_pattern (surface, source, op);
 
3016
    if (status)
 
3017
        return status;
2155
3018
 
2156
3019
    /* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */
2157
3020
    status = _cairo_ps_surface_emit_path (surface, stream, path,
2158
3021
                                          CAIRO_LINE_CAP_ROUND);
 
3022
    if (status)
 
3023
        return status;
2159
3024
 
2160
3025
    switch (fill_rule) {
2161
3026
    case CAIRO_FILL_RULE_WINDING:
2171
3036
    _cairo_output_stream_printf (stream,
2172
3037
                                 "%s\n", ps_operator);
2173
3038
 
2174
 
    return status;
 
3039
    return CAIRO_STATUS_SUCCESS;
2175
3040
}
2176
3041
 
2177
3042
/* This size keeps the length of the hex encoded string of glyphs
2206
3071
 
2207
3072
    assert (_cairo_ps_surface_operation_supported (surface, op, source));
2208
3073
 
 
3074
#if DEBUG_PS
2209
3075
    _cairo_output_stream_printf (stream,
2210
3076
                                 "%% _cairo_ps_surface_show_glyphs\n");
 
3077
#endif
2211
3078
 
2212
3079
    if (num_glyphs <= 0)
2213
3080
        return CAIRO_STATUS_SUCCESS;
2214
3081
 
2215
3082
    num_glyphs_unsigned = num_glyphs;
2216
3083
 
2217
 
    _cairo_ps_surface_emit_pattern (surface, source);
2218
 
    glyph_ids = malloc (num_glyphs_unsigned*sizeof (cairo_ps_glyph_id_t));
 
3084
    status = _cairo_ps_surface_emit_pattern (surface, source, op);
 
3085
    if (status)
 
3086
        return status;
 
3087
 
 
3088
    glyph_ids = _cairo_malloc_ab (num_glyphs_unsigned, sizeof (cairo_ps_glyph_id_t));
2219
3089
    if (glyph_ids == NULL)
2220
 
        return CAIRO_STATUS_NO_MEMORY;
 
3090
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2221
3091
 
2222
3092
    for (i = 0; i < num_glyphs_unsigned; i++) {
2223
3093
        status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
2233
3103
    while (i < num_glyphs_unsigned) {
2234
3104
        if (glyph_ids[i].subset_id != current_subset_id) {
2235
3105
            _cairo_output_stream_printf (surface->stream,
2236
 
                                         "/CairoFont-%d-%d findfont\n"
2237
 
                                         "[ %f %f %f %f 0 0 ] makefont\n"
2238
 
                                         "setfont\n",
 
3106
                                         "/CairoFont-%d-%d "
 
3107
                                         "[ %f %f %f %f 0 0 ] selectfont\n",
2239
3108
                                         subset_glyph.font_id,
2240
3109
                                         glyph_ids[i].subset_id,
2241
3110
                                         scaled_font->scale.xx,
2272
3141
            _cairo_output_stream_printf (surface->stream, "<%02x> S\n", glyph_ids[i].glyph_id);
2273
3142
        } else {
2274
3143
            word_wrap = _word_wrap_stream_create (surface->stream, 79);
 
3144
            status = _cairo_output_stream_get_status (word_wrap);
 
3145
            if (status)
 
3146
                goto fail;
 
3147
 
2275
3148
            _cairo_output_stream_printf (word_wrap, "<");
2276
3149
            for (j = i; j < last+1; j++)
2277
3150
                _cairo_output_stream_printf (word_wrap, "%02x", glyph_ids[j].glyph_id);
2298
3171
            } else {
2299
3172
                for (j = i; j < last+1; j++) {
2300
3173
                    if (j == num_glyphs_unsigned - 1)
2301
 
                        _cairo_output_stream_printf (word_wrap, "0 ");
 
3174
                        _cairo_output_stream_printf (word_wrap, "0 0 ");
2302
3175
                    else
2303
3176
                        _cairo_output_stream_printf (word_wrap,
2304
3177
                                                     "%f %f ",
2331
3204
    surface->paginated_mode = paginated_mode;
2332
3205
}
2333
3206
 
 
3207
static cairo_int_status_t
 
3208
_cairo_ps_surface_set_bounding_box (void                *abstract_surface,
 
3209
                                    cairo_box_t         *bbox)
 
3210
{
 
3211
    cairo_ps_surface_t *surface = abstract_surface;
 
3212
    int i, num_comments;
 
3213
    char **comments;
 
3214
    int x1, y1, x2, y2;
 
3215
 
 
3216
    if (surface->eps) {
 
3217
        x1 = (int) floor (_cairo_fixed_to_double (bbox->p1.x));
 
3218
        y1 = (int) floor (surface->height - _cairo_fixed_to_double (bbox->p2.y));
 
3219
        x2 = (int) ceil (_cairo_fixed_to_double (bbox->p2.x));
 
3220
        y2 = (int) ceil (surface->height - _cairo_fixed_to_double (bbox->p1.y));
 
3221
    } else {
 
3222
        x1 = 0;
 
3223
        y1 = 0;
 
3224
        x2 = (int) ceil (surface->width);
 
3225
        y2 = (int) ceil (surface->height);
 
3226
    }
 
3227
 
 
3228
    _cairo_output_stream_printf (surface->stream,
 
3229
                                 "%%%%Page: %d %d\n",
 
3230
                                 surface->num_pages,
 
3231
                                 surface->num_pages);
 
3232
 
 
3233
    _cairo_output_stream_printf (surface->stream,
 
3234
                                 "%%%%BeginPageSetup\n");
 
3235
 
 
3236
    num_comments = _cairo_array_num_elements (&surface->dsc_page_setup_comments);
 
3237
    comments = _cairo_array_index (&surface->dsc_page_setup_comments, 0);
 
3238
    for (i = 0; i < num_comments; i++) {
 
3239
        _cairo_output_stream_printf (surface->stream,
 
3240
                                     "%s\n", comments[i]);
 
3241
        free (comments[i]);
 
3242
        comments[i] = NULL;
 
3243
    }
 
3244
    _cairo_array_truncate (&surface->dsc_page_setup_comments, 0);
 
3245
 
 
3246
    _cairo_output_stream_printf (surface->stream,
 
3247
                                 "%%%%PageBoundingBox: %d %d %d %d\n"
 
3248
                                 "gsave %f %f translate 1.0 -1.0 scale gsave\n",
 
3249
                                 x1, y1, x2, y2,
 
3250
                                 0.0, surface->height);
 
3251
 
 
3252
    _cairo_output_stream_printf (surface->stream,
 
3253
                                 "%%%%EndPageSetup\n");
 
3254
 
 
3255
    if (surface->num_pages == 1) {
 
3256
        surface->bbox_x1 = x1;
 
3257
        surface->bbox_y1 = y1;
 
3258
        surface->bbox_x2 = x2;
 
3259
        surface->bbox_y2 = y2;
 
3260
    } else {
 
3261
        if (x1 < surface->bbox_x1)
 
3262
            surface->bbox_x1 = x1;
 
3263
        if (y1 < surface->bbox_y1)
 
3264
            surface->bbox_y1 = y1;
 
3265
        if (x2 > surface->bbox_x2)
 
3266
            surface->bbox_x2 = x2;
 
3267
        if (y2 > surface->bbox_y2)
 
3268
            surface->bbox_y2 = y2;
 
3269
    }
 
3270
 
 
3271
    return _cairo_output_stream_get_status (surface->stream);
 
3272
}
 
3273
 
2334
3274
static const cairo_surface_backend_t cairo_ps_surface_backend = {
2335
3275
    CAIRO_SURFACE_TYPE_PS,
2336
 
    NULL, /* create_similar */
 
3276
    _cairo_ps_surface_create_similar,
2337
3277
    _cairo_ps_surface_finish,
2338
3278
    NULL, /* acquire_source_image */
2339
3279
    NULL, /* release_source_image */
2343
3283
    NULL, /* composite */
2344
3284
    NULL, /* fill_rectangles */
2345
3285
    NULL, /* composite_trapezoids */
2346
 
    _cairo_ps_surface_copy_page,
 
3286
    NULL, /* cairo_ps_surface_copy_page */
2347
3287
    _cairo_ps_surface_show_page,
2348
3288
    NULL, /* set_clip_region */
2349
3289
    _cairo_ps_surface_intersect_clip_path,
2367
3307
 
2368
3308
static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend = {
2369
3309
    _cairo_ps_surface_start_page,
2370
 
    _cairo_ps_surface_set_paginated_mode
 
3310
    _cairo_ps_surface_set_paginated_mode,
 
3311
    _cairo_ps_surface_set_bounding_box,
2371
3312
};