~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to src/gdevtifs.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
 
   All Rights Reserved.
3
 
  
4
 
   This software is provided AS-IS with no warranty, either express or
5
 
   implied.
6
 
 
7
 
   This software is distributed under license and may not be copied, modified
8
 
   or distributed except as expressly authorized under the terms of that
9
 
   license.  Refer to licensing information at http://www.artifex.com/
10
 
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11
 
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
 
*/
13
 
 
14
 
/* $Id: gdevtifs.c 8250 2007-09-25 13:31:24Z giles $ */
15
 
/* TIFF-writing substructure */
16
 
#include "stdio_.h"
17
 
#include "time_.h"
18
 
#include "gstypes.h"
19
 
#include "gscdefs.h"
20
 
#include "gdevprn.h"
21
 
#include "gdevtifs.h"
22
 
 
23
 
/*
24
 
 * Define the standard contents of a TIFF directory.
25
 
 * Clients may add more items, also sorted in increasing tag order.
26
 
 */
27
 
typedef struct TIFF_std_directory_entries_s {
28
 
    TIFF_dir_entry SubFileType;
29
 
    TIFF_dir_entry ImageWidth;
30
 
    TIFF_dir_entry ImageLength;
31
 
    TIFF_dir_entry StripOffsets;
32
 
    TIFF_dir_entry Orientation;
33
 
    TIFF_dir_entry RowsPerStrip;
34
 
    TIFF_dir_entry StripByteCounts;
35
 
    TIFF_dir_entry XResolution;
36
 
    TIFF_dir_entry YResolution;
37
 
    TIFF_dir_entry PlanarConfig;
38
 
    TIFF_dir_entry ResolutionUnit;
39
 
    TIFF_dir_entry PageNumber;
40
 
    TIFF_dir_entry Software;
41
 
    TIFF_dir_entry DateTime;
42
 
} TIFF_std_directory_entries;
43
 
 
44
 
/* Define values that follow the directory entries. */
45
 
typedef struct TIFF_std_directory_values_s {
46
 
    TIFF_ulong diroff;          /* offset to next directory */
47
 
    TIFF_ulong xresValue[2];    /* XResolution indirect value */
48
 
    TIFF_ulong yresValue[2];    /* YResolution indirect value */
49
 
#define maxSoftware 40
50
 
    char softwareValue[maxSoftware];    /* Software indirect value */
51
 
    char dateTimeValue[20];     /* DateTime indirect value */
52
 
} TIFF_std_directory_values;
53
 
static const TIFF_std_directory_entries std_entries_initial =
54
 
{
55
 
    {TIFFTAG_SubFileType, TIFF_LONG, 1, SubFileType_page},
56
 
    {TIFFTAG_ImageWidth, TIFF_LONG, 1},
57
 
    {TIFFTAG_ImageLength, TIFF_LONG, 1},
58
 
    {TIFFTAG_StripOffsets, TIFF_LONG, 1},
59
 
    {TIFFTAG_Orientation, TIFF_SHORT, 1, Orientation_top_left},
60
 
    {TIFFTAG_RowsPerStrip, TIFF_LONG, 1},
61
 
    {TIFFTAG_StripByteCounts, TIFF_LONG, 1},
62
 
    {TIFFTAG_XResolution, TIFF_RATIONAL | TIFF_INDIRECT, 1,
63
 
     offset_of(TIFF_std_directory_values, xresValue[0])},
64
 
    {TIFFTAG_YResolution, TIFF_RATIONAL | TIFF_INDIRECT, 1,
65
 
     offset_of(TIFF_std_directory_values, yresValue[0])},
66
 
    {TIFFTAG_PlanarConfig, TIFF_SHORT, 1, PlanarConfig_contig},
67
 
    {TIFFTAG_ResolutionUnit, TIFF_SHORT, 1, ResolutionUnit_inch},
68
 
    {TIFFTAG_PageNumber, TIFF_SHORT, 2},
69
 
    {TIFFTAG_Software, TIFF_ASCII | TIFF_INDIRECT, 0,
70
 
     offset_of(TIFF_std_directory_values, softwareValue[0])},
71
 
    {TIFFTAG_DateTime, TIFF_ASCII | TIFF_INDIRECT, 20,
72
 
     offset_of(TIFF_std_directory_values, dateTimeValue[0])}
73
 
};
74
 
