OSDN Git Service

updated with TeX Live 2014.
[putex/putex.git] / src / dvipdfmx-pu / src / spc_util.c
1 /*  
2     
3     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
4
5     Copyright (C) 2007-2012 by Jin-Hwan Cho and Shunsaku Hirata,
6     the dvipdfmx project team.
7     
8     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
9
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14     
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
19     
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 */
24
25 #if HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "system.h"
30 #include "mem.h"
31 #include "error.h"
32 #include "dpxutil.h"
33
34 #include "pdfdev.h"
35 #include "pdfparse.h"
36 #include "pdfcolor.h"
37 #include "pdfdraw.h"
38
39 #include "specials.h"
40
41 #include "spc_util.h"
42
43
44 #ifndef ISBLANK
45 #define ISBLANK(c) ((c) == ' ' || (c) == '\t')
46 #endif
47 static void
48 skip_blank (const char **pp, const char *endptr)
49 {
50   const char  *p = *pp;
51   for ( ; p < endptr && ISBLANK(*p); p++);
52   *pp = p;
53 }
54
55
56 /* From pdfcolor.c */
57 static int pdf_color_namedcolor (pdf_color *color, const char *colorname);
58
59 static int
60 spc_util_read_numbers (double *values, int num_values,
61                        struct spc_env *spe, struct spc_arg *args)
62 {
63   int   count;
64   char *q;
65
66   skip_blank(&args->curptr, args->endptr);
67   for (count = 0;
68        count < num_values &&
69        args->curptr < args->endptr; ) {
70     q = parse_float_decimal(&args->curptr, args->endptr);
71     if (!q)
72       break;
73     else {
74       values[count] = atof(q);
75       RELEASE(q);
76       skip_blank(&args->curptr, args->endptr);
77       count++;
78     }
79   }
80
81   return  count;
82 }
83
84 static void
85 rgb_color_from_hsv (pdf_color *color, double h, double s, double v)
86 {
87   double  r, g, b;
88   ASSERT( color );
89   r = g = b = v;
90   if (s != 0.0) {
91     double h6, f, v1, v2, v3;
92     int    i;
93     h6 = h * 6; /* 360 / 60 */
94     i  = (int) h6;
95     f  = h6 - i;
96     v1 = v * (1 - s);
97     v2 = v * (1 - s * f);
98     v3 = v * (1 - s * (1 - f));
99     switch (i) {
100     case  0: r = v ; g = v3; b = v1; break;
101     case  1: r = v2; g = v ; b = v1; break;
102     case  2: r = v1; g = v ; b = v3; break;
103     case  3: r = v1; g = v2; b = v ; break;
104     case  4: r = v3; g = v1; b = v ; break;
105     case  5: r = v ; g = v1; b = v2; break;
106     case  6: r = v ; g = v1; b = v2; break;
107     }
108   }
109   pdf_color_rgbcolor(color, r, g, b);
110 }
111
112 static int
113 spc_read_color_color (struct spc_env *spe, pdf_color *colorspec, struct spc_arg *ap)
114 {
115   char    *q;
116   double   cv[4];
117   int      nc;
118   int      error = 0;
119
120   q = parse_c_ident(&ap->curptr, ap->endptr);
121   if (!q) {
122     spc_warn(spe, "No valid color specified?");
123     return  -1;
124   }
125   skip_blank(&ap->curptr, ap->endptr);
126
127   if (!strcmp(q, "rgb")) { /* Handle rgb color */
128     nc = spc_util_read_numbers(cv, 3, spe, ap);
129     if (nc != 3) {
130       spc_warn(spe, "Invalid value for RGB color specification.");
131       error = -1;
132     } else {
133       pdf_color_rgbcolor(colorspec, cv[0], cv[1], cv[2]);
134     }
135   } else if (!strcmp(q, "cmyk")) { /* Handle cmyk color */
136     nc = spc_util_read_numbers(cv, 4, spe, ap);
137     if (nc != 4) {
138       spc_warn(spe, "Invalid value for CMYK color specification.");
139       error = -1;
140     } else {
141       pdf_color_cmykcolor(colorspec, cv[0], cv[1], cv[2], cv[3]);
142     }
143   } else if (!strcmp(q, "gray")) { /* Handle gray */
144     nc = spc_util_read_numbers(cv, 1, spe, ap);
145     if (nc != 1) {
146       spc_warn(spe, "Invalid value for gray color specification.");
147       error = -1;
148     } else {
149       pdf_color_graycolor(colorspec, cv[0]);
150     }
151   } else if (!strcmp(q, "hsb")) {
152     nc = spc_util_read_numbers(cv, 3, spe, ap);
153     if (nc != 3) {
154       spc_warn(spe, "Invalid value for HSB color specification.");
155       error = -1;
156     } else {
157       rgb_color_from_hsv(colorspec, cv[0], cv[1], cv[2]);
158       spc_warn(spe, "HSB color converted to RGB: hsb: <%g, %g, %g> ==> rgb: <%g, %g, %g>",
159                cv[0], cv[1], cv[2],
160                colorspec->values[0], colorspec->values[1], colorspec->values[2]);
161     }
162   } else { /* Must be a "named" color */
163     error = pdf_color_namedcolor(colorspec, q);
164     if (error)
165       spc_warn(spe, "Unrecognized color name: %s", q);
166   }
167   RELEASE(q);
168
169   return  error;
170 }
171
172 /* Argumaent for this is PDF_Number or PDF_Array.
173  * But we ignore that since we don't want to add
174  * dependency to pdfxxx and @foo can not be
175  * allowed for color specification. "pdf" here
176  * means pdf: special syntax.
177  */
178 static int
179 spc_read_color_pdf (struct spc_env *spe, pdf_color *colorspec, struct spc_arg *ap)
180 {
181   double  cv[4]; /* at most four */
182   int     nc, isarry = 0;
183   int     error = 0;
184   char   *q;
185
186   skip_blank(&ap->curptr, ap->endptr);
187
188   if (ap->curptr[0] == '[') {
189     ap->curptr++; skip_blank(&ap->curptr, ap->endptr);
190     isarry = 1;
191   }
192
193   nc = spc_util_read_numbers(cv, 4, spe, ap);
194   switch (nc) {
195   case  1:
196     pdf_color_graycolor(colorspec, cv[0]);
197     break;
198   case  3:
199     pdf_color_rgbcolor (colorspec, cv[0], cv[1], cv[2]);
200     break;
201   case  4:
202     pdf_color_cmykcolor(colorspec, cv[0], cv[1], cv[2], cv[3]);
203     break;
204   default:
205     /* Try to read the color names defined in dvipsname.def */
206     q = parse_c_ident(&ap->curptr, ap->endptr);
207     if (q) {
208       error = pdf_color_namedcolor(colorspec, q);
209       if (error)
210         spc_warn(spe, "Unrecognized color name: %s, keep the current color", q);
211       RELEASE(q);
212     } else {
213       error = -1;
214     }
215     break;
216   }
217
218   if (isarry) {
219     skip_blank(&ap->curptr, ap->endptr);
220     if (ap->curptr >= ap->endptr || ap->curptr[0] != ']') {
221       spc_warn(spe, "Unbalanced '[' and ']' in color specification.");
222       error = -1;
223     } else {
224       ap->curptr++;
225     }
226   }
227
228   return  error;
229 }
230
231
232 /* This is for reading *single* color specification. */
233 int
234 spc_util_read_colorspec (struct spc_env *spe, pdf_color *colorspec, struct spc_arg *ap)
235 {
236   ASSERT(colorspec && spe && ap);
237
238   skip_blank(&ap->curptr, ap->endptr);
239   if (ap->curptr >= ap->endptr) {
240     return -1;
241   }
242   return spc_read_color_color(spe, colorspec, ap);
243 }
244
245 int
246 spc_util_read_pdfcolor (struct spc_env *spe, pdf_color *colorspec, struct spc_arg *ap, pdf_color *defaultcolor)
247 {
248   int error = 0;
249
250   ASSERT(colorspec && spe && ap);
251
252   skip_blank(&ap->curptr, ap->endptr);
253   if (ap->curptr >= ap->endptr) {
254     return -1;
255   }
256   error = spc_read_color_pdf(spe, colorspec, ap);
257   if (error < 0 && defaultcolor) {
258     pdf_color_copycolor(colorspec, defaultcolor);
259     error = 0;
260   }
261   return error;
262 }
263
264 /* This need to allow 'true' prefix for unit and
265  * length value must be divided by current magnification.
266  */
267 int
268 spc_util_read_length (struct spc_env *spe, double *vp /* ret. */, struct spc_arg *ap)
269 {
270   char   *q;
271   double  v, u = 1.0;
272   const char *ukeys[] = {
273 #define K_UNIT__PT  0
274 #define K_UNIT__IN  1
275 #define K_UNIT__CM  2
276 #define K_UNIT__MM  3
277 #define K_UNIT__BP  4
278     "pt", "in", "cm", "mm", "bp", NULL
279   };
280   int     k, error = 0;
281
282   q = parse_float_decimal(&ap->curptr, ap->endptr);
283   if (!q)
284     return  -1;
285
286   v = atof(q);
287   RELEASE(q);
288
289   q = parse_c_ident(&ap->curptr, ap->endptr);
290   if (q) {
291     if (strlen(q) > strlen("true") &&
292         !memcmp(q, "true", strlen("true"))) {
293       u /= spe->mag != 0.0 ? spe->mag : 1.0; /* inverse magnify */
294       q += strlen("true");
295     }
296     for (k = 0; ukeys[k] && strcmp(ukeys[k], q); k++);
297     switch (k) {
298     case K_UNIT__PT: u *= 72.0 / 72.27; break;
299     case K_UNIT__IN: u *= 72.0; break;
300     case K_UNIT__CM: u *= 72.0 / 2.54 ; break;
301     case K_UNIT__MM: u *= 72.0 / 25.4 ; break;
302     case K_UNIT__BP: u *= 1.0 ; break;
303     default:
304       spc_warn(spe, "Unknown unit of measure: %s", q);
305       error = -1;
306       break;
307     }
308     RELEASE(q);
309   }
310
311   *vp = v * u;
312   return  error;
313 }
314
315
316 /*
317  * Compute a transformation matrix
318  * transformations are applied in the following
319  * order: scaling, rotate, displacement.
320  */
321 static void
322 make_transmatrix (pdf_tmatrix *M,
323                   double xoffset, double yoffset,
324                   double xscale,  double yscale,
325                   double rotate)
326 {
327   double c, s;
328
329   c = cos(rotate);
330   s = sin(rotate);
331
332   M->a =  xscale * c; M->b = xscale * s;
333   M->c = -yscale * s; M->d = yscale * c;
334   M->e = xoffset;     M->f = yoffset;
335 }
336
337 static int
338 spc_read_dimtrns_dvips (struct spc_env *spe, transform_info *t, struct spc_arg *ap)
339 {
340   static const char *_dtkeys[] = {
341 #define  K_TRN__HOFFSET  0
342 #define  K_TRN__VOFFSET  1
343     "hoffset", "voffset",
344 #define  K_DIM__HSIZE    2
345 #define  K_DIM__VSIZE    3
346     "hsize", "vsize",
347 #define  K_TRN__HSCALE   4
348 #define  K_TRN__VSCALE   5
349     "hscale", "vscale",
350 #define  K_TRN__ANGLE    6
351     "angle",
352 #define  K__CLIP         7
353     "clip",
354 #define  K_DIM__LLX      8
355 #define  K_DIM__LLY      9
356 #define  K_DIM__URX     10
357 #define  K_DIM__URY     11
358     "llx", "lly", "urx", "ury",
359 #define  K_DIM__RWI     12
360 #define  K_DIM__RHI     13
361     "rwi", "rhi",
362     NULL
363   };
364   double xoffset, yoffset, xscale, yscale, rotate;
365   int    error  = 0;
366
367   xoffset = yoffset = rotate = 0.0; xscale = yscale = 1.0;
368
369   skip_blank(&ap->curptr, ap->endptr);
370   while (!error && ap->curptr < ap->endptr) {
371     char  *kp, *vp;
372     int    k;
373
374     kp = parse_c_ident(&ap->curptr, ap->endptr);
375     if (!kp)
376       break;
377
378     for (k = 0; _dtkeys[k] && strcmp(kp, _dtkeys[k]); k++);
379     if (!_dtkeys[k]) {
380       spc_warn(spe, "Unrecognized dimension/transformation key: %s", kp);
381       error = -1;
382       RELEASE(kp);
383       break;
384     }
385
386     skip_blank(&ap->curptr, ap->endptr);
387     if (k == K__CLIP) {
388       t->flags |= INFO_DO_CLIP;
389       RELEASE(kp);
390       continue; /* not key-value */
391     }
392
393     if (ap->curptr < ap->endptr && ap->curptr[0] == '=') {
394       ap->curptr++;
395       skip_blank(&ap->curptr, ap->endptr);
396     }
397
398     vp = NULL;
399     if (ap->curptr[0] == '\'' || ap->curptr[0] == '\"') {
400       char  qchr = ap->curptr[0];
401       ap->curptr++;
402       skip_blank(&ap->curptr, ap->endptr);
403       vp = parse_float_decimal(&ap->curptr, ap->endptr);
404       skip_blank(&ap->curptr, ap->endptr);
405       if (vp && qchr != ap->curptr[0]) {
406         spc_warn(spe, "Syntax error in dimension/transformation specification.");
407         error = -1;
408         RELEASE(vp); vp = NULL;
409       }
410       ap->curptr++;
411     } else {
412       vp = parse_float_decimal(&ap->curptr, ap->endptr);
413     }
414     if (!error && !vp) {
415       spc_warn(spe, "Missing value for dimension/transformation: %s", kp);
416       error = -1;
417     }
418     RELEASE(kp);
419     if (!vp || error) {
420       break;
421     }
422
423     switch (k) {
424     case  K_TRN__HOFFSET:
425       xoffset = atof(vp);
426       break;
427     case  K_TRN__VOFFSET:
428       yoffset = atof(vp);
429       break;
430     case  K_DIM__HSIZE:
431       t->width   = atof(vp);
432       t->flags  |= INFO_HAS_WIDTH;
433       break;
434     case  K_DIM__VSIZE:
435       t->height  = atof(vp);
436       t->flags  |= INFO_HAS_HEIGHT;
437       break;
438     case  K_TRN__HSCALE:
439       xscale  = atof(vp) / 100.0;
440       break;
441     case  K_TRN__VSCALE:
442       yscale  = atof(vp) / 100.0;
443       break;
444     case  K_TRN__ANGLE:
445       rotate  = M_PI * atof(vp) / 180.0;
446       break;
447     case  K_DIM__LLX:
448       t->bbox.llx = atof(vp);
449       t->flags   |= INFO_HAS_USER_BBOX;
450       break;
451     case  K_DIM__LLY:
452       t->bbox.lly = atof(vp);
453       t->flags   |= INFO_HAS_USER_BBOX;
454       break;
455     case  K_DIM__URX:
456       t->bbox.urx = atof(vp);
457       t->flags   |= INFO_HAS_USER_BBOX;
458       break;
459     case  K_DIM__URY:
460       t->bbox.ury = atof(vp);
461       t->flags   |= INFO_HAS_USER_BBOX;
462       break;
463     case  K_DIM__RWI:
464       t->width  = atof(vp) / 10.0;
465       t->flags |= INFO_HAS_WIDTH;
466       break;
467     case  K_DIM__RHI:
468       t->height = atof(vp) / 10.0;
469       t->flags |= INFO_HAS_HEIGHT;
470       break;
471     }
472     skip_blank(&ap->curptr, ap->endptr);
473     RELEASE(vp);
474   }
475   make_transmatrix(&(t->matrix), xoffset, yoffset, xscale, yscale, rotate);
476
477   return  error;
478 }
479
480
481 static int
482 spc_read_dimtrns_pdfm (struct spc_env *spe, transform_info *p, struct spc_arg *ap, long *page_no)
483 {
484   int     has_scale, has_xscale, has_yscale, has_rotate, has_matrix;
485   const char *_dtkeys[] = {
486 #define  K_DIM__WIDTH  0
487 #define  K_DIM__HEIGHT 1
488 #define  K_DIM__DEPTH  2
489     "width", "height", "depth",
490 #define  K_TRN__SCALE  3
491 #define  K_TRN__XSCALE 4
492 #define  K_TRN__YSCALE 5
493 #define  K_TRN__ROTATE 6
494     "scale", "xscale", "yscale", "rotate", /* See "Dvipdfmx User's Manual", p.5 */
495 #define  K_TRN__BBOX   7
496     "bbox",
497 #define  K_TRN__MATRIX 8
498     "matrix",
499 #undef  K__CLIP
500 #define  K__CLIP       9
501     "clip",
502 #define  K__PAGE       10
503     "page",
504 #define  K__HIDE       11
505     "hide",
506      NULL
507   };
508   double xscale, yscale, rotate;
509   int    error = 0;
510
511   has_xscale = has_yscale = has_scale = has_rotate = has_matrix = 0;
512   xscale = yscale = 1.0; rotate = 0.0;
513   p->flags |= INFO_DO_CLIP;   /* default: do clipping */
514   p->flags &= ~INFO_DO_HIDE;   /* default: do clipping */
515
516   skip_blank(&ap->curptr, ap->endptr);
517
518   while (!error && ap->curptr < ap->endptr) {
519     char  *kp, *vp;
520     int    k;
521
522     kp = parse_c_ident(&ap->curptr, ap->endptr);
523     if (!kp)
524       break;
525
526     skip_blank(&ap->curptr, ap->endptr);
527     for (k = 0; _dtkeys[k] && strcmp(_dtkeys[k], kp); k++);
528     switch (k) {
529     case  K_DIM__WIDTH:
530       error = spc_util_read_length(spe, &p->width , ap);
531       p->flags |= INFO_HAS_WIDTH;
532       break;
533     case  K_DIM__HEIGHT:
534       error = spc_util_read_length(spe, &p->height, ap);
535       p->flags |= INFO_HAS_HEIGHT;
536       break;
537     case  K_DIM__DEPTH:
538       error = spc_util_read_length(spe, &p->depth , ap);
539       p->flags |= INFO_HAS_HEIGHT;
540       break;
541     case  K_TRN__SCALE:
542       vp = parse_float_decimal(&ap->curptr, ap->endptr);
543       if (!vp)
544         error = -1;
545       else {
546         xscale = yscale = atof(vp);
547         has_scale = 1;
548         RELEASE(vp);
549       }
550       break;
551     case  K_TRN__XSCALE:
552       vp = parse_float_decimal(&ap->curptr, ap->endptr);
553       if (!vp)
554         error = -1;
555       else {
556         xscale  = atof(vp);
557         has_xscale = 1;
558         RELEASE(vp);
559       }
560       break;
561     case  K_TRN__YSCALE:
562       vp = parse_float_decimal(&ap->curptr, ap->endptr);
563       if (!vp)
564         error = -1;
565       else {
566         yscale  = atof(vp);
567         has_yscale = 1;
568         RELEASE(vp);
569       }
570       break;
571     case  K_TRN__ROTATE:
572       vp = parse_float_decimal(&ap->curptr, ap->endptr);
573       if (!vp)
574         error = -1;
575       else {
576         rotate = M_PI * atof(vp) / 180.0;
577         has_rotate = 1;
578         RELEASE(vp);
579       }
580       break;
581     case  K_TRN__BBOX:
582       {
583         double  v[4];
584         if (spc_util_read_numbers(v, 4, spe, ap) != 4)
585           error = -1;
586         else {
587           p->bbox.llx = v[0];
588           p->bbox.lly = v[1];
589           p->bbox.urx = v[2];
590           p->bbox.ury = v[3];
591           p->flags   |= INFO_HAS_USER_BBOX;
592         }
593       }
594       break;
595     case  K_TRN__MATRIX:
596       {
597         double  v[6];
598         if (spc_util_read_numbers(v, 6, spe, ap) != 6)
599           error = -1;
600         else {
601           pdf_setmatrix(&(p->matrix), v[0], v[1], v[2], v[3], v[4], v[5]);
602           has_matrix = 1;
603         }
604       }
605       break;
606     case  K__CLIP:
607       vp = parse_float_decimal(&ap->curptr, ap->endptr);
608       if (!vp)
609         error = -1;
610       else {
611         if (atof(vp))
612           p->flags |= INFO_DO_CLIP;
613         else
614           p->flags &= ~INFO_DO_CLIP;
615         RELEASE(vp);
616       }
617       break;
618     case  K__PAGE:
619       {
620         double page;
621         if (page_no && spc_util_read_numbers(&page, 1, spe, ap) == 1)
622           *page_no = (long) page;
623         else
624           error = -1;
625       }
626       break;
627     case  K__HIDE:
628       p->flags |= INFO_DO_HIDE;
629       break;
630     default:
631       error = -1;
632       break;
633     }
634     if (error)
635       spc_warn(spe, "Unrecognized key or invalid value for dimension/transformation: %s", kp);
636     else
637       skip_blank(&ap->curptr, ap->endptr);
638     RELEASE(kp);
639   }
640
641   if (!error) {
642     /* Check consistency */
643     if (has_xscale && (p->flags & INFO_HAS_WIDTH)) {
644       spc_warn(spe, "Can't supply both width and xscale. Ignore xscale.");
645       xscale = 1.0;
646     } else if (has_yscale &&
647                (p->flags & INFO_HAS_HEIGHT)) {
648       spc_warn(spe, "Can't supply both height/depth and yscale. Ignore yscale.");
649       yscale = 1.0;
650     } else if (has_scale &&
651                (has_xscale || has_yscale)) {
652       spc_warn(spe, "Can't supply overall scale along with axis scales.");
653       error = -1;
654     } else if (has_matrix &&
655                (has_scale || has_xscale || has_yscale || has_rotate)) {
656       spc_warn(spe, "Can't supply transform matrix along with scales or rotate. Ignore scales and rotate.");
657     }
658   }
659
660   if (!has_matrix) {
661     make_transmatrix(&(p->matrix), 0.0, 0.0, xscale, yscale, rotate);
662   }
663
664   if (!(p->flags & INFO_HAS_USER_BBOX)) {
665     p->flags &= ~INFO_DO_CLIP;    /* no clipping needed */
666   }
667
668   return  error;
669 }
670
671 int
672 spc_util_read_dimtrns (struct spc_env *spe, transform_info *ti, struct spc_arg *args, long *page_no, int syntax)
673 {
674   ASSERT(ti && spe && args);
675
676   if (syntax) {
677     ASSERT(!page_no);
678     return  spc_read_dimtrns_dvips(spe, ti, args);
679   } else {
680     return  spc_read_dimtrns_pdfm (spe, ti, args, page_no);
681   }
682
683   return  -1;
684 }
685
686
687 /* Color names */
688 #ifdef  rgb
689 #undef  rgb
690 #endif
691 #ifdef  cmyk
692 #undef  cmyk
693 #endif
694 #define gray(g)       {1, {g}}
695 #define rgb8(r,g,b)   {3, {((r)/255.0), ((g)/255.0), ((b)/255.0), 0.0}}
696 #define cmyk(c,m,y,k) {4, {(c), (m), (y), (k)}}
697
698 static struct colordef_
699 {
700   const char  *key;
701   pdf_color    color;
702 } colordefs[] = {
703   {"GreenYellow",    cmyk(0.15, 0.00, 0.69, 0.00)},
704   {"Yellow",         cmyk(0.00, 0.00, 1.00, 0.00)},
705   {"Goldenrod",      cmyk(0.00, 0.10, 0.84, 0.00)},
706   {"Dandelion",      cmyk(0.00, 0.29, 0.84, 0.00)},
707   {"Apricot",        cmyk(0.00, 0.32, 0.52, 0.00)},
708   {"Peach",          cmyk(0.00, 0.50, 0.70, 0.00)},
709   {"Melon",          cmyk(0.00, 0.46, 0.50, 0.00)},
710   {"YellowOrange",   cmyk(0.00, 0.42, 1.00, 0.00)},
711   {"Orange",         cmyk(0.00, 0.61, 0.87, 0.00)},
712   {"BurntOrange",    cmyk(0.00, 0.51, 1.00, 0.00)},
713   {"Bittersweet",    cmyk(0.00, 0.75, 1.00, 0.24)},
714   {"RedOrange",      cmyk(0.00, 0.77, 0.87, 0.00)},
715   {"Mahogany",       cmyk(0.00, 0.85, 0.87, 0.35)},
716   {"Maroon",         cmyk(0.00, 0.87, 0.68, 0.32)},
717   {"BrickRed",       cmyk(0.00, 0.89, 0.94, 0.28)},
718   {"Red",            cmyk(0.00, 1.00, 1.00, 0.00)},
719   {"OrangeRed",      cmyk(0.00, 1.00, 0.50, 0.00)},
720   {"RubineRed",      cmyk(0.00, 1.00, 0.13, 0.00)},
721   {"WildStrawberry", cmyk(0.00, 0.96, 0.39, 0.00)},
722   {"Salmon",         cmyk(0.00, 0.53, 0.38, 0.00)},
723   {"CarnationPink",  cmyk(0.00, 0.63, 0.00, 0.00)},
724   {"Magenta",        cmyk(0.00, 1.00, 0.00, 0.00)},
725   {"VioletRed",      cmyk(0.00, 0.81, 0.00, 0.00)},
726   {"Rhodamine",      cmyk(0.00, 0.82, 0.00, 0.00)},
727   {"Mulberry",       cmyk(0.34, 0.90, 0.00, 0.02)},
728   {"RedViolet",      cmyk(0.07, 0.90, 0.00, 0.34)},
729   {"Fuchsia",        cmyk(0.47, 0.91, 0.00, 0.08)},
730   {"Lavender",       cmyk(0.00, 0.48, 0.00, 0.00)},
731   {"Thistle",        cmyk(0.12, 0.59, 0.00, 0.00)},
732   {"Orchid",         cmyk(0.32, 0.64, 0.00, 0.00)},
733   {"DarkOrchid",     cmyk(0.40, 0.80, 0.20, 0.00)},
734   {"Purple",         cmyk(0.45, 0.86, 0.00, 0.00)},
735   {"Plum",           cmyk(0.50, 1.00, 0.00, 0.00)},
736   {"Violet",         cmyk(0.79, 0.88, 0.00, 0.00)},
737   {"RoyalPurple",    cmyk(0.75, 0.90, 0.00, 0.00)},
738   {"BlueViolet",     cmyk(0.86, 0.91, 0.00, 0.04)},
739   {"Periwinkle",     cmyk(0.57, 0.55, 0.00, 0.00)},
740   {"CadetBlue",      cmyk(0.62, 0.57, 0.23, 0.00)},
741   {"CornflowerBlue", cmyk(0.65, 0.13, 0.00, 0.00)},
742   {"MidnightBlue",   cmyk(0.98, 0.13, 0.00, 0.43)},
743   {"NavyBlue",       cmyk(0.94, 0.54, 0.00, 0.00)},
744   {"RoyalBlue",      cmyk(1.00, 0.50, 0.00, 0.00)},
745   {"Blue",           cmyk(1.00, 1.00, 0.00, 0.00)},
746   {"Cerulean",       cmyk(0.94, 0.11, 0.00, 0.00)},
747   {"Cyan",           cmyk(1.00, 0.00, 0.00, 0.00)},
748   {"ProcessBlue",    cmyk(0.96, 0.00, 0.00, 0.00)},
749   {"SkyBlue",        cmyk(0.62, 0.00, 0.12, 0.00)},
750   {"Turquoise",      cmyk(0.85, 0.00, 0.20, 0.00)},
751   {"TealBlue",       cmyk(0.86, 0.00, 0.34, 0.02)},
752   {"Aquamarine",     cmyk(0.82, 0.00, 0.30, 0.00)},
753   {"BlueGreen",      cmyk(0.85, 0.00, 0.33, 0.00)},
754   {"Emerald",        cmyk(1.00, 0.00, 0.50, 0.00)},
755   {"JungleGreen",    cmyk(0.99, 0.00, 0.52, 0.00)},
756   {"SeaGreen",       cmyk(0.69, 0.00, 0.50, 0.00)},
757   {"Green",          cmyk(1.00, 0.00, 1.00, 0.00)},
758   {"ForestGreen",    cmyk(0.91, 0.00, 0.88, 0.12)},
759   {"PineGreen",      cmyk(0.92, 0.00, 0.59, 0.25)},
760   {"LimeGreen",      cmyk(0.50, 0.00, 1.00, 0.00)},
761   {"YellowGreen",    cmyk(0.44, 0.00, 0.74, 0.00)},
762   {"SpringGreen",    cmyk(0.26, 0.00, 0.76, 0.00)},
763   {"OliveGreen",     cmyk(0.64, 0.00, 0.95, 0.40)},
764   {"RawSienna",      cmyk(0.00, 0.72, 1.00, 0.45)},
765   {"Sepia",          cmyk(0.00, 0.83, 1.00, 0.70)},
766   {"Brown",          cmyk(0.00, 0.81, 1.00, 0.60)},
767   {"Tan",            cmyk(0.14, 0.42, 0.56, 0.00)},
768   /* Adobe Reader 7 and 8 had problem when gray and cmyk black colors
769    * are mixed. No problem with Previewer.app.
770    * It happens when \usepackage[dvipdfm]{graphicx} and then called
771    * \usepackage{color} without dvipdfm option. */
772   {"Gray",           gray(0.5)},
773   {"Black",          gray(0.0)},
774   {"White",          gray(1.0)},
775   {NULL}
776 };
777
778
779 static int
780 pdf_color_namedcolor (pdf_color *color, const char *name)
781 {
782   int   i;
783   for (i = 0; colordefs[i].key; i++) {
784     if (!strcmp(colordefs[i].key, name)) {
785       pdf_color_copycolor(color, &colordefs[i].color);
786       return  0;
787     }
788   }
789   return  -1;
790 }
791