1#!/usr/local/bin/perl -w
2#
3# cdlabelgen - a program for making cd jewel box covers and traycards
4#
5# Author: Avinash Chopde <avinash@aczoom.com>  www.aczoom.com
6# -----------------------------------------------------------------------
7# Copyright (C) 1998, 1999 B. W. Fitzpatrick <fitz@red-bean.com>
8# Copyright (C) 2001-2005 Avinash Chopde <avinash@aczoom.com>  www.aczoom.com
9#
10# All rights reserved.
11#
12# Permission is hereby granted, free of charge, to any person obtaining a
13# copy of this software and associated documentation files (the
14# "Software"), to deal in the Software without restriction, including
15# without limitation the rights to use, copy, modify, merge, publish,
16# distribute, and/or sell copies of the Software, and to permit persons
17# to whom the Software is furnished to do so, provided that the above
18# copyright notice(s) and this permission notice appear in all copies of
19# the Software and that both the above copyright notice(s) and this
20# permission notice appear in supporting documentation.
21#
22# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
25# OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26# HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
27# INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
28# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
29# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
30# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31#
32# Except as contained in this notice, the name of a copyright holder
33# shall not be used in advertising or otherwise to promote the sale, use
34# or other dealings in this Software without prior written authorization
35# of the copyright holder.
36# ---------------------------------------------------------------------
37# Created: October, 1998 by B. W. Fitzpatrick <fitz@red-bean.com>
38# ---------------------------------------------------------------------
39# Apr 2001 Avinash Chopde <avinash@aczoom.com> http://www.aczoom.com/
40# Added -m option to support slim-cd cases
41#          prints front cover insert - folding two page insert
42# Added -S 0 and -T 0 support, to print logo as background image instead
43# Minor changes for better handling of Windows NT.
44# Jul 2001 Avinash Chopde <avinash@aczoom.com> http://www.aczoom.com/
45# Added -p option to enable clipping of item text strings
46#   without this option, an item is fit to a column by shrinking it as needed
47#   Using -p requires the new template.ps that contains this feature.
48# Apr 2002 added CD envelope print option -M
49# Jul 2002 -S and -T options now take image offset values, -y for page offset
50# Aug 2002 Alessandro Dotti Contra <alessandro.dotti@libero.it> [2.5.0]
51#   - Added support for long options
52#   - Added options to choose colors for plaque background,
53#     category, subcategory and text
54# May 2003  From Mathias Herberts <Mathias.Herberts@iroise.net>
55#   - * Adds the option to output slim cd cover cases with the order of the
56#   - pages switched so the folding line lies on the outside
57#   - of a normal cd case.
58#   - * Included two logos for DivX and Ogg Vorbis, they come from:
59#   - Ogg Vorbis      http://w148.de/~mmartin/xifish/  [Marcel Martin]
60#   - DivX            http://www.divxnetworks.com/press/logos.php
61#       Updates from Peter Bieringer:
62#   - * Word-wrap fix
63# ---------------------------------------------------------------------
64# June 2003 Updates from Tony Mancill
65# 20021102 tony mancill <tmancill@debian.org>
66#   - added -C/--no-cover-plaque option
67#   - added -n/--number-in-set option
68# 20030601 tony mancill <tmancill@debian.org>
69#    - fold 2.6.0 upstream changes into Debian 2.5.0-2
70# ---------------------------------------------------------------------
71# Oct 2003 - Added support for DVD cases, inside inserts only for now [2.7.0]
72# Nov 2003 - Added support for DVD cases, outside covers [3.0.0]
73# ---------------------------------------------------------------------
74# Dec 2004  From: Stephan Grund <Stephan.Grund@isst.fraunhofer.de>
75#   - added support for rotating end-caps
76# ---------------------------------------------------------------------
77# Jan 2005  Added support for directly printing on a Compact Disc [3.5.0]
78#   - page-offset now takes both x,y values
79# ---------------------------------------------------------------------
80# Aug 2005 [3.6.0]
81#   --rows-columns= option to force #rows and columns, don't compute
82#       line_height or num_columns for list of items.
83# ---------------------------------------------------------------------
84# Aug 2007 [4.0.0]
85#   tray overlay EPS support - draw a EPS file over the background and items
86#   can be used to print barcode, use in conjunction with "barcodegen"
87# ---------------------------------------------------------------------
88# Oct 2008 [4.1.0]
89#   Create covers for double-sided DVD cases that hold 6 DVDs.
90#   --double-case option now available, uses wider spine section.
91#   Only double-width DVD cases are supported, double-width CD cases are
92#   not supported.
93#   Therefore, using --double-case also implies the --create-dvd-outside
94#   option.
95#   Thanks to Andras Salamon <asalamon@chello.hu> for this patch.
96# ---------------------------------------------------------------------
97# Apr 2012 [4.2.0]
98#   Support for double-depth slim DVD cases. --slim-double-case option added.
99#   Patch sent by Dominique Dumont dod@debian.org
100# ---------------------------------------------------------------------
101
102use Socket qw(:DEFAULT :crlf);
103use strict;
104use Getopt::Long;
105# Configure the Getopt::Long module;
106$Getopt::Long::ignorecase = 0;
107
108# Prepare to slurp up the file
109my $template = 'template.ps';
110my $directory;
111
112# Modify this if you want to store your template somewhere else
113# Perhaps we can make this part of a conf file in the future?
114my @where_is_the_template;
115
116if ($^O !~ /^MSWin32/) { # not windows...
117  # Unix section -----------------------------------------------------
118  @where_is_the_template = (
119    '/usr/local/lib/cdlabelgen/',
120    '/usr/share/cdlabelgen/',
121    '/opt/lib/cdlabelgen/',
122    '/usr/local/share/cdlabelgen/',
123    '/etc/cdlabelgen/',
124    './postscript/',
125    );
126} else { # any MSWindows 32 platform...
127  # DOS section -----------------------------------------------------
128  @where_is_the_template = ('c:/cdlabelgen/', './postscript/');
129}
130
131my $found_template = '';
132foreach $directory (@where_is_the_template) {
133    if (-e ("$directory$template")) {
134        $template = "$directory$template";
135        $found_template = 1;
136        #Put the template dir at the front of the list for later
137        push @where_is_the_template,$directory;
138        last;
139    }
140}
141
142my (@items, @cover_items, @tray_items, $num_items_cover);
143my $eps_cover_file;
144my $eps_tray_card_file;
145my $eps_cover_bounds;
146my $eps_tray_card_bounds;
147my $eps_cover_scale;
148my $eps_tray_card_scale;
149my $date;
150my $print_to_file;
151my $default_eol = $/;
152my $show_tray_plaque = 1;
153my $show_cover_plaque = 1;
154my $default_bounds = "\n/bound1x 10 def\n/bound1y 10 def\n/bound2x 10 def\n/bound2y 10 def\n/scaleratio 1.0 def\n";
155my $normalcdcase = "true";
156my $slimcase = "false"; # 0.5 normal dvd width
157my $slimdoublecase = "false"; # 1.5 normal dvd width
158my $doublecase = "false"; # 2 x normal dvd width
159my $envelopecdcase = "false";
160my $insidedvdcase = "false";
161my $outsidedvdcase = "false";
162my $cdlabel = "false";
163my $enable_item_scaling = "true";
164my $outside_foldout = "false";
165my $yoffset = "0.8"; # margin, default for letter sized paper
166my $xoffset = "1.0"; # margin, default for letter sized paper
167my $cover_image_xoffset = 0; # shift image logos by this much
168my $cover_image_yoffset = 0; # shift image logos by this much
169my $tray_image_xoffset = 0; # shift image logos by this much
170my $tray_image_yoffset = 0; # shift image logos by this much
171my $edge_line_width = 0.6; # edge line width in points
172my $rotate_endcaps = "false";
173my $count_rows = "0"; # default 0 implies calculate #rows in template.ps
174my $count_cols = "0"; # default 0 implies calculate #cols in template.ps
175my $eps_tray_overlay_bounds;
176my $eps_tray_overlay_file = '';
177my ($eps_tray_overlay_scale, $tray_overlay_image_xoffset, $tray_overlay_image_yoffset) = (1, 0, 0);
178######################################################################
179# Argument processing
180
181# mar 01 avinash: add defaults, -c or -s can be omitted
182# aug 02 alessandro: added support for long options
183
184my $CATEGORY = "";           # Category
185my $SUBCATEGORY = "";        # Subcatgory
186my $ITEMS;                   # List of item
187my $ITEMS_FILE;              # File with items to print
188my $COVER_ITEMS;             # Items to print on cover
189my $COVER_IMAGE;             # Image for cover (eps file)
190my $COVER_IMAGE_SCALERATIO;  # Scaleratio for cover image
191my $TRAY_IMAGE;              # Image for tray (eps file)
192my $TRAY_IMAGE_SCALERATIO;   # Scaleratio for tray image
193my $DATE;                    # Date
194my $NODATE;                  # Don't print date
195my $OUTPUT_FILE;             # PostScript code output file
196my $COVER_TEMPLATE;          # Template to use for PostScript code
197my $NO_TRAY_PLAQUE;          # Don't print plaque on tray
198my $NO_COVER_PLAQUE;         # Don't print plaque on the front cover
199my $TRAY_WORD_WRAP;          # Apply word wrap to tray's items
200my $HELP;                    # Print help
201my $CREATE_SLIM_CASE;        # Create a cover suitable for slim cases
202my $CREATE_SLIM_DOUBLE_CASE; # Create a cover suitable for 1.5 normal dvd cases
203my $CREATE_DOUBLE_CASE;      # Create a cover suitable for double cases
204my $CREATE_ENVELOPE;         # Create an envelope
205my $CREATE_DVD_INSIDE;       # Create insert for inside of the DVD case
206my $CREATE_DVD_OUTSIDE;      # Create insert for outside of the DVD case
207my $CREATE_CDLABEL;          # Directly printing on the CD
208my $CLIP_ITEMS;              # Use fixed size font to print items
209my $PAGE_OFFSET;             # Put text <offset> inches from top of page
210my $LINE_WIDTH;              # Length of a text line
211my $PLAQUE_COLOR;            # <r,g,b> values for plaque color
212my $CATEGORY_COLOR;          # <r,g,b> values for category color
213my $SUBCATEGORY_COLOR;       # <r,g,b> values for subcategory color
214my $TEXT_COLOR;              # <r,g,b> values for text color
215my $OUTSIDE_FOLDOUT;         # Fold slim case/DVD inside insert fold line lie on the outside
216my $NUMBER_IN_SET;           # volume/member number in a set
217my $ROTATE_ENDCAPS;          # Rotate endcaps in jewelcase
218my $ROWS_COLUMNS;            # force list of items in these many rows/columns
219my $TRAY_OVERLAY;            # overlay this image on tray card
220my $TRAY_OVERLAY_SCALERATIO;
221
222unless ( GetOptions (
223      "c=s"                        => \$CATEGORY,
224      "category=s"                 => \$CATEGORY,
225      "s=s"                        => \$SUBCATEGORY,
226      "subcategory=s"              => \$SUBCATEGORY,
227      "i=s"                        => \$ITEMS,
228      "items=s"                    => \$ITEMS,
229      "f=s"                        => \$ITEMS_FILE,
230      "items-from-file=s"          => \$ITEMS_FILE,
231      "v=i"                        => \$COVER_ITEMS,
232      "cover-items=i"              => \$COVER_ITEMS,
233      "e=s"                        => \$COVER_IMAGE,
234      "cover-image=s"              => \$COVER_IMAGE,
235      "S=s"                        => \$COVER_IMAGE_SCALERATIO,
236      "cover-image-scaleratio=s"   => \$COVER_IMAGE_SCALERATIO,
237      "E=s"                        => \$TRAY_IMAGE,
238      "tray-image=s"               => \$TRAY_IMAGE,
239      "T=s"                        => \$TRAY_IMAGE_SCALERATIO,
240      "tray-image-scaleratio=s"    => \$TRAY_IMAGE_SCALERATIO,
241      "d=s"                        => \$DATE,
242      "date=s"                     => \$DATE,
243      "D"                          => \$NODATE,
244      "no-date"                    => \$NODATE,
245      "o=s"                        => \$OUTPUT_FILE,
246      "output-file=s"              => \$OUTPUT_FILE,
247      "t=s"                        => \$COVER_TEMPLATE,
248      "cover-template=s"           => \$COVER_TEMPLATE,
249      "b"                          => \$NO_TRAY_PLAQUE,
250      "no-tray-plaque"             => \$NO_TRAY_PLAQUE,
251      "C"                          => \$NO_COVER_PLAQUE,
252      "no-cover-plaque"            => \$NO_COVER_PLAQUE,
253      "w"                          => \$TRAY_WORD_WRAP,
254      "tray-word-wrap"             => \$TRAY_WORD_WRAP,
255      "h"                          => \$HELP,
256      "help"                       => \$HELP,
257      "m"                          => \$CREATE_SLIM_CASE,
258      "slim-case"                  => \$CREATE_SLIM_CASE,
259      "slim-double-case"           => \$CREATE_SLIM_DOUBLE_CASE,
260      "double-case"                => \$CREATE_DOUBLE_CASE,
261      "create-slim-cover"          => \$CREATE_SLIM_CASE, ##DEPRECATE-Dec04
262      "O"                          => \$OUTSIDE_FOLDOUT,
263      "outside-foldout"            => \$OUTSIDE_FOLDOUT,
264      "slim-cover-foldout"         => \$OUTSIDE_FOLDOUT, ##DEPRECATE
265      "M"                          => \$CREATE_ENVELOPE,
266      "create-envelope"            => \$CREATE_ENVELOPE,
267      "p"                          => \$CLIP_ITEMS,
268      "clip-items"                 => \$CLIP_ITEMS,
269      "y=s"                        => \$PAGE_OFFSET,
270      "page-offset=s"              => \$PAGE_OFFSET,
271      "l=f"                        => \$LINE_WIDTH,
272      "line-width=f"               => \$LINE_WIDTH,
273      "create-dvd-inside"          => \$CREATE_DVD_INSIDE,
274      "create-dvd-outside"         => \$CREATE_DVD_OUTSIDE,
275      "create-cdlabel"             => \$CREATE_CDLABEL,
276      "plaque-color=s"             => \$PLAQUE_COLOR,
277      "category-color=s"           => \$CATEGORY_COLOR,
278      "subcategory-color=s"        => \$SUBCATEGORY_COLOR,
279      "text-color=s"               => \$TEXT_COLOR,
280      "n=s"                        => \$NUMBER_IN_SET,
281      "number-in-set=s"            => \$NUMBER_IN_SET,
282      "rotate-endcaps"             => \$ROTATE_ENDCAPS,
283      "rows-columns=s"             => \$ROWS_COLUMNS,
284      "tray-overlay=s"             => \$TRAY_OVERLAY,
285      "tray-overlay-scaleratio=s"  => \$TRAY_OVERLAY_SCALERATIO,
286   ))
287   { &show_help; }
288
289if($HELP) {
290    &show_help();
291}
292
293# Do we have enough flags to go on? Bail here if not.
294# april 2001: -c -s are both optional now...
295
296if($COVER_TEMPLATE && -f $COVER_TEMPLATE)
297{
298    $template = $COVER_TEMPLATE;
299    $found_template = 1;
300}
301unless ($found_template) {    &error("Postscript template file not found") }
302
303# Category/title
304my $category = &scrub($CATEGORY);
305
306# Subcategory/subtitle
307my $subcategory = &scrub($SUBCATEGORY);
308
309# Items | directories | songs
310if (defined($ITEMS_FILE)) {
311   my $infile = $ITEMS_FILE;
312   @items = split(/\n/, &scrub(get_file_contents($infile,@where_is_the_template)));
313}
314elsif (defined($ITEMS)){
315   my $clean_items = &scrub($ITEMS);
316   @items = (split (/%/, $clean_items));
317}
318
319# Word wrapping
320if (defined($TRAY_WORD_WRAP)) {
321   @items = &word_wrap(@items);
322}
323
324# how to split the items between tray and cover
325if (defined($COVER_ITEMS)) {
326    unless ( $COVER_ITEMS =~ /^([+]?\d+)$/ ) {
327       &error("-v num items in cover must be a positive integer");
328    }
329    $num_items_cover = $COVER_ITEMS;
330    @cover_items = @items;
331    if ($num_items_cover < ($#items + 1)) {
332       # split items between cover and tray
333       @tray_items = splice(@cover_items, $num_items_cover);
334    } else {
335       # put all items on cover, no items in tray
336       @tray_items = (' ');
337    }
338}
339else { # Else, no items to be printed on cover, default
340    $num_items_cover = 0;
341    @cover_items = (' ');
342    @tray_items = @items;
343}
344
345# Need to at least have an empty string, 1 min item needed
346@cover_items = (' ') if ($#cover_items < 0);
347@tray_items = (' ') if ($#tray_items < 0);
348
349# Format for a postscript array of strings now that we've wrapped (or not)
350# mar 01 avinash: To try to keep this from exceeding
351# DSC line len (255 chars), insert \n after each item
352@tray_items = map {"($_)\n"} @tray_items;
353@cover_items = map {"($_)\n"} @cover_items;
354
355# Date stuff
356if (defined($DATE)) {
357    $date = &scrub($DATE);
358}
359else {
360    $date = &get_date();
361}
362if ($NODATE) {
363    $date = '';
364}
365
366# 20021102 - <tmancill@debian.org> - patch for "volume in a set"
367# based on a patch submission by David Schmitt <david@schmitt.edv-bus.at>
368# sample usage is:
369#    for $i in `seq 1 5`; do
370#    cdlabelgen -c "My Filesystem" -s "/usr/local/foo" \
371#       -n "CD $i of 5" -e postscript/recycle.eps > foo_$i.ps
372#    done
373if (defined($NUMBER_IN_SET)) {
374   my $number_in_set = &scrub($NUMBER_IN_SET);
375   if ($date) {
376      $date .= " - ";
377   }
378   $date .= $number_in_set;
379}
380
381# page offsets
382# yoffset - to fit various sized pages. 0.8 works for letter, 1.5 for A4
383if (defined($PAGE_OFFSET)) {
384    if ($PAGE_OFFSET =~ /,/) {
385        ($xoffset, $yoffset) = split( /,/, $PAGE_OFFSET, 2);
386        unless ( $xoffset =~ /^([+-]?\d+)$|([+-]?(\d+\.\d+|\d+\.|\.\d+))$/ ) {
387          &error("--page-offset page_X_offset in inches must be a integer or floating point number");
388        }
389    } else {
390        $yoffset = $PAGE_OFFSET;
391    }
392    unless ( $yoffset =~ /^([+-]?\d+)$|([+-]?(\d+\.\d+|\d+\.|\.\d+))$/ ) {
393      &error("--page-offset page_Y_offset in inches must be a integer or floating point number");
394    }
395}
396# cover espfile scaling with optional translate
397if (defined($COVER_IMAGE_SCALERATIO)) {
398    ($eps_cover_scale, $cover_image_xoffset, $cover_image_yoffset) = split( /,/, $COVER_IMAGE_SCALERATIO, 3);
399    unless ( $eps_cover_scale =~ /^([+]?\d+)$|([+]?(\d+\.\d+|\d+\.|\.\d+))$/ ) {
400      &error("-S logo scale ratio must be a positive integer or floating point number");
401    }
402    if (defined($cover_image_xoffset)) {
403      $cover_image_yoffset = "" unless (defined($cover_image_yoffset));
404      unless (
405        $cover_image_xoffset =~ /^([+-]?\d+)$|([+-]?(\d+\.\d+|\d+\.|\.\d+))$/ &&
406        $cover_image_yoffset =~ /^([+-]?\d+)$|([+-]?(\d+\.\d+|\d+\.|\.\d+))$/ ) {
407        &error("-S <scale>[,<xoffset>,<yoffset>] offset in inches must be a pair of numbers: x,y");
408      }
409    } else {
410        $cover_image_xoffset = 0;
411        $cover_image_yoffset = 0;
412    }
413    if ($eps_cover_scale == 0.0 && ($cover_image_xoffset != 0 || $cover_image_yoffset != 0)) {
414      warn("$0: Warning: -S <scale>[,<xoffset>,<yoffset>] scale is zero, so no image translate possible\n");
415    }
416}
417else { # Else, no scaling
418    $eps_cover_scale = 1;
419    $cover_image_xoffset = 0;
420    $cover_image_yoffset = 0;
421}
422
423# traycard espfile scaling and optional translate
424if (defined($TRAY_IMAGE_SCALERATIO)) {
425    ($eps_tray_card_scale, $tray_image_xoffset, $tray_image_yoffset) = split( /,/, $TRAY_IMAGE_SCALERATIO, 3);
426    unless ( $eps_tray_card_scale =~ /^(fill1|fill2|([+]?\d+)|([+]?(\d+\.\d+|\d+\.|\.\d+)))$/ ) {
427      &error("-T logo scale ratio must be a positive integer or floating point number, or the words fill1 or fill2");
428    }
429    if (defined($tray_image_xoffset)) {
430      $tray_image_yoffset = "" unless (defined($tray_image_yoffset));
431      unless (
432        $tray_image_xoffset =~ /^([+-]?\d+)$|([+-]?(\d+\.\d+|\d+\.|\.\d+))$/ &&
433        $tray_image_yoffset =~ /^([+-]?\d+)$|([+-]?(\d+\.\d+|\d+\.|\.\d+))$/ ) {
434        &error("-T <scale>[,<xoffset>,<yoffset>] offset in inches must be a pair of numbers: x,y");
435      }
436      if (
437        ($eps_tray_card_scale =~ /(fill1|fill2)/ || $eps_tray_card_scale == 0.0)
438        &&
439        ($tray_image_xoffset != 0 || $tray_image_yoffset != 0)) {
440          warn("$0: Warning: -T <scale>[,<xoffset>,<yoffset>] scale is zero, so no image translate possible\n");
441      }
442    } else {
443        $tray_image_xoffset = 0;
444        $tray_image_yoffset = 0;
445    }
446}
447else { # Else, no scaling
448    $eps_tray_card_scale = 1;
449    $tray_image_xoffset = 0;
450    $tray_image_yoffset = 0;
451}
452# cover epsfile
453if (defined($COVER_IMAGE)) {
454    $eps_cover_file = get_file_contents($COVER_IMAGE,@where_is_the_template);
455    $eps_cover_bounds = &get_bounding_box($COVER_IMAGE, $eps_cover_scale);
456}
457else {
458    $eps_cover_bounds = $default_bounds;
459    $eps_cover_file = '';
460}
461# traycard epsfile
462if (defined($TRAY_IMAGE)) {
463    $eps_tray_card_file = get_file_contents($TRAY_IMAGE,@where_is_the_template);
464    $eps_tray_card_bounds = &get_bounding_box($TRAY_IMAGE, $eps_tray_card_scale);
465}
466else {
467    $eps_tray_card_bounds = $default_bounds;
468    $eps_tray_card_file = '';
469}
470
471# line width (0 suppreses all cover/tray edge lines)
472if (defined($LINE_WIDTH)) {
473    unless ( $LINE_WIDTH =~ /^([+]?\d+)$|([+]?(\d+\.\d+|\d+\.|\.\d+))$/ ) {
474       &error("-l line width in points must be a positive number");
475    }
476    $edge_line_width = $LINE_WIDTH;
477}
478
479# output file
480if (defined($OUTPUT_FILE)) {
481    open (OUT, ">$OUTPUT_FILE") or &error("Cannot open $OUTPUT_FILE for writing: $!");
482    $print_to_file = 1;
483}
484
485# If this flag is set, don't print the plaque on the back (give more room for items).
486if ($NO_TRAY_PLAQUE) {
487   $show_tray_plaque = 0;
488}
489
490# If this flag is set, don't print the plaque on the cover (only on the sides and maybe the back).
491if ($NO_COVER_PLAQUE) {
492   $show_cover_plaque = 0;
493}
494
495# ---- figure out which insert to output - only one should be set
496my $outputmodes = 0;
497
498
499
500if ($CREATE_SLIM_CASE) { # applies to CDs and DVDs
501   $slimcase = "true";
502   $outputmodes++;
503}
504
505if ($CREATE_SLIM_DOUBLE_CASE) { # applies to DVDs
506   $slimdoublecase = "true";
507   $outputmodes++;
508}
509
510if ($CREATE_DOUBLE_CASE) { # applies to DVDs
511   $doublecase = "true";
512   $outputmodes++;
513}
514
515if ($CREATE_ENVELOPE) {
516   $envelopecdcase = "true";
517   $outputmodes++;
518}
519
520if ($CREATE_DVD_INSIDE) {
521   $insidedvdcase  = "true";
522   $outputmodes++;
523}
524
525if ($CREATE_DVD_OUTSIDE) {
526   $outsidedvdcase  = "true";
527   $outputmodes++;
528}
529
530if ($CREATE_CDLABEL) {
531   $cdlabel  = "true";
532   $outputmodes++;
533}
534
535# sanity checks
536if ($CREATE_SLIM_CASE) {
537   &error("Conflicting output modes - slim case cannot be used with dvdinside or envelope") if ($CREATE_DVD_INSIDE || $CREATE_ENVELOPE);
538   }
539if ($CREATE_DOUBLE_CASE || $CREATE_SLIM_DOUBLE_CASE) {
540   &error("Conflicting output modes - double case cannot be used with dvdinside or envelope") if ($CREATE_DVD_INSIDE || $CREATE_ENVELOPE);
541   # only dvd outside supported at this time, so force make it set
542   $outsidedvdcase  = "true";
543   }
544if ($outputmodes == 0) { $normalcdcase = "true";}
545if ($outputmodes >= 1) { $normalcdcase = "false";}
546if ($outputmodes > 1) {
547   &error("Conflicting output modes - multiple provided, only one should be present -- cd, dvd-inside, outside, etc")
548       unless (($CREATE_SLIM_CASE || $CREATE_SLIM_DOUBLE_CASE || $CREATE_DOUBLE_CASE) && ($outputmodes == 2));
549   }
550
551#-------------
552
553if ($CLIP_ITEMS) {
554   $enable_item_scaling = "false";
555}
556
557if ($OUTSIDE_FOLDOUT) {
558   $outside_foldout = "true";
559   &error("outside foldout option can only be used with slim-cd or dvd-inside modes") unless ($CREATE_SLIM_CASE || $CREATE_DVD_INSIDE && !$CREATE_DVD_OUTSIDE);
560}
561
562# If this flag is set, rotate the text in endcaps
563if ($ROTATE_ENDCAPS) {
564   $rotate_endcaps = "true";
565}
566
567# If user specified #rows and #columns, use that for printing list of items
568if (defined($ROWS_COLUMNS)) {
569    ($count_rows, $count_cols) = split( /,/, $ROWS_COLUMNS, 2);
570    unless (
571      $count_rows =~ /^([+]?\d+)$|([+]?(\d+\.\d+|\d+\.|\.\d+))$/ &&
572      $count_cols =~ /^([+]?\d+)$|([+]?(\d+\.\d+|\d+\.|\.\d+))$/ ) {
573      &error("--rows-columns=<count_rows_for_items,count_columns_for_items> must be a pair of numbers: x,y");
574    }
575}
576
577######################################################################
578# HANDLE COLORS: added by alessandro aug 02
579#
580# The values supplied to the color options must be in the r,g,b form.
581# The following condition must be true:
582#
583#    0 <= (r|g|b) <= 255
584#
585# This values must be converted, since postcript needs values lesser
586# then or equal to one.
587
588# PLAQUE color
589
590my $r_plaque_color = 1;   # default color is white
591my $g_plaque_color = 1;
592my $b_plaque_color = 1;
593
594if ($PLAQUE_COLOR)
595{
596   if ($PLAQUE_COLOR !~ /(\d+)\,(\d+)\,(\d+)/) { &error("Plaque color not specified correctly."); }
597
598   $r_plaque_color = $1 / 255;
599   &error("Plaque color: invalid red component.") if $r_plaque_color > 1;
600   $g_plaque_color = $2 / 255;
601   &error("Plaque color: invalid green component.") if $g_plaque_color > 1;
602   $b_plaque_color = $3 / 255;
603   &error("Plaque color: invalid blue component.") if $b_plaque_color > 1;
604}
605
606# CATEGORY color
607
608my $r_category_color = 0;   # default color is black
609my $g_category_color = 0;
610my $b_category_color = 0;
611
612if ($CATEGORY_COLOR)
613{
614   if ($CATEGORY_COLOR !~ /(\d+)\,(\d+)\,(\d+)/) { &error("Category color not specified correctly."); }
615
616   $r_category_color = $1 / 255;
617   &error("Category color: invalid red component.") if $r_category_color > 1;
618   $g_category_color = $2 / 255;
619   &error("Category color: invalid green component.") if $g_category_color > 1;
620   $b_category_color = $3 / 255;
621   &error("Category color: invalid blue component.") if $b_category_color > 1;
622}
623
624# SUBCATEGORY color
625
626my $r_subcategory_color = 0;   # default color is black
627my $g_subcategory_color = 0;
628my $b_subcategory_color = 0;
629
630if ($SUBCATEGORY_COLOR)
631{
632   if ($SUBCATEGORY_COLOR !~ /(\d+)\,(\d+)\,(\d+)/) { &error("Subcategory color not specified correctly."); }
633
634   $r_subcategory_color = $1 / 255;
635   &error("Subcategory color: invalid red component.") if $r_subcategory_color > 1;
636   $g_subcategory_color = $2 / 255;
637   &error("Subcategory color: invalid green component.") if $g_subcategory_color > 1;
638   $b_subcategory_color = $3 / 255;
639   &error("Subcategory color: invalid blue component.") if $b_subcategory_color > 1;
640}
641
642# TEXT color
643
644my $r_text_color = 0;   # default color is black
645my $g_text_color = 0;
646my $b_text_color = 0;
647
648if ($TEXT_COLOR)
649{
650   if ($TEXT_COLOR !~ /(\d+)\,(\d+)\,(\d+)/) { &error("Text color not specified correctly."); }
651
652   $r_text_color = $1 / 255;
653   &error("Text color: invalid red component.") if $r_text_color > 1;
654   $g_text_color = $2 / 255;
655   &error("Text color: invalid green component.") if $g_text_color > 1;
656   $b_text_color = $3 / 255;
657   &error("Text color: invalid blue component.") if $b_text_color > 1;
658}
659
660# Tray Overlay
661# first - get arguments for scaling with optional translate
662if (defined($TRAY_OVERLAY_SCALERATIO)) {
663    ($eps_tray_overlay_scale, $tray_overlay_image_xoffset, $tray_overlay_image_yoffset) = split( /,/, $TRAY_OVERLAY_SCALERATIO, 3);
664    unless ( $eps_tray_overlay_scale =~ /^([+]?\d+)$|([+]?(\d+\.\d+|\d+\.|\.\d+))$/ ) {
665      &error("--tray-overlay-scaleratio scale ratio must be a positive integer or floating point number");
666    }
667    if (defined($tray_overlay_image_xoffset)) {
668      $tray_overlay_image_yoffset = "" unless (defined($tray_overlay_image_yoffset));
669      unless (
670        $tray_overlay_image_xoffset =~ /^([+-]?\d+)$|([+-]?(\d+\.\d+|\d+\.|\.\d+))$/ &&
671        $tray_overlay_image_yoffset =~ /^([+-]?\d+)$|([+-]?(\d+\.\d+|\d+\.|\.\d+))$/ ) {
672        &error("-tray-overlay-scaleratio <scale>[,<xoffset>,<yoffset>] offset in inches must be a pair of numbers: x,y");
673      }
674    } else {
675        $tray_overlay_image_xoffset = 0;
676        $tray_overlay_image_yoffset = 0;
677    }
678    if ($eps_tray_overlay_scale == 0.0 && ($tray_overlay_image_xoffset != 0 || $tray_overlay_image_yoffset != 0)) {
679      warn("$0: Warning: -tray-overlay-scaleratio <scale>[,<xoffset>,<yoffset>] scale is zero, so no image translate possible\n");
680    }
681}
682else { # Else, no scaling
683    $eps_tray_overlay_scale = 1;
684    $tray_overlay_image_xoffset = 0;
685    $tray_overlay_image_yoffset = 0;
686}
687# now use the scale/offset args to assemble the tray overlay itselfn
688if ($TRAY_OVERLAY)
689{
690    $eps_tray_overlay_file = get_file_contents($TRAY_OVERLAY,@where_is_the_template);
691    $eps_tray_overlay_bounds = &get_bounding_box($TRAY_OVERLAY, $eps_tray_overlay_scale);
692}
693else {
694    $eps_tray_overlay_bounds = $default_bounds;
695    $eps_tray_overlay_file = '';
696}
697
698######################################################################
699# Grab the template
700
701my $psout = get_file_contents($template);
702
703$psout =~ s/TOKEN_BAN_STRING/$category/;
704$psout =~ s/TOKEN_SUBBAN_STRING/$subcategory/g;
705$psout =~ s/TOKEN_DATE/$date/g;
706$psout =~ s/TOKEN_ITEMS_TRAY/ @tray_items/g; # space makes first item indented same as following items
707$psout =~ s/TOKEN_ITEMS_COVER/ @cover_items/g; # space makes first item indented same as following items
708$psout =~ s/TOKEN_EPS_BOUNDS/$eps_cover_bounds/g;
709$psout =~ s/TOKEN_COVER_EPS/$eps_cover_file/g;
710$psout =~ s/TOKEN_TRAY_CARD_BOUNDS/$eps_tray_card_bounds/g;
711$psout =~ s/TOKEN_TRAY_CARD_EPS/$eps_tray_card_file/g;
712$psout =~ s/TOKEN_TRAY_PLAQUE_P/$show_tray_plaque/;
713$psout =~ s/TOKEN_COVER_PLAQUE_P/$show_cover_plaque/;
714$psout =~ s/TOKEN_NORMAL_CDCASE/$normalcdcase/;
715$psout =~ s/TOKEN_SLIM_CASE/$slimcase/;
716$psout =~ s/TOKEN_SLIM_DOUBLE_CASE/$slimdoublecase/;
717$psout =~ s/TOKEN_DOUBLE_CASE/$doublecase/;
718$psout =~ s/TOKEN_ENVELOPE_CDCASE/$envelopecdcase/;
719$psout =~ s/TOKEN_INSIDE_DVDCASE/$insidedvdcase/;
720$psout =~ s/TOKEN_OUTSIDE_DVDCASE/$outsidedvdcase/;
721$psout =~ s/TOKEN_CDLABEL/$cdlabel/;
722$psout =~ s/TOKEN_ENABLE_ITEM_SCALING_P/$enable_item_scaling/;
723$psout =~ s/TOKEN_Y_OFFSET_INCHES/$yoffset/;
724$psout =~ s/TOKEN_X_OFFSET_INCHES/$xoffset/;
725$psout =~ s/TOKEN_COVER_IMAGE_X_OFFSET_INCHES/$cover_image_xoffset/;
726$psout =~ s/TOKEN_COVER_IMAGE_Y_OFFSET_INCHES/$cover_image_yoffset/;
727$psout =~ s/TOKEN_TRAY_IMAGE_X_OFFSET_INCHES/$tray_image_xoffset/;
728$psout =~ s/TOKEN_TRAY_IMAGE_Y_OFFSET_INCHES/$tray_image_yoffset/;
729$psout =~ s/TOKEN_EDGE_LINE_WIDTH/$edge_line_width/;
730$psout =~ s/TOKEN_R_PLAQUE_COLOR/$r_plaque_color/;
731$psout =~ s/TOKEN_G_PLAQUE_COLOR/$g_plaque_color/;
732$psout =~ s/TOKEN_B_PLAQUE_COLOR/$b_plaque_color/;
733$psout =~ s/TOKEN_R_CATEGORY_COLOR/$r_category_color/;
734$psout =~ s/TOKEN_G_CATEGORY_COLOR/$g_category_color/;
735$psout =~ s/TOKEN_B_CATEGORY_COLOR/$b_category_color/;
736$psout =~ s/TOKEN_R_SUBCATEGORY_COLOR/$r_subcategory_color/;
737$psout =~ s/TOKEN_G_SUBCATEGORY_COLOR/$g_subcategory_color/;
738$psout =~ s/TOKEN_B_SUBCATEGORY_COLOR/$b_subcategory_color/;
739$psout =~ s/TOKEN_R_TEXT_COLOR/$r_text_color/;
740$psout =~ s/TOKEN_G_TEXT_COLOR/$g_text_color/;
741$psout =~ s/TOKEN_B_TEXT_COLOR/$b_text_color/;
742$psout =~ s/TOKEN_OUTSIDE_FOLDOUT_P/$outside_foldout/g;
743$psout =~ s/TOKEN_ROTATE_ENDCAPS_P/$rotate_endcaps/;
744$psout =~ s/TOKEN_COUNT_ROWS/$count_rows/;
745$psout =~ s/TOKEN_COUNT_COLS/$count_cols/;
746$psout =~ s/TOKEN_TRAY_OVERLAY_BOUNDS/$eps_tray_overlay_bounds/g;
747$psout =~ s/TOKEN_TRAY_OVERLAY_EPS/$eps_tray_overlay_file/g;
748$psout =~ s/TOKEN_TRAY_OVERLAY_IMAGE_X_OFFSET_INCHES/$tray_overlay_image_xoffset/;
749$psout =~ s/TOKEN_TRAY_OVERLAY_IMAGE_Y_OFFSET_INCHES/$tray_overlay_image_yoffset/;
750
751if ($print_to_file) { print OUT $psout; }
752else { print $psout; }
753##################################################################################
754# Subroutines
755
756sub get_date {
757   my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
758   $mon++;
759   if ($mon  < 10) { $mon = "0$mon"; }
760   if ($mday < 10) { $mday = "0$mday"; }
761   $year += 1900;
762   return "$year-$mon-$mday";     # ISO 8601:1988
763}
764
765
766sub get_full_filename {
767    my $fname = shift @_;
768    my ($directory,$realname,$found);
769    $found=0;
770    $realname=$fname;
771    foreach $directory ("",@_) {
772        if ( -f "$directory$fname") {
773            $realname = "$directory$fname";
774            $found = 1;
775            last;
776        }
777    }
778    return $realname;
779}
780
781
782sub get_file_contents {
783    my $fname = shift @_;
784    local $/ = undef;
785    my ($directory,$realname,$found);
786    $found=0;
787    foreach $directory ("",@_) {
788        if (open (GET_FILE, "$directory$fname")) {
789            $realname = "$directory$fname";
790            $found = 1;
791            last;
792        }
793    }
794    unless ($found) {    &error("Cannot open $fname") }
795    $_ = <GET_FILE>;
796    close GET_FILE;
797
798        # check end-of-line delimter, make is \n, which is what
799        # input will be split on...
800    s/$CR?$LF/\n/g; # variables from Socket package
801
802    $_ .= "\n" unless m/\n$/; # make sure last item is included
803
804    return $_;
805}
806
807
808sub scrub {
809    my $string = shift @_;
810    $string =~ s?\(?\\050?g;
811    $string =~ s?\)?\\051?g;
812    return $string;
813}
814
815
816sub get_bounding_box {
817    my $file = shift @_;
818    my $eps_scale = shift @_;
819    my $bounds;
820    my $got_bounding_box = 0;
821    $/ = $default_eol;
822    open (EPS, get_full_filename("$file",@where_is_the_template)) or &error("Cannot open epsfile $file");
823    while (<EPS>) {
824        chomp;
825        if (s/\%\%BoundingBox: //) {
826            my ($llx, $lly, $urx, $ury) = split (/\s/, $_);
827            $bounds ="\n/bound1x $llx def\n/bound1y $lly def\n/bound2x $urx def\n/bound2y $ury def\n";
828	    if ($eps_scale =~ /fill1|0.0/) { # -T option only
829		  $bounds .="/trayimage_fill_all false def\n";
830		  $bounds .="/scaleratio 0.0 def\n";
831	    } elsif ($eps_scale =~ /fill2/) { # -T option only
832		  $bounds .="/trayimage_fill_all true def\n";
833		  $bounds .="/scaleratio 0.0 def\n";
834	    } else {
835		  $bounds .="/scaleratio $eps_scale def\n";
836	    }
837            $got_bounding_box = 1;
838            last;
839        }
840    }
841    unless ($got_bounding_box) {
842        &error("Cannot get BoundingBox from $file. Are you sure it's an EPS file?");
843    }
844undef $/;
845    return $bounds;
846}
847
848# Ugh. This is nasty and hackish, but it sort of does the trick. If
849# anyone can improve the word wrapping capability (either in this
850# routine(yuck) or in the postscript (yay!), *please* do and send me
851# the diffs.  I'd love to do this in postscript, but I just don't have
852# the time right now.
853sub word_wrap {
854   my @long_items = @_;
855   my $long_item;
856   my @long_item;
857   my $max_chars;
858   my @wrapped_items;
859
860   # Account for the super long possibilities of the single column display
861   # Note that by wrapping, it may add a column (or 2), so account for that!
862   # Jan 2002: With no wrapping, the current template.ps can handle
863   # a minimum of these many items (assuming no title/subtiutle on tray):
864   # 1 col -> 60
865   # 2 col -> 120
866   # 3 col -> 180
867   # 4 col -> 240
868   # 5 col -> 300
869   # Since the cover is slightly larger,
870   # it can take one additional item in each column
871
872 SWITCH: {
873      ($#long_items < 40)  && do { $max_chars = 135; last SWITCH;}; # try 1 cols
874      ($#long_items < 100) && do { $max_chars = 107; last SWITCH;}; # try 2 cols
875      ($#long_items < 160) && do { $max_chars = 79; last SWITCH;}; # try 3 cols
876      ($#long_items < 220) && do { $max_chars = 51; last SWITCH;}; # try 4 cols
877      $max_chars = 23;                                             # need 5 cols
878   }
879
880   foreach $long_item (@long_items) {
881
882      @long_item = split(/(\s+)/, $long_item);
883      my $len = 0;
884      my $wrapped = "";
885
886      foreach (@long_item) {
887      $len += length($_);
888      if ($len > $max_chars) {
889              push (@wrapped_items, $wrapped);
890         # remove leading spaces
891              $_ =~ s/^\s+//g;
892              $wrapped = "   $_"; # indent wrapped lines a bit
893          $len = length($wrapped);
894      } else {
895          $wrapped .= $_;
896      }
897      }
898      push (@wrapped_items, $wrapped);
899   }
900   return @wrapped_items;
901}
902
903
904sub show_help {
905    print <<EOT;
906cdlabelgen, 4.1.0: (C) Avinash Chopde <avinash\@aczoom.com>  www.aczoom.com
907usage: $0
908   -c, --category <category>
909   -s, --subcategory <subcategory>
910   -i, --items <item1%item2%etc>
911   -f, --items-from-file <itemsfile>
912   -v, --cover-items <num_items_cover>
913   -e, --cover-image <cover_epsfile>
914   -S, --cover-image-scaleratio <cover_eps_scaleratio>[,<image_x_offset>,<image_y_offset_inches>]
915   -E, --tray-image <tray_epsfile>
916   -T, --tray-image-scaleratio <tray_eps_scaleratio>[,<image_x_offset>,<image_y_offset_inches>]
917   -d, --date <date>
918   -D, --no-date
919   -o, --output-file <outputfile>
920   -t, --cover-template <template>
921   -b, --no-tray-plaque
922   -C, --no-cover-plaque
923   -w, --tray-word-wrap
924   -h, --help
925   -m, --slim-case
926       --double-case
927       --slim-double-case
928   -M, --create-envelope
929       --create-dvd-inside
930       --create-dvd-outside
931       --create-cdlabel
932   -O, --outside-foldout
933       --rotate-endcaps
934   -p, --clip-items
935   -y, --page-offset [<page_x_offset>,]<page_y_offset_inches>
936   -l, --line-width <line_width_points>
937       --plaque-color <r_0_to_255>,<g_0_to_255>,<b_0_to_255>
938       --category-color <r_0_to_255>,<g_0_to_255>,<b_0_to_255>
939       --subcategory-color <r_0_to_255>,<g_0_to_255>,<b_0_to_255>
940       --text-color  <r_0_to_255>,<g_0_to_255>,<b_0_to_255>
941   -n, --number-in-set <number-in-set/volume info>
942   --rows-columns <count_rows_for_items,count_columns_for_items>
943   --tray-overlay <tray_overlay_epsfile>
944   --tray-overlay-scaleratio <scaleratio>[,<x_offset>,<y_offset_inches>]
945EOT
946exit 255;
947}
948
949
950sub error {
951    my $err = shift @_;
952    warn "$0: $err\n\n";
953    &show_help;
954}
955
956__END__
957