static const TIFF_std_directory_values std_values_initial =
75
 
{
76
 
    0,
77
 
    {0, 1},
78
 
    {0, 1},
79
 
    {0},
80
 
    {0, 0}
81
 
};
82
 
 
83
 
/* Fix up tag values on big-endian machines if necessary. */
84
 
#if arch_is_big_endian
85
 
static void
86
 
tiff_fixup_tag(TIFF_dir_entry * dp)
87
 
{
88
 
    switch (dp->type) {
89
 
        case TIFF_SHORT:
90
 
        case TIFF_SSHORT:
91
 
            /* We may have two shorts packed into a TIFF_ulong. */
92
 
            dp->value = (dp->value << 16) + (dp->value >> 16);
93
 
            break;
94
 
        case TIFF_BYTE:
95
 
        case TIFF_SBYTE:
96
 
            dp->value <<= 24;
97
 
            break;
98
 
    }
99
 
}
100
 
#else
101
 
#  define tiff_fixup_tag(dp) DO_NOTHING
102
 
#endif
103
 
 
104
 
/* Begin a TIFF page. */
105
 
int
106
 
gdev_tiff_begin_page(gx_device_printer * pdev, gdev_tiff_state * tifs,
107
 
                     FILE * fp,
108
 
                     const TIFF_dir_entry * entries, int entry_count,
109
 
                     const byte * values, int value_size, long max_strip_size)
110
 
