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