1/*********************************************************************** 2 * * 3 * $Id: hpgspen.c 298 2006-03-05 18:18:03Z softadm $ 4 * * 5 * hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript * 6 * API for rendering a scene and thus renders to a variety of * 7 * devices and fileformats. * 8 * * 9 * (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at * 10 * * 11 * Author: Wolfgang Glas * 12 * * 13 * hpgs is free software; you can redistribute it and/or * 14 * modify it under the terms of the GNU Lesser General Public * 15 * License as published by the Free Software Foundation; either * 16 * version 2.1 of the License, or (at your option) any later version. * 17 * * 18 * hpgs is distributed in the hope that it will be useful, * 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 21 * Lesser General Public License for more details. * 22 * * 23 * You should have received a copy of the GNU Lesser General Public * 24 * License along with this library; if not, write to the * 25 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * 26 * Boston, MA 02111-1307 USA * 27 * * 28 *********************************************************************** 29 * * 30 * The implementation of the HPGL reader. * 31 * * 32 ***********************************************************************/ 33 34#include <hpgsreader.h> 35#include <math.h> 36#include <string.h> 37#include <ctype.h> 38 39/* 40 Internal 41*/ 42static int hpgs_reader_set_number_of_pens(hpgs_reader *reader, int npens) 43{ 44 double *pw =(double *)realloc(reader->pen_widths,npens*sizeof(double)); 45 46 if (!pw) 47 return hpgs_set_error(hpgs_i18n("Out of memory growing pen width array.")); 48 49 reader->pen_widths = pw; 50 51 hpgs_color *pc = (hpgs_color *)realloc(reader->pen_colors,npens*sizeof(hpgs_color)); 52 53 if (!pc) 54 return hpgs_set_error(hpgs_i18n("Out of memory growing pen color array.")); 55 56 reader->pen_colors = pc; 57 58 for (;reader->npens<npens;++reader->npens) 59 { 60 reader->pen_widths[reader->npens] = 1.0; 61 reader->pen_colors[reader->npens].r = 0.0; 62 reader->pen_colors[reader->npens].g = 0.0; 63 reader->pen_colors[reader->npens].b = 0.0; 64 } 65 66 return 0; 67} 68 69/* 70 Do the pen select. 71*/ 72int hpgs_reader_do_setpen(hpgs_reader *reader, int pen) 73{ 74 double width; 75 76 if (hpgs_reader_checkpath(reader)) return -1; 77 78 if (pen < 0) 79 return hpgs_set_error(hpgs_i18n("Illegal pen numer %d."),pen); 80 81 if (pen >= reader->npens) 82 { 83 if (pen < 256) 84 { 85 if (hpgs_reader_set_number_of_pens(reader,pen+1)) 86 return -1; 87 } 88 else 89 { 90 if (reader->verbosity) 91 hpgs_log(hpgs_i18n("Illegal pen number %d replaced by %d.\n"), 92 pen, pen % reader->npens); 93 pen = pen % reader->npens; 94 } 95 } 96 97 reader->current_pen = pen; 98 99 width = reader->pen_widths[pen]; 100 101 if (reader->pen_width_relative) 102 width *= hypot(reader->P2.x-reader->P1.x, 103 reader->P2.y-reader->P1.y ) * 0.001 * HP_TO_PT; 104 else 105 width *= HP_TO_PT / reader->world_scale; 106 107 width *= reader->page_scale; 108 109 if (hpgs_setlinewidth(reader->device,width*reader->lw_factor)) 110 return -1; 111 112 return hpgs_setrgbcolor(reader->device, 113 &reader->pen_colors[pen]); 114} 115 116/* 117 HPGL command NP (Number of Pens) 118*/ 119int hpgs_reader_do_NP (hpgs_reader *reader) 120{ 121 int npens=8; 122 123 if (!reader->eoc && 124 hpgs_reader_read_int(reader,&npens)) return -1; 125 126 if (npens <= reader->npens) return 0; 127 128 return hpgs_reader_set_number_of_pens(reader,npens); 129} 130 131/* 132 HPGL command SP (Set Pen) 133*/ 134int hpgs_reader_do_SP (hpgs_reader *reader) 135{ 136 int pen=0; 137 138 if (!reader->eoc && 139 hpgs_reader_read_int(reader,&pen)) return -1; 140 141 return hpgs_reader_do_setpen(reader,pen); 142} 143 144/* 145 HPGL command PC (Pen Color) 146*/ 147int hpgs_reader_do_PC (hpgs_reader *reader) 148{ 149 int pen=-1; 150 double r=-1.0e20,g=-1.0e20,b=-1.0e20; 151 152 if (!reader->eoc && hpgs_reader_read_int(reader,&pen)) return -1; 153 if (!reader->eoc && hpgs_reader_read_double(reader,&r)) return -1; 154 if (!reader->eoc && hpgs_reader_read_double(reader,&g)) return -1; 155 if (!reader->eoc && hpgs_reader_read_double(reader,&b)) return -1; 156 157 if (pen >= reader->npens) 158 { 159 if (pen < 256) 160 { 161 if (hpgs_reader_set_number_of_pens(reader,pen+1)) 162 return -1; 163 } 164 else 165 { 166 if (reader->verbosity) 167 hpgs_log(hpgs_i18n("PC: Illegal pen number %d.\n"),pen); 168 169 return 0; 170 } 171 } 172 173 if (pen < 0) 174 { 175 hpgs_reader_set_std_pen_colors(reader,0,reader->npens); 176 pen = reader->current_pen; 177 } 178 else 179 { 180 if (r==-1.0e20 || g==-1.0e20 || b==-1.0e20) 181 { 182 hpgs_reader_set_std_pen_colors(reader,pen,1); 183 } 184 else 185 { 186 reader->pen_colors[pen].r = 187 (r - reader->min_color.r) / (reader->max_color.r - reader->min_color.r); 188 if (reader->pen_colors[pen].r < 0.0) reader->pen_colors[pen].r = 0.0; 189 if (reader->pen_colors[pen].r > 1.0) reader->pen_colors[pen].r = 1.0; 190 191 reader->pen_colors[pen].g = 192 (g - reader->min_color.g) / (reader->max_color.g - reader->min_color.g); 193 if (reader->pen_colors[pen].g < 0.0) reader->pen_colors[pen].g = 0.0; 194 if (reader->pen_colors[pen].g > 1.0) reader->pen_colors[pen].g = 1.0; 195 196 reader->pen_colors[pen].b = 197 (b - reader->min_color.b) / (reader->max_color.b - reader->min_color.b); 198 if (reader->pen_colors[pen].b < 0.0) reader->pen_colors[pen].b = 0.0; 199 if (reader->pen_colors[pen].b > 1.0) reader->pen_colors[pen].b = 1.0; 200 } 201 } 202 203 if (pen == reader->current_pen) 204 if (hpgs_setrgbcolor(reader->device, 205 &reader->pen_colors[pen])) 206 return -1; 207 208 return 0; 209} 210 211/* 212 HPGL command CR (Color Range) 213*/ 214int hpgs_reader_do_CR (hpgs_reader *reader) 215{ 216 reader->min_color.r = 0.0; 217 reader->min_color.g = 0.0; 218 reader->min_color.b = 0.0; 219 220 reader->max_color.r = 255.0; 221 reader->max_color.g = 255.0; 222 reader->max_color.b = 255.0; 223 224 if (!reader->eoc) 225 { 226 if (hpgs_reader_read_double(reader,&reader->min_color.r)) return -1; 227 if (reader->eoc) return -1; 228 if (hpgs_reader_read_double(reader,&reader->max_color.r)) return -1; 229 if (reader->eoc) return -1; 230 if (hpgs_reader_read_double(reader,&reader->min_color.g)) return -1; 231 if (reader->eoc) return -1; 232 if (hpgs_reader_read_double(reader,&reader->max_color.g)) return -1; 233 if (reader->eoc) return -1; 234 if (hpgs_reader_read_double(reader,&reader->min_color.b)) return -1; 235 if (reader->eoc) return -1; 236 if (hpgs_reader_read_double(reader,&reader->max_color.b)) return -1; 237 } 238 239 return 0; 240} 241 242/* 243 HPGL command LA (Line Attributes) 244*/ 245int hpgs_reader_do_LA(hpgs_reader *reader) 246{ 247 int kind; 248 int ivalue; 249 double rvalue; 250 251 static hpgs_line_cap caps[5] = 252 { hpgs_cap_butt, 253 hpgs_cap_butt, 254 hpgs_cap_square, 255 hpgs_cap_round, 256 hpgs_cap_round }; 257 258 static hpgs_line_join joins[7] = 259 { hpgs_join_miter, 260 hpgs_join_miter, 261 hpgs_join_miter, 262 hpgs_join_miter, 263 hpgs_join_round, 264 hpgs_join_bevel, 265 hpgs_join_miter }; 266 267 while (!reader->eoc) 268 { 269 if (hpgs_reader_read_int(reader,&kind)) return -1; 270 if (reader->eoc) return -1; 271 272 switch (kind) 273 { 274 case 3: 275 if (hpgs_reader_read_double(reader,&rvalue)) return -1; 276 if (hpgs_setmiterlimit(reader->device,rvalue)) return -1; 277 break; 278 case 1: 279 if (hpgs_reader_read_int(reader,&ivalue)) return -1; 280 if (ivalue >= 0 && ivalue < 5 && 281 hpgs_setlinecap(reader->device,caps[ivalue])) return -1; 282 break; 283 case 2: 284 if (hpgs_reader_read_int(reader,&ivalue)) return -1; 285 if (ivalue >= 0 && ivalue < 7 && 286 hpgs_setlinejoin(reader->device,joins[ivalue])) return -1; 287 break; 288 default: 289 return -1; 290 } 291 } 292 return 0; 293} 294 295/* 296 HPGL command LT (Line Type) 297*/ 298int hpgs_reader_do_LT(hpgs_reader *reader) 299{ 300 float dashes[20]; 301 int i,ndash; 302 int linetype=0; 303 double patlen = 4.0; 304 int mode = 0; 305 306 if (hpgs_reader_checkpath(reader)) return -1; 307 308 if (!reader->eoc && 309 hpgs_reader_read_int(reader,&linetype)) return -1; 310 311 if (!reader->eoc && 312 hpgs_reader_read_double(reader,&patlen)) return -1; 313 314 if (!reader->eoc && 315 hpgs_reader_read_int(reader,&mode)) return -1; 316 317 if (linetype < -8 || linetype > 8) 318 { 319 if (reader->verbosity) 320 hpgs_log(hpgs_i18n("LT: Illegal linetype %d.\n"),linetype); 321 return 0; 322 } 323 324 // line type are store as percentages. 325 patlen *= 0.01; 326 327 if (mode) 328 patlen *= MM_TO_PT; 329 else 330 patlen *= hypot(reader->P2.x-reader->P1.x, 331 reader->P2.y-reader->P1.y ) * 0.01 * HP_TO_PT; 332 333 ndash = reader->linetype_nsegs[linetype+8]; 334 if (ndash > 20) ndash = 20; 335 336 for (i=0;i<ndash;++i) 337 dashes[i] = reader->linetype_segs[linetype+8][i] * patlen; 338 339 return hpgs_setdash(reader->device, 340 dashes,ndash,0.0); 341} 342 343/* 344 HPGL command PW (Pen Width) 345*/ 346int hpgs_reader_do_PW (hpgs_reader *reader) 347{ 348 int pen=-1; 349 double width=1.0; 350 351 if (!reader->eoc) 352 if (hpgs_reader_read_double(reader,&width)) return -1; 353 if (!reader->eoc) 354 { 355 if (hpgs_reader_read_int(reader,&pen)) return -1; 356 357 if (pen < 0 || pen >= reader->npens) 358 { 359 if (pen >= reader->npens && pen < 256) 360 { 361 if (hpgs_reader_set_number_of_pens(reader,pen+1)) 362 return -1; 363 } 364 else 365 { 366 if (reader->verbosity) 367 hpgs_log(hpgs_i18n("PW: Illegal pen number %d.\n"),pen); 368 369 return 0; 370 } 371 } 372 } 373 374 if (reader->verbosity >= 2) 375 hpgs_log("PW: pen,width,rel = %d,%g,%d.\n",pen,width,reader->pen_width_relative); 376 377 if (reader->pen_width_relative) 378 width *= 10.0; 379 else 380 width *= MM_TO_PT; 381 382 if (pen < 0) 383 { 384 int i; 385 for (i=0;i<reader->npens;++i) 386 reader->pen_widths[i] = width; 387 } 388 else 389 reader->pen_widths[pen] = width; 390 391 if (pen < 0 || pen == reader->current_pen) 392 { 393 if (hpgs_reader_checkpath(reader)) return -1; 394 395 if (reader->pen_width_relative) 396 width *= hypot(reader->P2.x-reader->P1.x, 397 reader->P2.y-reader->P1.y ) * 0.001 * HP_TO_PT; 398 else 399 width *= HP_TO_PT / reader->world_scale; 400 401 width *= reader->page_scale; 402 403 if (hpgs_setlinewidth(reader->device,width*reader->lw_factor)) 404 return -1; 405 } 406 407 return 0; 408} 409 410/* 411 HPGL command WU (Width Unit selection) 412*/ 413int hpgs_reader_do_WU (hpgs_reader *reader) 414{ 415 reader->pen_width_relative=0; 416 417 if (!reader->eoc && 418 hpgs_reader_read_int(reader,&reader->pen_width_relative)) return -1; 419 return 0; 420} 421 422