{
111
 
    gs_memory_t *mem = pdev->memory;
112
 
    TIFF_std_directory_entries std_entries;
113
 
    const TIFF_dir_entry *pse;
114
 
    const TIFF_dir_entry *pce;
115
 
    TIFF_dir_entry entry;
116
 
#define std_entry_count\
117
 
  (sizeof(TIFF_std_directory_entries) / sizeof(TIFF_dir_entry))
118
 
    int nse, nce, ntags;
119
 
    TIFF_std_directory_values std_values;
120
 
 
121
 
#define std_value_size sizeof(TIFF_std_directory_values)
122
 
 
123
 
    tifs->mem = mem;
124
 
    if (gdev_prn_file_is_new(pdev)) {
125
 
        /* This is a new file; write the TIFF header. */
126
 
        static const TIFF_header hdr = {
127
 
#if arch_is_big_endian
128
 
            TIFF_magic_big_endian,
129
 
#else
130
 
            TIFF_magic_little_endian,
131
 
#endif
132
 
            TIFF_version_value,
133
 
            sizeof(TIFF_header)
134
 
        };
135
 
 
136
 
        fwrite((const char *)&hdr, sizeof(hdr), 1, fp);
137
 
        tifs->prev_dir = 0;
138
 
    } else {                    /* Patch pointer to this directory from previous. */
139
 
        TIFF_ulong offset = (TIFF_ulong) tifs->dir_off;
140
 
 
141
 
        fseek(fp, tifs->prev_dir, SEEK_SET);
142
 
        fwrite((char *)&offset, sizeof(offset), 1, fp);
143
 
        fseek(fp, tifs->dir_off, SEEK_SET);
144
 
    }
145
 
 
146
 
    /* We're going to shuffle the two tag lists together. */
147
 
    /* Both lists are sorted; entries in the client list */
148
 
    /* replace entries with the same tag in the standard list. */
149
 
    for (ntags = 0, pse = (const TIFF_dir_entry *)&std_entries_initial,
150
 
         nse = std_entry_count, pce = entries, nce = entry_count;
151
 
         nse && nce; ++ntags
152
 
        ) {
153
 
        if (pse->tag < pce->tag)
154
 
            ++pse, --nse;
155
 
        else if (pce->tag < pse->tag)
156
 
            ++pce, --nce;
157
 
        else
158
 
            ++pse, --nse, ++pce, --nce;
159
 
    }
160
 
    ntags += nse + nce;
161
 
    tifs->ntags = ntags;
162
 
 
163
 
    /* Write count of tags in directory. */
164
 
    {
165
 
        TIFF_short dircount = ntags;
166
 
 
167
 
        fwrite((char *)&dircount, sizeof(dircount), 1, fp);
168
 
    }
169
 
    tifs->dir_off = ftell(fp);
170
 
 
171
 
    /* Fill in standard directory tags. */
172
 
    std_entries = std_entries_initial;
173
 
    std_values = std_values_initial;
174
 
    std_entries.ImageWidth.value = pdev->width;
175
 
    std_entries.ImageLength.value = pdev->height;
176
 
    if (max_strip_size == 0) {
177
 
        tifs->strip_count = 1;
178
 
        tifs->rows = pdev->height;
179
 
        std_entries.RowsPerStrip.value = pdev->height;
180
 
    } else {
181
 
        int max_strip_rows =
182
 
            max_strip_size / gdev_mem_bytes_per_scan_line((gx_device *)pdev);
183
 
        int rps = max(1, max_strip_rows);
184
 
 
185
 
        tifs->strip_count = (pdev->height + rps - 1) / rps;
186
 
        tifs->rows = rps;
187
 
        std_entries.RowsPerStrip.value = rps;
188
 
        std_entries.StripOffsets.count = tifs->strip_count;
189
 
        std_entries.StripByteCounts.count = tifs->strip_count;
190
 
    }
191
 
    tifs->StripOffsets = (TIFF_ulong *)gs_alloc_bytes(mem,
192
 
                    (tifs->strip_count)*2*sizeof(TIFF_ulong),
193
 
                    "gdev_tiff_begin_page(StripOffsets)");
194
 
    tifs->StripByteCounts = &(tifs->StripOffsets[tifs->strip_count]);
195
 
    if (tifs->StripOffsets == 0)
196
 
        return_error(gs_error_VMerror);
197
 
    std_entries.PageNumber.value = (TIFF_ulong) pdev->PageCount;
198
 
    std_values.xresValue[0] = (TIFF_ulong)pdev->x_pixels_per_inch;
199
 
    std_values.yresValue[0] = (TIFF_ulong)pdev->y_pixels_per_inch;
200
 
    {
201
 
        char revs[10];
202
 
 
203
 
        strncpy(std_values.softwareValue, gs_product, maxSoftware);
204
 
        std_values.softwareValue[maxSoftware - 1] = 0;
205
 
        sprintf(revs, " %1.2f", gs_revision / 100.0);
206
 
        strncat(std_values.softwareValue, revs,
207
 
                maxSoftware - strlen(std_values.softwareValue) - 1);
208
 
        std_entries.Software.count =
209
 
            strlen(std_values.softwareValue) + 1;
210
 
    }
211
 
    {
212
 
        struct tm tms;
213
 
        time_t t;
214
 
 
215
 
        time(&t);
216
 
        tms = *localtime(&t);
217
 
        sprintf(std_values.dateTimeValue,
218
 
                "%04d:%02d:%02d %02d:%02d:%02d",
219
 
                tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
220
 
                tms.tm_hour, tms.tm_min, tms.tm_sec);
221
 
    }
222
 
 
223
 
    /* Write the merged directory. */
224
 
    for (pse = (const TIFF_dir_entry *)&std_entries,
225
 
         nse = std_entry_count, pce = entries, nce = entry_count;
226
 
         nse || nce;
227
 
        ) {
228
 
        bool std;
229
 
 
230
 
        if (nce == 0 || (nse != 0 && pse->tag < pce->tag))
231
 
            std = true, entry = *pse++, --nse;
232
 
        else if (nse == 0 || (nce != 0 && pce->tag < pse->tag))
233
 
            std = false, entry = *pce++, --nce;
234
 
        else
235
 
            std = false, ++pse, --nse, entry = *pce++, --nce;
236
 
        if (entry.tag == TIFFTAG_StripOffsets)  {
237
 
            if (tifs->strip_count > 1) {
238
 
                tifs->offset_StripOffsets = tifs->dir_off +
239
 
                    (ntags * sizeof(TIFF_dir_entry)) + std_value_size + value_size;
240
 
                entry.value = tifs->offset_StripOffsets;
241
 
            } else {
242
 
                tifs->offset_StripOffsets = ftell(fp) +
243
 
                    offset_of(TIFF_dir_entry, value);
244
 
            }
245
 
        }
246
 
        if (entry.tag == TIFFTAG_StripByteCounts) {
247
 
            if (tifs->strip_count > 1) {
248
 
                tifs->offset_StripByteCounts = tifs->dir_off +
249
 
                    (ntags * sizeof(TIFF_dir_entry)) + std_value_size + value_size +
250
 
                    (sizeof(TIFF_ulong) * tifs->strip_count);
251
 
                entry.value = tifs->offset_StripByteCounts;
252
 
            } else {
253
 
                tifs->offset_StripByteCounts = ftell(fp) +
254
 
                    offset_of(TIFF_dir_entry, value);
255
 
            }
256
 
        }
257
 
        tiff_fixup_tag(&entry); /* don't fix up indirects */
258
 
        if (entry.type & TIFF_INDIRECT) {
259
 
            /* Fix up the offset for an indirect value. */
260
 
            entry.type -= TIFF_INDIRECT;
261
 
            entry.value +=
262
 
                tifs->dir_off + ntags * sizeof(TIFF_dir_entry) +
263
 
                (std ? 0 : std_value_size);
264
 
        }
265
 
        fwrite((char *)&entry, sizeof(entry), 1, fp);
266
 
    }
267
 
 
268
 
    /* Write the indirect values. */
269
 
    fwrite((const char *)&std_values, sizeof(std_values), 1, fp);
270
 
    fwrite((const char *)values, value_size, 1, fp);
271
 
    /* Write placeholders for the strip offsets. */
272
 
    fwrite(tifs->StripOffsets, sizeof(TIFF_ulong), 2 * tifs->strip_count, fp);
273
 
    tifs->strip_index = 0;
274
 
    tifs->StripOffsets[0] = ftell(fp);
275
 
    return 0;
276
 
}
277
 
 
278
 
