~ubuntu-branches/debian/experimental/cups-filters/experimental

« back to all changes in this revision

Viewing changes to pdftopdf/P2PResources.cxx

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2012-07-22 18:57:32 UTC
  • mfrom: (1.1.17)
  • Revision ID: package-import@ubuntu.com-20120722185732-26kkte5p1lth3rt5
Tags: 1.0.20-0bzr1
* New upstream release
   - pdftops: Added another workaround for Kyocera printers: Some
     models get very slow on images which request interpolation,
     so now we remove the image interpolation requests by additional
     PostScript code only inserted for Kyocera printers (LP: #1026974).
   - Made the Poppler-based filters pdftopdf and pdftoopvp build with
     both Poppler 0.18.x and 0.20.x (Upstream bug #1055).
   - Fixes according to Coverity scan results (Upstream bug #1054).
   - Switched build system to autotools. This especially fixes several
     build problems in Gentoo. Also build-tested with CUPS 1.6.0b1.
   - Fixes for compatibility with clang/gcc-4.7.
   - textonly: Filter did not work as a pipe with copies=1 (Upstream bug
     #1032).
   - texttopdf: Avoid trimming the results of FcFontSort(), as this may
     miss some reasonable candidates under certain circumstances. BTW,
     fix passing a non-pointer as a pointer to "result" (Closes: #670055).
   - Corrected documentation. The option for the maximum image rendering
     resolution in pdftops is "pdftops-max-image-resolution", not
     "pdftops-max-image-resolution-default".
* debian/patches/fcfontsort-no-trim.patch: Removed, fixed upstream.
* debian/rules: Updated options for ./configure and make for the new autotools
  build system.
* debian/watch: Switched to bz2 upstream packages.
* debian/rules, debian/copyright, debian/cups-filters.docs: Updated for
  renamed documentation files.
* debian/control, debian/libfontembed1.install,
  debian/libfontembed-dev.install: Added new binary packages for libfontembed.
* debian/copyright: Updated for recent file additions, and rearrangement of
  directories.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 
3
 
Copyright (c) 2006-2007, BBR Inc.  All rights reserved.
4
 
 
5
 
Permission is hereby granted, free of charge, to any person obtaining
6
 
a copy of this software and associated documentation files (the
7
 
"Software"), to deal in the Software without restriction, including
8
 
without limitation the rights to use, copy, modify, merge, publish,
9
 
distribute, sublicense, and/or sell copies of the Software, and to
10
 
permit persons to whom the Software is furnished to do so, subject to
11
 
the following conditions:
12
 
 
13
 
The above copyright notice and this permission notice shall be included
14
 
in all copies or substantial portions of the Software.
15
 
 
16
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
 
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
 
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
 
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
 
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
 
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 
 
24
 
*/
25
 
/*
26
 
 P2PResources.cc
27
 
 pdftopdf resources dictionary
28
 
*/
29
 
 
30
 
#include <config.h>
31
 
#include <string.h>
32
 
#include "goo/gmem.h"
33
 
#include "P2PResources.h"
34
 
#include "P2PFont.h"
35
 
#include "P2PForm.h"
36
 
 
37
 
P2PResourceMap::P2PResourceMap()
38
 
{
39
 
  int i;
40
 
 
41
 
  for (i = 0;i < P2PResources::NDict;i++) {
42
 
    tables[i] = 0;
43
 
  }
44
 
}
45
 
 
46
 
P2PResourceMap::~P2PResourceMap()
47
 
{
48
 
  int i;
49
 
 
50
 
  for (i = 0;i < P2PResources::NDict;i++) {
51
 
    if (tables[i] != 0) {
52
 
      delete tables[i];
53
 
    }
54
 
  }
55
 
}
56
 
 
57
 
const char *P2PResources::dictNames[NDict] = {
58
 
  "ExtGState",
59
 
  "ColorSpace",
60
 
  "Pattern",
61
 
  "Shading",
62
 
  "XObject",
63
 
  "Font"
64
 
};
65
 
 
66
 
P2PResources::P2PResources(XRef *xrefA)
67
 
{
68
 
  int i;
69
 
 
70
 
  xref = xrefA;
71
 
  for (i = 0;i < NDict;i++) {
72
 
    dictionaries[i] = 0;
73
 
  }
74
 
  resourceNo = 0;
75
 
  patternDict = 0;
76
 
  nPattern = 0;
77
 
  fontResource = 0;
78
 
  oldForms = 0;
79
 
  nOldForms = 0;
80
 
}
81
 
 
82
 
P2PResources::~P2PResources()
83
 
{
84
 
  int i;
85
 
 
86
 
  for (i = 0;i < NDict;i++) {
87
 
    if (dictionaries[i] != 0) {
88
 
      delete dictionaries[i];
89
 
    }
90
 
  }
91
 
  if (patternDict != 0) delete[] patternDict;
92
 
  if (oldForms != 0) {
93
 
    for (i = 0;i < nOldForms;i++) {
94
 
      if (oldForms[i] != 0) delete oldForms[i];
95
 
    }
96
 
    delete[] oldForms;
97
 
  }
98
 
  /* fontResource is deleted in other Class,
99
 
     Don't delete it */
100
 
}
101
 
 
102
 
void P2PResources::output(P2POutputStream *str)
103
 
{
104
 
  int i;
105
 
  str->puts("<<");
106
 
 
107
 
  for (i = 0;i < NDict;i++) {
108
 
    if (i == Font && fontResource != 0 && fontResource->getNDicts() > 0) {
109
 
      str->printf(" /%s ",dictNames[i]);
110
 
      fontResource->output(str,xref);
111
 
      str->putchar('\n');
112
 
    } else if (i == Pattern) {
113
 
      if (nPattern > 0) {
114
 
        int j;
115
 
 
116
 
        str->printf(" /%s << ",dictNames[i]);
117
 
        for (j = 0;j < nPattern;j++) {
118
 
          if (patternDict[j].pattern != 0) {
119
 
            /* output body later */
120
 
            P2PXRef::put(patternDict[j].pattern);
121
 
            /* output refrence here */
122
 
            P2POutput::outputName(patternDict[j].name,str);
123
 
            str->putchar(' ');
124
 
            patternDict[j].pattern->outputRef(str);
125
 
            str->putchar('\n');
126
 
          }
127
 
        }
128
 
        str->puts(">>\n");
129
 
      }
130
 
    } else if (i == XObject && nOldForms > 0 && dictionaries[i] != 0) {
131
 
      int j;
132
 
 
133
 
      /* There is any old form in XObject dictionary */
134
 
      Dict *xobjDict = dictionaries[i];
135
 
      int n = xobjDict->getLength();
136
 
      str->printf(" /%s << ",dictNames[i]);
137
 
      for (j = 0;j < n;j++) {
138
 
        char *key = xobjDict->getKey(j);
139
 
 
140
 
        P2POutput::outputName(key,str);
141
 
        str->putchar(' ');
142
 
        if (j < nOldForms && oldForms[j] != 0) {
143
 
          P2PXRef::put(oldForms[j]);
144
 
          oldForms[j]->outputRef(str);
145
 
        } else {
146
 
          Object obj;
147
 
 
148
 
          xobjDict->getValNF(j,&obj);
149
 
          P2POutput::outputObject(&obj,str,xref);
150
 
          obj.free();
151
 
        }
152
 
        str->putchar('\n');
153
 
      }
154
 
      str->puts(">>\n");
155
 
    } else {
156
 
      if (dictionaries[i] != 0) {
157
 
        str->printf(" /%s ",dictNames[i]);
158
 
        P2POutput::outputDict(dictionaries[i],str,xref);
159
 
        str->putchar('\n');
160
 
      }
161
 
    }
162
 
  }
163
 
  /* output ProcSet */ 
164
 
  /* Notice: constant values */
165
 
  str->puts(" /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] ");
166
 
 
167
 
  /* Notice: no Properties */
168
 
 
169
 
  str->puts(">>");
170
 
}
171
 
 
172
 
void P2PResources::handleOldForm(P2PResourceMap *map)
173
 
{
174
 
  int n;
175
 
  int i;
176
 
 
177
 
  /* find Forms without Resources and replace them */
178
 
  Dict *xobjDict = dictionaries[XObject];
179
 
  if (xobjDict == 0) return;
180
 
  n = xobjDict->getLength();
181
 
  for (i = 0;i < n;i++) {
182
 
    Object xobj;
183
 
    Object obj;
184
 
    Dict *strDict;
185
 
    P2PForm *form;
186
 
 
187
 
    xobjDict->getVal(i,&xobj);
188
 
    if (!xobj.isStream()) {
189
 
        xobj.free();
190
 
        continue;
191
 
    }
192
 
    strDict = xobj.streamGetDict();
193
 
    strDict->lookupNF("Subtype",&obj);
194
 
    if (!obj.isName() || strcmp("Form",obj.getName()) != 0) {
195
 
        obj.free();
196
 
        xobj.free();
197
 
        continue;
198
 
    }
199
 
    obj.free();
200
 
    strDict->lookupNF("Resources",&obj);
201
 
    if (!obj.isNull()) {
202
 
        obj.free();
203
 
        xobj.free();
204
 
        continue;
205
 
    }
206
 
    if (nOldForms <= i || oldForms[i] == 0) {
207
 
      /* found a Form without Resource,
208
 
        replace it with a refrence to a P2PForm */
209
 
      form = new P2PForm(&xobj,this,map);
210
 
      xobj.free();
211
 
      if (nOldForms < n) {
212
 
          P2PObject **oldp = oldForms;
213
 
          oldForms = new P2PObject *[n];
214
 
          memset(oldForms,0,n*sizeof(P2PForm *));
215
 
          if (oldp != 0) {
216
 
              memcpy(oldForms,oldp,nOldForms*sizeof(P2PForm *));
217
 
          }
218
 
          nOldForms = n;
219
 
      }
220
 
      oldForms[i] = form;
221
 
    }
222
 
  }
223
 
}
224
 
 
225
 
P2PResourceMap *P2PResources::merge(Dict *res)
226
 
{
227
 
  P2PResourceMap *map = 0;
228
 
  Object obj;
229
 
  int i;
230
 
 
231
 
  if (res == 0) return 0;
232
 
  for (i = 0;i < NDict;i++) {
233
 
    if (res->lookup(const_cast<char *>(dictNames[i]),&obj) != 0
234
 
         && obj.isDict()) {
235
 
      if (map == 0) {
236
 
        map = new P2PResourceMap();
237
 
      }
238
 
      if (dictionaries[i] == 0) {
239
 
        dictionaries[i] = new Dict(xref);
240
 
      }
241
 
      if (map->tables[i] == 0) {
242
 
        map->tables[i] = new Dict((XRef *)0);
243
 
      }
244
 
      mergeOneDict(dictionaries[i],obj.getDict(),map->tables[i],i != Pattern);
245
 
      obj.free();
246
 
    }
247
 
  }
248
 
  handleOldForm(map);
249
 
  return map;
250
 
}
251
 
 
252
 
P2PResourceMap *P2PResources::merge(P2PResources *res)
253
 
{
254
 
  P2PResourceMap *map = 0;
255
 
  int i;
256
 
 
257
 
  for (i = 0;i < NDict;i++) {
258
 
    if (res->dictionaries[i] != 0) {
259
 
      if (map == 0) {
260
 
        map = new P2PResourceMap();
261
 
      }
262
 
      if (dictionaries[i] == 0) {
263
 
        dictionaries[i] = new Dict(xref);
264
 
      }
265
 
      if (map->tables[i] == 0) {
266
 
        map->tables[i] = new Dict((XRef *)0);
267
 
      }
268
 
      mergeOneDict(dictionaries[i],res->dictionaries[i],map->tables[i],
269
 
        i != Pattern);
270
 
    }
271
 
  }
272
 
  handleOldForm(map);
273
 
  return map;
274
 
}
275
 
 
276
 
void P2PResources::mergeOneDict(Dict *dst, Dict *src, Dict *map, GBool unify)
277
 
{
278
 
  int i,j;
279
 
  int srcn = src->getLength();
280
 
  int dstn;
281
 
 
282
 
  for (i = 0;i < srcn;i++) {
283
 
    Object srcobj;
284
 
    GBool found = gFalse;
285
 
#ifdef HAVE_UGOOSTRING_H
286
 
    UGooString *srckey;
287
 
#else
288
 
    char *srckey;
289
 
#endif
290
 
 
291
 
    src->getValNF(i,&srcobj);
292
 
    srckey = src->getKey(i);
293
 
    if (srcobj.isRef() && unify) {
294
 
      dstn = dst->getLength();
295
 
      for (j = 0;j < dstn;j++) {
296
 
        Object dstobj;
297
 
 
298
 
        dst->getValNF(j,&dstobj);
299
 
        if (dstobj.isRef() && srcobj.getRefNum() == dstobj.getRefNum()
300
 
          && srcobj.getRefGen() == dstobj.getRefGen()) {
301
 
          /* add to map */
302
 
#ifdef HAVE_UGOOSTRING_H
303
 
          addMap(srckey,dst->getKey(j)->getCString(),map);
304
 
#else
305
 
          addMap(srckey,dst->getKey(j),map);
306
 
#endif
307
 
          found = gTrue;
308
 
        }
309
 
        dstobj.free();
310
 
      }
311
 
    }
312
 
    if (!found) {
313
 
      /* add to dst */
314
 
      addDict(dst,&srcobj,srckey,map);
315
 
    } else {
316
 
      srcobj.free();
317
 
    }
318
 
  }
319
 
}
320
 
 
321
 
#ifdef HAVE_UGOOSTRING_H
322
 
void P2PResources::addDict(Dict *dict, Object *obj, 
323
 
  UGooString *srckey, Dict *map)
324
 
{
325
 
  char name[20];
326
 
  Object tobj;
327
 
 
328
 
  snprintf(name,20,"R%d",resourceNo++);
329
 
  dict->addOwnVal(name,obj);
330
 
  addMap(srckey,name,map);
331
 
}
332
 
#else
333
 
void P2PResources::addDict(Dict *dict, Object *obj, 
334
 
  char *srckey, Dict *map)
335
 
{
336
 
  char name[20];
337
 
  Object tobj;
338
 
 
339
 
  snprintf(name,20,"R%d",resourceNo++);
340
 
  dict->add(strdup(name),obj);
341
 
  addMap(srckey,name,map);
342
 
}
343
 
#endif
344
 
 
345
 
#ifdef HAVE_UGOOSTRING_H
346
 
void P2PResources::addMap(UGooString *org, char *mapped, Dict *map)
347
 
{
348
 
  Object obj;
349
 
 
350
 
  obj.initName(mapped);
351
 
  map->add(*org,&obj);
352
 
}
353
 
#else
354
 
void P2PResources::addMap(char *org, char *mapped, Dict *map)
355
 
{
356
 
  Object obj;
357
 
 
358
 
  obj.initName(mapped);
359
 
  map->add(strdup(org),&obj);
360
 
}
361
 
#endif
362
 
 
363
 
void P2PResources::setupPattern()
364
 
{
365
 
  int i;
366
 
 
367
 
  if (patternDict != NULL) {
368
 
    return;
369
 
  }
370
 
  if (dictionaries[Pattern] == 0) return;
371
 
  nPattern = dictionaries[Pattern]->getLength();
372
 
  patternDict = new P2PPatternDict[nPattern];
373
 
  /* setting names */
374
 
  for (i = 0;i < nPattern;i++) {
375
 
#ifdef HAVE_UGOOSTRING_H
376
 
    char *p = dictionaries[Pattern]->getKey(i)->getCString();
377
 
#else
378
 
    char *p = strdup(dictionaries[Pattern]->getKey(i));
379
 
#endif
380
 
    patternDict[i].name = p;
381
 
  }
382
 
}
383
 
 
384
 
void P2PResources::refPattern(char *name, P2PMatrix *matA)
385
 
{
386
 
  int i;
387
 
 
388
 
  if (dictionaries[Pattern] == 0) return; /* no pattern */
389
 
  for (i = 0;i < nPattern;i++) {
390
 
    if (strcmp(name,patternDict[i].name) == 0) {
391
 
      if (patternDict[i].pattern == 0) {
392
 
        Object patObj;
393
 
 
394
 
        dictionaries[Pattern]->lookupNF(name,&patObj);
395
 
        if (patObj.isRef() || patObj.isDict()) {
396
 
          patternDict[i].pattern = new P2PPattern(&patObj,xref,matA);
397
 
        }
398
 
        patObj.free();
399
 
      }
400
 
    }
401
 
  }
402
 
}