/* End a TIFF strip. */
279
 
/* Record the size of the current strip, update the     */
280
 
/* start of the next strip  and bump the strip_index    */
281
 
int
282
 
gdev_tiff_end_strip(gdev_tiff_state * tifs, FILE * fp)
283
 
{
284
 
    TIFF_ulong strip_size;
285
 
    TIFF_ulong next_strip_start;
286
 
    int pad = 0;
287
 
 
288
 
    next_strip_start = (TIFF_ulong)ftell(fp);
289
 
    strip_size = next_strip_start - tifs->StripOffsets[tifs->strip_index];
290
 
    if (next_strip_start & 1) {
291
 
        next_strip_start++;     /* WORD alignment */
292
 
        fwrite(&pad, 1, 1, fp);
293
 
    }
294
 
    tifs->StripByteCounts[tifs->strip_index++] = strip_size;
295
 
    if (tifs->strip_index < tifs->strip_count)
296
 
        tifs->StripOffsets[tifs->strip_index] = next_strip_start;
297
 
    return 0;
298
 
}
299
 
 
300
 
/* End a TIFF page. */
301
 
int
302
 
gdev_tiff_end_page(gdev_tiff_state * tifs, FILE * fp)
303
 
{
304
 
    gs_memory_t *mem = tifs->mem;
305
 
    long dir_off = tifs->dir_off;
306
 
    int tags_size = tifs->ntags * sizeof(TIFF_dir_entry);
307
 
 
308
 
    tifs->prev_dir =
309
 
        dir_off + tags_size + offset_of(TIFF_std_directory_values, diroff);
310
 
    tifs->dir_off = ftell(fp);
311
 
    /* Patch strip byte counts and offsets values. */
312
 
    /* The offset in the file was determined at begin_page and may be indirect */
313
 
    fseek(fp, tifs->offset_StripOffsets, SEEK_SET);
314
 
    fwrite(tifs->StripOffsets, sizeof(TIFF_ulong), tifs->strip_count, fp);
315
 
    fseek(fp, tifs->offset_StripByteCounts, SEEK_SET);
316
 
    fwrite(tifs->StripByteCounts, sizeof(TIFF_ulong), tifs->strip_count, fp);
317
 
    gs_free_object(mem, tifs->StripOffsets, "gdev_tiff_begin_page(StripOffsets)");
318
 
    return 0;
319
 
}