From 98608a8ba0379cf62593478f4605b1e86e42b99c Mon Sep 17 00:00:00 2001 From: Werner LEMBERG Date: Sun, 27 Feb 2000 01:42:13 +0000 Subject: [PATCH] grolbp output device --- src/devices/grolbp/Makefile.sub | 6 + src/devices/grolbp/charset.h | 69 ++++ src/devices/grolbp/grolbp.man | 277 +++++++++++++++ src/devices/grolbp/lbp.cc | 726 ++++++++++++++++++++++++++++++++++++++++ src/devices/grolbp/lbp.h | 512 ++++++++++++++++++++++++++++ 5 files changed, 1590 insertions(+) create mode 100644 src/devices/grolbp/Makefile.sub create mode 100644 src/devices/grolbp/charset.h create mode 100644 src/devices/grolbp/grolbp.man create mode 100644 src/devices/grolbp/lbp.cc create mode 100644 src/devices/grolbp/lbp.h diff --git a/src/devices/grolbp/Makefile.sub b/src/devices/grolbp/Makefile.sub new file mode 100644 index 00000000..b061e0a7 --- /dev/null +++ b/src/devices/grolbp/Makefile.sub @@ -0,0 +1,6 @@ +PROG=grolbp +MAN1=grolbp.n +XLIBS=$(LIBDRIVER) $(LIBGROFF) +MLIB=$(LIBM) +OBJS=lbp.o +CCSRCS=lbp.cc diff --git a/src/devices/grolbp/charset.h b/src/devices/grolbp/charset.h new file mode 100644 index 00000000..adc76f42 --- /dev/null +++ b/src/devices/grolbp/charset.h @@ -0,0 +1,69 @@ +// Definition of the WP54 character set + +char symset[] = { +0x57,0x50,0x35,0x34,0x00,0x41,0x76,0x61,0x6e,0x74,0x47,0x61, +0x72,0x64,0x65,0x2d,0x42,0x6f,0x6f,0x6b,0x00,0x41,0x76, +0x61,0x6e,0x74,0x47,0x61,0x72,0x64,0x65,0x2d,0x44,0x65, +0x6d,0x69,0x00,0x41,0x76,0x61,0x6e,0x74,0x47,0x61,0x72, +0x64,0x65,0x2d,0x42,0x6f,0x6f,0x6b,0x4f,0x62,0x6c,0x69, +0x71,0x75,0x65,0x00,0x41,0x76,0x61,0x6e,0x74,0x47,0x61, +0x72,0x64,0x65,0x2d,0x44,0x65,0x6d,0x69,0x4f,0x62,0x6c, +0x69,0x71,0x75,0x65,0x00,0x42,0x6f,0x6f,0x6b,0x6d,0x61, +0x6e,0x2d,0x4c,0x69,0x67,0x68,0x74,0x00,0x42,0x6f,0x6f, +0x6b,0x6d,0x61,0x6e,0x2d,0x44,0x65,0x6d,0x69,0x00,0x42, +0x6f,0x6f,0x6b,0x6d,0x61,0x6e,0x2d,0x4c,0x69,0x67,0x68, +0x74,0x49,0x74,0x61,0x6c,0x69,0x63,0x00,0x42,0x6f,0x6f, +0x6b,0x6d,0x61,0x6e,0x2d,0x44,0x65,0x6d,0x69,0x49,0x74, +0x61,0x6c,0x69,0x63,0x00,0x43,0x65,0x6e,0x74,0x75,0x72, +0x79,0x53,0x63,0x68,0x6c,0x62,0x6b,0x2d,0x52,0x6f,0x6d, +0x61,0x6e,0x00,0x43,0x65,0x6e,0x74,0x75,0x72,0x79,0x53, +0x63,0x68,0x6c,0x62,0x6b,0x2d,0x42,0x6f,0x6c,0x64,0x00, +0x43,0x65,0x6e,0x74,0x75,0x72,0x79,0x53,0x63,0x68,0x6c, +0x62,0x6b,0x2d,0x49,0x74,0x61,0x6c,0x69,0x63,0x00,0x43, +0x65,0x6e,0x74,0x75,0x72,0x79,0x53,0x63,0x68,0x6c,0x62, +0x6b,0x2d,0x42,0x6f,0x6c,0x64,0x49,0x74,0x61,0x6c,0x69, +0x63,0x00,0x44,0x75,0x74,0x63,0x68,0x2d,0x52,0x6f,0x6d, +0x61,0x6e,0x00,0x44,0x75,0x74,0x63,0x68,0x2d,0x42,0x6f, +0x6c,0x64,0x00,0x44,0x75,0x74,0x63,0x68,0x2d,0x49,0x74, +0x61,0x6c,0x69,0x63,0x00,0x44,0x75,0x74,0x63,0x68,0x2d, +0x42,0x6f,0x6c,0x64,0x49,0x74,0x61,0x6c,0x69,0x63,0x00, +0x53,0x77,0x69,0x73,0x73,0x00,0x53,0x77,0x69,0x73,0x73, +0x2d,0x42,0x6f,0x6c,0x64,0x00,0x53,0x77,0x69,0x73,0x73, +0x2d,0x4f,0x62,0x6c,0x69,0x71,0x75,0x65,0x00,0x53,0x77, +0x69,0x73,0x73,0x2d,0x42,0x6f,0x6c,0x64,0x4f,0x62,0x6c, +0x69,0x71,0x75,0x65,0x00,0x53,0x77,0x69,0x73,0x73,0x2d, +0x4e,0x61,0x72,0x72,0x6f,0x77,0x00,0x53,0x77,0x69,0x73, +0x73,0x2d,0x4e,0x61,0x72,0x72,0x6f,0x77,0x2d,0x42,0x6f, +0x6c,0x64,0x00,0x53,0x77,0x69,0x73,0x73,0x2d,0x4e,0x61, +0x72,0x72,0x6f,0x77,0x2d,0x4f,0x62,0x6c,0x69,0x71,0x75, +0x65,0x00,0x53,0x77,0x69,0x73,0x73,0x2d,0x4e,0x61,0x72, +0x72,0x6f,0x77,0x2d,0x42,0x6f,0x6c,0x64,0x4f,0x62,0x6c, +0x69,0x71,0x75,0x65,0x00,0x5a,0x61,0x70,0x66,0x43,0x61, +0x6c,0x6c,0x69,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x2d, +0x52,0x6f,0x6d,0x61,0x6e,0x00,0x5a,0x61,0x70,0x66,0x43, +0x61,0x6c,0x6c,0x69,0x67,0x72,0x61,0x70,0x68,0x69,0x63, +0x2d,0x42,0x6f,0x6c,0x64,0x00,0x5a,0x61,0x70,0x66,0x43, +0x61,0x6c,0x6c,0x69,0x67,0x72,0x61,0x70,0x68,0x69,0x63, +0x2d,0x49,0x74,0x61,0x6c,0x69,0x63,0x00,0x5a,0x61,0x70, +0x66,0x43,0x61,0x6c,0x6c,0x69,0x67,0x72,0x61,0x70,0x68, +0x69,0x63,0x2d,0x42,0x6f,0x6c,0x64,0x49,0x74,0x61,0x6c, +0x69,0x63,0x00,0x5a,0x61,0x70,0x66,0x43,0x68,0x61,0x6e, +0x63,0x65,0x72,0x79,0x2d,0x4d,0x65,0x64,0x69,0x75,0x6d, +0x49,0x74,0x61,0x6c,0x69,0x63,0x00,0x00,0x09,0x00,0x0A, +0x00,0x0B,0x00,0x0E,0x00,0x14,0x00,0x17,0x00,0x18,0x00, +0x1F,0x00,0x20,0x00,0x36,0x00,0x37,0x00,0x38,0x00,0x45,0x00, +0x47,0x00,0x48,0x00,0x80,0x00,0x82,0x00,0x83,0x00,0x84, +0x00,0x85,0x00,0x87,0x00,0x8B,0x00,0x8C,0x00,0x8D,0x00,0x8E, +0x00,0x8F,0x00,0x90,0x00,0x91,0x00,0x92,0x00,0x95,0x00,0x96, +0x00,0x97,0x00,0x98,0x00,0x99,0x00,0x9C,0x00,0x9E,0x00, +0x9F,0x00,0xA0,0x00,0xA1,0x00,0xA2,0x00,0xA3,0x00,0xCB,0x00, +0xCC,0x00,0xCD,0x00,0xCE,0x00,0xD1,0x00,0xD3,0x00,0xD4, +0x00,0xD5,0x00,0xD6,0x00,0xFA,0x00,0xFB,0x00,0xFC,0x00,0xFD, +0x00,0xCF,0x00,0x26,0x00,0x7E,0x03,0x05,0x00,0xA5,0x00, +0xA6,0x00,0xA8,0x00,0xAA,0x00,0xAD,0x00,0xAE,0x00,0xAF,0x00, +0xB0,0x00,0xB1,0x00,0xB2,0x00,0xB3,0x00,0xB5,0x00,0xB6,0x00, +0xB8,0x00,0xB9,0x00,0xBA,0x00,0xBB,0x00,0xBC,0x00,0xBE, +0x00,0xBF,0x00,0xC0,0x00,0xC1,0x00,0xC6,0x00,0xDC,0x00,0xEB, +0x00,0xEC,0x00,0xF2,0x00,0xF3,0x00,0x15,0x00,0x16,0x00, +0x86 +}; diff --git a/src/devices/grolbp/grolbp.man b/src/devices/grolbp/grolbp.man new file mode 100644 index 00000000..cc0bf117 --- /dev/null +++ b/src/devices/grolbp/grolbp.man @@ -0,0 +1,277 @@ +.ig \"-*- nroff -*- +Copyright (C) 1994-2000 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. + +Modified by Francisco Andrés Verdú for the grolbp +program. +.. +.de TQ +.br +.ns +.TP \\$1 +.. +.\" Like TP, but if specified indent is more than half +.\" the current line-length - indent, use the default indent. +.de Tp +.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP +.el .TP "\\$1" +.. +.TH GROLBP @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" +.SH NAME +grolbp \- groff driver for Canon CAPSL printers (LBP-4 and LBP-8 series laser printers). +.SH SYNOPSIS +.nr a \n(.j +.ad l +.nr i \n(.i +.in +\w'\fBgrolbp 'u +.ti \niu +.B grolpb +.de OP +.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\ \\$2" "\ ]" +.el .RB "[\ " "\\$1" "\ ]" +.. +.OP \-l +.OP \-\-landscape +.OP \-v +.OP \-\-version +.OP \-c n +.OP \-\-copies numcopies +.OP \-p paper_size +.OP \-\-papersize paper_size +.OP \-o orientation +.OP \-\-orientation orientation +.OP \-F dir +.OP \-\-fontdir dir +.OP \-h +.OP \-\-help +.RI "[\ " files\|.\|.\|. "\ ]" +.br +.ad \na +.SH DESCRIPTION +.B grolbp +is a driver for +.B groff +that produces output in CAPSL and VDM format suitable for Canon LBP\-4 and +LBP\-8 printers. +.LP +For compatibility with grolj4 there is an additional drawing command +available: +.TP +.BI \eD'R\ dh\ dv ' +Draw a rule (i.e.\ a solid black rectangle), with one corner at the current +position, and the diagonally opposite corner at the current position +.RI +( dh , dv ). +.SH OPTIONS +Note that the whitespace between a one-letter option and its argument can be +omitted; on the other hand, there must be whitespace and/or an equal sign +(`=') between a long-name option and its argument. +.TP +.BI \-c \ numcopies +.TQ +.BI \-\-copies \ numcopies +Print +.I numcopies +copies of each page. +.TP +.B \-l +.TQ +.B \-\-landscape +Print the document with a landscape orientation. +.TP +.BI \-p \ paper_size +.TQ +.BI \-\-papersize \ paper_size +Set the paper size to +.IR paper_size , +which must be a valid paper size description as indicated in the section +.BR "PAPER SIZES" . +.TP +.BI \-o \ orientation +.TQ +.BI \-\-orientation \ orientation +Print the document with +.I orientation +orientation, which must be `portrait' or `landscape'. +.TP +.B \-v +.TQ +.B \-\-version +Print the version number. +.TP +.BI \-F \ dir +.TQ +.BI \-\-fontdir \ dir +Search directory +.IB dir /devlbp +for font and device description files. +.TP +.B \-h +.TQ +.B \-\-help +Print a short help text. +.SH TYPEFACES +The driver supports the Dutch, Swiss and Swiss-Narrow scalable typefaces, +each one in the Regular, Bold, Italic and Bold-Italic styles. +Additionally, the Courier and Elite monospaced typefaces at the sizes 8 and +12 points (for Courier) resp. 8 and 10 points (for Elite) are supported, +each one in the Regular, Bold and Italic styles. +.PP +The following chart summarizes the font names you can use to access these +fonts: +.PP +.TS +tab(|) allbox center; +c c c c c +ab c c c c +. +Typeface | Regular | Bold | Italic | Bold-Italic +Dutch | TR | TB | TI | TBI +Swiss | HR | HB | HI | HBI +Swiss Narrow | HNR | HNB | HNI | HNBI +Courier | CR | CB | CI | +Elite | ER | EB | EI | +.TE +.PP +.SH PAPER SIZES +The paper size can be set in the +.B DESC +file or with command line options to +.BR grolbp . +If the paper size is specified both ways, the command line options take +precedence over the contents of the +.B DESC +file (this applies to the page orientation too). +.PP +To set the paper size in the +.B DESC +file, insert in that file a line containing +.B papersize +.IR desired_papersize , +where +.I desired_papersize +is: +.IP \(bu 4 +One of the recognized paper sizes: `a4', `letter', `legal' or `executive'. +.IP \(bu 4 +A custom defined paper size, as described in the +.B CUSTOM PAPER SIZES +subsection below. +.IP \(bu 4 +The name of a file (e.g. +.IR /etc/papersize ) +whose first line must be the desired paper size in one of the above formats. +.PP +If there are various papersize lines in the +.B DESC +file, only the first valid one is used. +.PP +To set the paper size in the command line, add +.sp 1 +.in +2m +.BI \-p \ desired_papersize +.in -2m +.sp 1 +or +.sp 1 +.in +2m +.BI \-\-papersize \ desired_papersize +.in -2m +.sp 1 +to the other +.B grolbp +options, where +.B desired_papersize +is in the same format as in the +.B DESC +file. +.PP +Paper sizes are case insensitive (i.e., `A4' is the same as `a4'). +.PP +If no paper size is specified in the +.B DESC +file or the command line, a default size of A4 is used. +.TP +.SH CUSTOM PAPER SIZES +Custom defined paper sizes are in the form +.BI cust length x width +where +.I length +and +.I width +are the dimensions of the paper you want to to use, specified in printer +units (1/300 of an inch). +For instance, to print in a postcard sized paper which is two inches long +and four inches wide you can insert a line containing +.sp 1 +.in +2m +.B papersize cust600x1200 +.in -2m +.sp 1 +at the beginning of the +.B DESC +file. +.SH PAGE ORIENTATION +As with the page size, the orientation of the printed page +.RB ( portrait +or +.BR landscape ) +can be set in the +.B DESC +file or with command line options. +It is also case insensitive. +.PP +To set the orientation in the +.B DESC +file, insert a line with the following content: +.sp 1 +.in +2m +.B orientation +.RB [ portrait | landscape ] +.in -2m +.sp 1 +As with paper sizes, only the first valid orientation command in the +.B DESC +file is used. +.PP +To set the page orientation with command line options you can use the +.B \-o +or +.B \-\-orientation +option with the same parameters +.RB ( portrait +or +.BR landscape ) +as in the +.B DESC +file. +Or you can use the +.B \-l +option to force the pages to be printed in landscape. +.SH FILES +.TP +.B @FONTDIR@/devlbp/DESC +Device description file. +.TP +.BI @FONTDIR@/devlbp/ F +Font description file for font +.IR F . +.SH SEE ALSO +.BR groff (@MAN1EXT@), +.BR @g@troff (@MAN1EXT@), +.BR groff_out (@MAN5EXT@), +.BR groff_font (@MAN5EXT@), +.BR groff_char (@MAN7EXT@) diff --git a/src/devices/grolbp/lbp.cc b/src/devices/grolbp/lbp.cc new file mode 100644 index 00000000..361a8fa4 --- /dev/null +++ b/src/devices/grolbp/lbp.cc @@ -0,0 +1,726 @@ +// -*- C++ -*- +/* Copyright (C) 1994 Free Software Foundation, Inc. + Written by Francisco Andrés Verdú with many ideas + taken from the other groff drivers. + + +This file is part of groff. + +groff is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +groff is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with groff; see the file COPYING. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* +TODO + + - Add X command to include bitmaps +*/ +#define _GNU_SOURCE +#include + +#include +#include "driver.h" +#include "lbp.h" +#include "charset.h" + + +static short int papersize = -1, // papersize + orientation = -1 , // orientation + paperlength = 0, // Custom Paper size + paperwidth = 0, + ncopies = 1; // Number of copies + +class lbp_font : public font { +public: + ~lbp_font(); + void handle_unknown_font_command(const char *command, const char *arg, + const char *filename, int lineno); + static lbp_font *load_lbp_font(const char *); + char *lbpname; + char is_scalable; +private: + lbp_font(const char *); +}; + + +class lbp_printer : public printer { +public: + lbp_printer(); + ~lbp_printer(); + void set_char(int, font *, const environment *, int, const char *name); + void draw(int code, int *p, int np, const environment *env); + void begin_page(int); + void end_page(int page_length); + font *make_font(const char *); + void end_of_line(); +private: + void set_line_thickness(int size, int dot = 0); + void vdmstart(); + void vdmflush(); // the name vdmend was already used in lbp.h + void setfillmode(int mode); + void lbp_printer::polygon( int hpos,int vpos,int np,int *p); + char *lbp_printer::font_name(const lbp_font *f, const int siz); + + int fill_pattern; + int fill_mode; + int cur_hpos; + int cur_vpos; + lbp_font *cur_font; + int cur_size; + unsigned short cur_symbol_set; + int line_thickness; +}; + +lbp_font::lbp_font(const char *nm) +: font(nm) +{ +} + +lbp_font::~lbp_font() +{ +} + +lbp_font *lbp_font::load_lbp_font(const char *s) +{ + lbp_font *f = new lbp_font(s); + f->lbpname = NULL; + f->is_scalable = 1; // Default is that fonts are scalable + if (!f->load()) { + delete f; + return 0; + } + return f; +} + + +void lbp_font::handle_unknown_font_command(const char *command, + const char *arg, + const char *filename, int lineno) +{ + if (strcmp(command, "lbpname") == 0) { + if (arg == 0) + fatal_with_file_and_line(filename, lineno, + "`%1' command requires an argument", + command); + this->lbpname = new char[strlen(arg)+1]; + strcpy(this->lbpname,arg); + // We Recongnize bitmaped fonts by the first character of it's name + if (arg[0] == 'N') this->is_scalable = 0; + // fprintf(stderr,"Loading font \"%s\" \n",arg); + }; // if (strcmp(command, "lbpname") + // fprintf(stderr,"Loading font %s \"%s\" in %s at %d\n",command,arg,filename,lineno); +}; + +static void wp54charset() +{ + int i; + + lbpputs("\033[714;100;29;0;32;120.}"); + for (i = 0; i < sizeof(symset) ; i++) lbpputc(symset[i]); + lbpputs("\033[100;0 D"); + return ; +}; + +lbp_printer::lbp_printer() +: fill_pattern(1), + fill_mode(0), + cur_hpos(-1), + cur_font(0), + cur_size(0), + cur_symbol_set(0), + line_thickness(-1) +{ + lbpinit(stdout); + lbpputs("\033c\033;\033[2&z\033[7 I\033[?32h\033[?33h\033[11h"); + wp54charset(); // Define the new symbol set + lbpputs("\033[7 I\033[?32h\033[?33h\033[11h"); + // Paper size handling + if (orientation < 0) orientation = 0;// Default orientation is portrait + if (papersize < 0) papersize = 14; // Default paper size is A4 + if (papersize < 80) // standard paper + lbpprintf("\033[%dp",(papersize | orientation)); + else // Custom paper + lbpprintf("\033[%d;%d;%dp",(papersize | orientation),\ + paperlength,paperwidth); + + // Number of copies + lbpprintf("\033[%dv\n",ncopies); + + lbpputs("\033[0u\033[1u\033P1y Grolbp\033\\"); + lbpmoveabs(0,0); + lbpputs("\033[0t\033[2t"); + lbpputs("\033('$2\033)' 1"); // Primary symbol set IBML + // Secondary symbol set IBMR1 + cur_symbol_set = 0; +}; + +lbp_printer::~lbp_printer() +{ + lbpputs("\033P1y\033\\"); + lbpputs("\033c\033<"); +} + +void lbp_printer::begin_page(int) +{ +} + +void lbp_printer::end_page(int) +{ + if (vdminited()) vdmflush(); + lbpputc('\f'); + cur_hpos = -1; +} + +void lbp_printer::end_of_line() +{ + cur_hpos = -1; // force absolute motion +} + +char *lbp_printer::font_name(const lbp_font *f, const int siz) +{ + static char bfont_name[255] ; // The resulting font name + char type, // Italic, Roman, Bold + ori, // Normal or Rotated + nam[strlen(f->lbpname)-2]; // The font name without other data. + int cpi; // The font size in characters per inch + // (Bitmaped fonts are monospaced). + + + /* Bitmap font selection is ugly in this printer, so don't expect + this function to be elegant. */ + + bfont_name[0] = 0x00; + if (orientation) // Landscape + ori = 'R'; + else // Portrait + ori = 'N'; + type = f->lbpname[strlen(f->lbpname)-1]; + strncpy(nam,&(f->lbpname[1]),strlen(f->lbpname)-2); + nam[strlen(f->lbpname)-2] = 0x00; + // fprintf(stderr,"Bitmap font '%s' %d %c %c \n",nam,siz,type,ori); + /* Since these fonts are avaiable only at certain sizes, + 10 and 17 cpi for courier, 12 and 17 cpi for elite, + we adjust the resulting size. */ + // Fortunately there were only two bitmaped fonts shiped with the printer. + if (!strcasecmp(nam,"courier")) + { // Courier font + if (siz >= 12) cpi = 10; + else cpi = 17; + }; + if (!strcasecmp(nam,"elite")) + { // Elite font + if (siz >= 10) cpi = 12; + else cpi = 17; + }; + + // Now that we have all the data, let's generate the font name. + if ((type != 'B') && (type != 'I')) // Roman font + sprintf(bfont_name,"%c%s%d",ori,nam,cpi); + else + sprintf(bfont_name,"%c%s%d%c",ori,nam,cpi,type); + + return bfont_name; + +}; // lbp_printer::font_name + +void lbp_printer::set_char(int index, font *f, const environment *env, int w, const char *name) +{ + int code = f->get_code(index); + + unsigned char ch = code & 0xff; + unsigned short symbol_set = code >> 8; + if (f != cur_font) { + lbp_font *psf = (lbp_font *)f; + // fprintf(stderr,"Loading font %s \"%d\" \n",psf->lbpname,env->size); + if (psf->is_scalable) + { // Scalable font selection is different from bitmaped + lbpprintf("\033Pz%s.IBML\033\\\033[%d C",psf->lbpname,\ + (int)((env->size*300)/72)); + } else + { // Bitmaped font + lbpprintf("\033Pz%s.IBML\033\\\n",font_name(psf,env->size)); + }; + lbpputs("\033)' 1"); // Select IBML and IBMR1 symbol set + cur_size = env->size; + cur_font = psf; + cur_symbol_set = 0; + } + if (symbol_set != cur_symbol_set) { + if ( cur_symbol_set == 3 ) { + // if current symbol set is Symbol we must restore the font + lbpprintf("\033Pz%s.IBML\033\\\033[%d C",cur_font->lbpname,\ + (int)((env->size*300)/72)); + }; // if ( cur_symbol_set == 3 ) + switch (symbol_set) { + case 0: lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets + break; + case 1: lbpputs("\033(d\033)' 1"); // Select wp54 symbol set + break; + case 2: lbpputs("\033('$2\033)'!0"); // Select IBMP symbol set + break; + case 3: lbpprintf("\033PzSymbol.SYML\033\\\033[%d C",\ + (int)((env->size*300)/72)); + lbpputs("\033(\"!!0\033)\"!!1"); // Select symbol font + break; + case 4: lbpputs("\033)\"! 1\033(\"!$2"); // Select PS symbol set + break; + }; // switch (symbol_set) + +// if (symbol_set == 1) lbpputs("\033(d"); // Select wp54 symbol set +// else lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets + cur_symbol_set = symbol_set; + } + if (env->size != cur_size) { + + if (!cur_font->is_scalable) + lbpprintf("\033Pz%s.IBML\033\\\n",font_name(cur_font,env->size)); + else + lbpprintf("\033[%d C",(int)((env->size*300)/72)); + cur_size = env->size; + } + if ((env->hpos != cur_hpos) || (env->vpos != cur_vpos)) + { + // lbpmoveabs(env->hpos - ((5*300)/16),env->vpos ); + lbpmoveabs(env->hpos - 64,env->vpos - 64 ); + cur_vpos = env->vpos; + cur_hpos = env->hpos; + }; + if ((ch & 0x7F) < 32) lbpputs("\033[1.v"); + lbpputc(ch); + cur_hpos += w; +}; + +void +lbp_printer::vdmstart() +{ + FILE *f; + static int changed_origin = 0; + + errno = 0; + f = tmpfile(); + // f = fopen("/tmp/gtmp","w+"); + if (f == NULL) perror("Openinig temp file"); + vdminit(f); + if (!changed_origin) { // we should change the origin only one time + changed_origin = 1; + vdmorigin(-63,0); + }; + vdmlinewidth(line_thickness); + +}; + +void +lbp_printer::vdmflush() +{ + char buffer[1024]; + int bytes_read = 1; + + vdmend(); + fflush(lbpoutput); + /* lets copy the vdm code to the output */ + rewind(vdmoutput); + do + { + bytes_read = fread(buffer,1,sizeof(buffer),vdmoutput); + bytes_read = fwrite(buffer,1,bytes_read,lbpoutput); + } while ( bytes_read == sizeof(buffer)); + + fclose(vdmoutput); // This will also delete the file, + // since it is created by tmpfile() + vdmoutput = NULL; + +}; // lbp_printer::vdmflush + +inline void +lbp_printer::setfillmode(int mode) +{ + if (mode != fill_mode) { + if (mode != 1) vdmsetfillmode(mode,1,0); + else vdmsetfillmode(mode,1,1); // To get black we must use white + // inverted + fill_mode = mode; + }; +}; // setfillmode + +inline void +lbp_printer::polygon( int hpos,int vpos,int np,int *p) +{ + int points[np+2],i; + + points[0] = hpos; + points[1] = vpos; +/* fprintf(stderr,"Poligon (%d,%d) ", points[0],points[1]);*/ + for (i = 0; i < np; i++) points[i+2] = p[i]; +/* for (i = 0; i < np; i++) fprintf(stderr," %d ",p[i]); + fprintf(stderr,"\n"); */ + vdmpolygon((np /2) + 1,points); +}; + +void lbp_printer::draw(int code, int *p, int np, const environment *env) +{ + switch (code) { + case 't': + if (np == 0) line_thickness = 1; + else { // troff gratuitously adds an extra 0 + if (np != 1 && np != 2) { + error("0 or 1 argument required for thickness"); + break; + } // if (np != ... + if (p[0] == 0) line_thickness = 1; + if (p[0] < 0) // Default = 1 point + line_thickness = (int)(env->size*30/72); + line_thickness = (int)((abs(p[0])*env->size)/10); + if ((line_thickness > 16 ) && (!vdminited())) + { /* for greater thickness we must use VDM */ + vdmstart(); + /* vdmlinewidth(line_thickness); already done in + * vdmstart() */ + }; + if (vdminited()) vdmlinewidth(line_thickness); + // fprintf(stderr,"\nthickness: %d == %d, size %d\n",\ + // p[0],line_thickness,env->size ); + break; + } // else + + case 'l': // Line + if (np != 2) { + error("2 arguments required for line"); + break; + }; + if (!vdminited()) vdmstart(); + vdmline(env->hpos,env->vpos,p[0],p[1]); + /*fprintf(stderr,"\nline: %d,%d - %d,%d thickness %d == %d\n",\ + env->hpos - 64,env->vpos -64, env->hpos - 64 + p[0],\ + env->vpos -64 + p[1],env->size, line_thickness);*/ + break; + case 'R': // Rule + if (np != 2) { + error("2 arguments required for Rule"); + break; + } + if (vdminited()) { + setfillmode(fill_pattern); // Solid Rule + vdmrectangle(env->hpos,env->vpos,p[0],p[1]); + } + else { + lbpruleabs(env->hpos - 64,env->vpos -64 , p[0], p[1]); + cur_vpos = p[1]; + cur_hpos = p[0]; + }; + fprintf(stderr,"\nrule: thickness %d == %d\n", env->size, line_thickness); + break; + case 'P': // Filled Polygon + if (!vdminited()) vdmstart(); + setfillmode(fill_pattern); + polygon(env->hpos,env->vpos,np,p); + break; + case 'p': // Empty Polygon + if (!vdminited()) vdmstart(); + setfillmode(0); + polygon(env->hpos,env->vpos,np,p); + break; + case 'C': // Filled Circle + if (!vdminited()) vdmstart(); + // fprintf(stderr,"Circle (%d,%d) Fill %d\n",env->hpos,env->vpos,fill_pattern); + setfillmode(fill_pattern); + vdmcircle(env->hpos + (p[0]/2),env->vpos,p[0]/2); + break; + case 'c': // Empty Circle + if (!vdminited()) vdmstart(); + setfillmode(0); + vdmcircle(env->hpos + (p[0]/2),env->vpos,p[0]/2); + break; + case 'E': // Filled Ellipse + if (!vdminited()) vdmstart(); + setfillmode(fill_pattern); + vdmellipse(env->hpos + (p[0]/2),env->vpos,p[0]/2,p[1]/2,0); + break; + case 'e': // Empty Ellipse + if (!vdminited()) vdmstart(); + setfillmode(0); + vdmellipse(env->hpos + (p[0]/2),env->vpos,p[0]/2,p[1]/2,0); + break; + case 'a': // Arc + if (!vdminited()) vdmstart(); + setfillmode(0); + // VDM draws arcs clockwise and pic counterclockwise + // We must compensate for that, exchanging the starting and + // ending points + vdmvarc(env->hpos + p[0],env->vpos+p[1],\ + int(sqrt( (p[0]*p[0])+(p[1]*p[1]))),\ + p[2],p[3],\ + (-p[0]),(-p[1]),1,2); + break; + case '~': // Spline + if (!vdminited()) vdmstart(); + setfillmode(0); + vdmspline(np/2,env->hpos,env->vpos,p); + break; + case 'f': + if (np != 1 && np != 2) { + error("1 argument required for fill"); + break; + }; + // fprintf(stderr,"Fill %d\n",p[0]); + if ((p[0] == 1) || (p[0] >= 1000)) { // Black + fill_pattern = 1; + break; + }; // if (p[0] == 1) + if (p[0] == 0) { // White + fill_pattern = 0; + break; + }; + if ((p[0] > 1) && (p[0] < 1000)) + { + if (p[0] >= 990) fill_pattern = -23; + else if (p[0] >= 700) fill_pattern = -28; + else if (p[0] >= 500) fill_pattern = -27; + else if (p[0] >= 400) fill_pattern = -26; + else if (p[0] >= 300) fill_pattern = -25; + else if (p[0] >= 200) fill_pattern = -22; + else if (p[0] >= 100) fill_pattern = -24; + else fill_pattern = -21; + }; // if (p[0] >= 0 && p[0] <= 1000) + break; + default: + error("unrecognised drawing command `%1'", char(code)); + break; + }; // switch (code) + return ; +}; + +font *lbp_printer::make_font(const char *nm) +{ + return lbp_font::load_lbp_font(nm); +} + + + +printer *make_printer() +{ + return new lbp_printer; +} + +static struct +{ + const char *name; + int code; +} papersizes[] = +{{ "A4", 14 }, +{ "letter", 30 }, +{ "legal", 32 }, +{ "executive", 40 }, +}; + +static int set_papersize(const char *papersize) +{ + int i; + + // First test for a standard (i.e. supported directly by the printer) + // papersize + for (i = 0 ; i < sizeof(papersizes)/sizeof(papersizes[0]); i++) + { + if (strcasecmp(papersizes[i].name,papersize) == 0) + return papersizes[i].code; + }; + + // Now test for a custom papersize + if (strncasecmp("cust",papersize,4) == 0) + { + char *p , + *p1, + *papsize; + + p = papsize = strdup(&papersize[4]); + if (papsize == NULL) return -1; + p1 = strsep(&p,"x"); + if (p == NULL) + { // let's test for an uppercase x + p = papsize ; + p1 = strsep(&p,"X"); + if (p == NULL) { free(papsize); return -1;}; + }; // if (p1 == NULL) + paperlength = atoi(p1); + if (paperlength == 0) { free(papsize); return -1;}; + paperwidth = atoi(p); + if (paperwidth == 0) { free(papsize); return -1;}; + free(papsize); + return 82; + }; // if (strcnasecmp("cust",papersize,4) == 0) + + return -1; +}; + +static int handle_papersize_command(const char *arg) +{ + int n = set_papersize(arg); + + if (n < 0) + { // If is not a standard nor custom paper size + // let's see if it's a file (i.e /etc/papersize ) + FILE *f = fopen(arg,"r"); + if (f != NULL) + { // the file exists and is readable + char psize[255],*p; + fgets(psize,254,f); + fclose(f); + // set_papersize doesn't like the trailing \n + p = psize; while (*p) p++; + if (*(--p) == '\n') *p = 0x00; + + n = set_papersize(psize); + }; // if (f != NULL) + }; // if (n < 0) + + return n; +}; // handle_papersize_command + + +static void handle_unknown_desc_command(const char *command, const char *arg, + const char *filename, int lineno) +{ + // papersize command + if (strcasecmp(command, "papersize") == 0) { + // We give priority to command line options + if (papersize > 0) return; + if (arg == 0) + error_with_file_and_line(filename, lineno, + "`papersize' command requires an argument"); + else + { + int n = handle_papersize_command(arg); + if (n < 0) + error_with_file_and_line(filename, lineno, + "unknown paper size `%1'", arg); + else + papersize = n; + + }; // if (arg == 0) ... else ... + }; // if (strcasecmp(command, "papersize") + + // orientation command + if (strcasecmp(command, "orientation") == 0) { + // We give priority to command line options + if (orientation > 0) return; + if (arg == 0) + error_with_file_and_line(filename, lineno, + "`papersize' command requires an argument"); + else { + if (strcasecmp(arg,"portrait") == 0) orientation = 0; + else { if (strcasecmp(arg,"landscape") == 0) orientation = 1; + else error_with_file_and_line(filename, lineno, + "`orientation' command requires an argument"); + }; + }; // if (arg == 0) ... else ... + }; // if (strcasecmp(command, "orientation") == 0) +}; + +static struct option long_options[] = { + {"orientation",1,NULL,'o'}, + {"version",0,NULL,'v'}, + {"copies",1,NULL,'c'}, + {"landscape",0,NULL,'l'}, + {"papersize",1,NULL,'p'}, + {"fontdir",1,NULL,'F'}, + {"help",0,NULL,'h'}, + {0, 0, 0, 0} + }; + +static void usage() +{ + fprintf(stderr, + "usage: %s [-lvh] [-c n] [-p paper_size] [-F dir] [-o or] "\ + " [files ...]\n"\ + " -o --orientation=[portrait|landscape]\n"\ + " -v --version\n"\ + " -c --copies=numcopies\n"\ + " -l --landscape\n"\ + " -p --papersize=paper_size\n"\ + " -F --fontdir=dir\n"\ + " -h --help\n", + program_name); + exit(1); +}; // usage + +int main(int argc, char **argv) +{ + if (program_name == NULL) program_name = strdup(argv[0]); + + font::set_unknown_desc_command_handler(handle_unknown_desc_command); + // command line parsing + int c = 0; + int digit_optind = 0, option_index = 0; + + while (c >= 0 ) + { + c = getopt_long (argc, argv, "F:p:lvo:c:h",\ + long_options, &option_index); + switch (c) { + case 'F' : font::command_line_font_dir(optarg); + break; + case 'p' : { + int n = handle_papersize_command(optarg); + if (n < 0) + error("unknown paper size `%1'", optarg); + else + papersize = n; + break; + }; + case 'l' : orientation = 1; + break; + case 'v' : { + extern const char *version_string; + fprintf(stderr, "grolbp version %s\n",\ + version_string); + fflush(stderr); + break; + }; + case 'o' : { + if (strcasecmp(optarg,"portrait") == 0) + orientation = 0; + else { + if (strcasecmp(optarg,"landscape") == 0) + orientation = 1; + else + error("unknown orientation '%1'", optarg); + }; + }; + break; + case 'c' : { + char *ptr; + long n = strtol(optarg, &ptr, 10); + if ((n <= 0) && (ptr == optarg)) + error("argument for -c must be a positive integer"); + else if (n <= 0 || n > 32767) + error("out of range argument for -c"); + else + ncopies = unsigned(n); + break; + } + case 'h' : usage(); + break; + + + }; // switch (c) + }; // while (c > 0 ) + + if (optind >= argc) + do_file("-"); + + while (optind < argc) { + do_file(argv[optind++]); + }; + + lbpputs("\033c\033<"); + return 0; +}; diff --git a/src/devices/grolbp/lbp.h b/src/devices/grolbp/lbp.h new file mode 100644 index 00000000..332d0a43 --- /dev/null +++ b/src/devices/grolbp/lbp.h @@ -0,0 +1,512 @@ + +// -*- C -*- +/* Copyright (C) 1994 Free Software Foundation, Inc. + Written by Francisco Andrés Verdú + +groff is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +groff is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with groff; see the file COPYING. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file contains a set of utility functions to use canon CAPSL printers + * (lbp-4 and lbp-8 series printers) */ + +#ifndef LBP_H +#define LBP_H + +#include +#include + +static FILE *lbpoutput = NULL; +static FILE *vdmoutput = NULL; + +static inline void +lbpinit(FILE *outfile) +{ + lbpoutput = outfile; +}; + + +static inline void +lbpprintf(char *format, ... ) +{ /* Taken from cjet */ + va_list stuff; + + va_start(stuff, format); + vfprintf(lbpoutput, format, stuff); + va_end(stuff); +}; + +static inline void +lbpputs(char *data) +{ + fputs(data,lbpoutput); +}; + +static inline void +lbpputc(char c) +{ + fputc(c,lbpoutput); +}; + + +static inline void +lbpsavestatus(int index ) +{ + fprintf(lbpoutput,"\033[%d%%y",index); +}; + +static inline void +lbprestorestatus(int index ) +{ + fprintf(lbpoutput,"\033[%d%cz",index ,'%'); +}; + +static inline void +lbpsavepos(int index) +{ + fprintf(lbpoutput,"\033[1;%d;0x",index); +}; + +static inline void +lbprestorepos(int index) +{ + fprintf(lbpoutput,"\033[0;%d;0x",index); +}; + +static inline void +lbprestoreposx(int index) +{ + fprintf(lbpoutput,"\033[0;%d;1x",index); +}; + +static inline void +lbpmoverel(int despl, char direction) +{ + fprintf(lbpoutput,"\033[%d%c",despl,direction); +}; + +static inline void +lbplinerel(int width,int despl,char direction ) +{ + fprintf(lbpoutput,"\033[%d;0;9{\033[%d%c\033[9}",width,despl,direction); +}; + +static inline void +lbpmoveabs(int x, int y) +{ + fprintf(lbpoutput,"\033[%d;%df",y,x); +}; + +static inline void +lbplineto(int x,int y, int width ) +{ + fprintf(lbpoutput,"\033[%d;0;9{",width); + lbpmoveabs(x,y); + fprintf(lbpoutput,"\033[9}\n"); +}; + +static inline void +lbpruleabs(int x, int y, int hsize, int vsize) +{ + lbpmoveabs(x,y); + fprintf(lbpoutput,"\033[0;9;000s"); + lbpmoveabs(x+hsize,y+vsize); + fprintf(lbpoutput,"\033[9r"); +}; + +static inline void vdmprintf(char *format, ... ); + +static inline char * +vdmnum(int num,char *result) +{ + char b1,b2,b3; + char *p = result; + int nm; + + nm = abs(num); + /* First byte 1024 - 32768 */ + b1 = ((nm >> 10) & 0x3F); + if (b1) *p++ = b1 | 0x40; + + /* Second Byte 16 - 1024 */ + b2 = ((nm >> 4) & 0x3F); + if ( b1 || b2) *p++= b2 | 0x40; + + /* Third byte 0 - 15 */ + b3 = ((nm & 0x0F) | 32); + if (num >= 0) b3 |= 16; + *p++ = b3; + *p = 0x00; /* End of the resulting string */ + return result; +}; + +static inline void +vdmorigin(int newx, int newy) +{ + char nx[4],ny[4]; + + vdmprintf("}\"%s%s\x1e",vdmnum(newx,nx),vdmnum(newy,ny)); +}; /* vdmorigin */ + + +static inline FILE * +vdminit(FILE *vdmfile) +{ + char scale[4],size[4],lineend[4]; + +/* vdmoutput = tmpfile();*/ + vdmoutput = vdmfile; + /* Initialize the VDM mode */ + vdmprintf("\033[0&}#GROLBP\x1e!0%s%s\x1e$\x1e}F%s\x1e",\ + vdmnum(-3,scale),vdmnum(1,size),vdmnum(1,lineend)); + return vdmoutput; + +}; + +static inline void +vdmend() +{ + vdmprintf("}p\x1e"); +}; + +static inline void +vdmprintf(char *format, ... ) +{ /* Taken from cjet */ + va_list stuff; + + if (vdmoutput == NULL) vdminit(tmpfile()); + va_start(stuff, format); + vfprintf(vdmoutput, format, stuff); + va_end(stuff); +}; + +static inline void +vdmsetfillmode(int pattern,int perimeter, int inverted) +{ + char patt[4],perim[4], + rot[4], /* rotation */ + espejo[4], /* espejo */ + inv[4]; /* Inverted */ + + vdmprintf("I%s%s%s%s%s\x1e",vdmnum(pattern,patt),\ + vdmnum(perimeter,perim),vdmnum(0,rot), + vdmnum(0,espejo),vdmnum(inverted,inv)); +}; + +static inline void +vdmcircle(int centerx, int centery, int radius) +{ + char x[4],y[4],rad[4]; + + vdmprintf("5%s%s%s\x1e",vdmnum(centerx,x),vdmnum(centery,y),\ + vdmnum(radius,rad)); +}; + +static inline void +vdmaarc(int centerx, int centery, int radius,int startangle,int angle,int style,int arcopen) +{ + char x[4],y[4],rad[4],stx[4],sty[4],styl[4],op[4]; + + vdmprintf("}6%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\ + vdmnum(centerx,x),vdmnum(centery,y),\ + vdmnum(radius,rad),vdmnum(startangle,stx),vdmnum(angle,sty),\ + vdmnum(style,styl)); +}; + +static inline void +vdmvarc(int centerx, int centery,int radius, int startx, int starty, int endx, int endy,\ + int style,int arcopen) +{ + char x[4],y[4],rad[4],stx[4],sty[4],enx[4],eny[4],styl[4],op[4]; + + vdmprintf("}6%s%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\ + vdmnum(centerx,x),vdmnum(centery,y),\ + vdmnum(radius,rad),vdmnum(startx,stx),vdmnum(starty,sty),\ + vdmnum(endx,enx),vdmnum(endy,eny),vdmnum(style,styl)); +}; + +static inline void +vdmellipse(int centerx, int centery, int radiusx, int radiusy,int rotation) +{ + char x[4],y[4],radx[4],rady[4],rotat[4]; + + vdmprintf("}7%s%s%s%s%s\x1e\n",vdmnum(centerx,x),vdmnum(centery,y),\ + vdmnum(radiusx,radx),vdmnum(radiusy,rady),\ + vdmnum(rotation,rotat)); +}; + +static inline void +vdmsetlinetype(int lintype) +{ + char ltyp[4], expfact[4]; + + vdmprintf("E1%s%s\x1e",vdmnum(lintype,ltyp),vdmnum(1,expfact)); + +}; + +static inline void +vdmsetlinestyle(int lintype, int pattern,int unionstyle) +{ + char patt[4],ltip[4], + rot[4], /* rotation */ + espejo[4], /* espejo */ + in[4]; /* Inverted */ + + vdmprintf("}G%s%s%s%s%s\x1e",vdmnum(lintype,ltip),\ + vdmnum(pattern,patt),vdmnum(0,rot), + vdmnum(0,espejo),vdmnum(0,in)); + vdmprintf("}F%s",vdmnum(unionstyle,rot)); +}; + +static inline void +vdmlinewidth(int width) +{ + char wh[4]; + + vdmprintf("F1%s\x1e",vdmnum(width,wh)); +}; + +static inline void +vdmrectangle(int origx, int origy,int dstx, int dsty) +{ + char xcoord[4],ycoord[4],sdstx[4],sdsty[4]; + + vdmprintf("}:%s%s%s%s\x1e\n",vdmnum(origx,xcoord),vdmnum(dstx,sdstx),\ + vdmnum(origy,ycoord),vdmnum(dsty,sdsty)); +}; /* polyline */ + +static inline void +vdmpolyline(int numpoints, int *points) +{ + int i,*p = points; + char xcoord[4],ycoord[4]; + + if (numpoints < 2) return; + vdmprintf("1%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); + p += 2; + for (i = 1; i < numpoints ; i++) { + vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); + p += 2; + }; /* for */ + vdmprintf("\x1e\n"); +}; /* polyline */ + +static inline void +vdmpolygon(int numpoints, int *points) +{ + int i,*p = points; + char xcoord[4],ycoord[4]; + + if (numpoints < 2) return; + vdmprintf("2%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); + p += 2; + for (i = 1; i < numpoints ; i++) { + vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); + p += 2; + }; /* for */ + vdmprintf("\x1e\n"); + +}; /* vdmpolygon */ + + +/************************************************************************ + * Highter level auxiliary functions * + ************************************************************************/ +static inline int +vdminited() +{ + return (vdmoutput != NULL); +}; /* vdminited */ + + +static inline void +vdmline(int startx, int starty, int sizex, int sizey) +{ + int points[4]; + + points[0] = startx; + points[1] = starty; + points[2] = sizex; + points[3] = sizey; + + vdmpolyline(2,points); + +}; + +/*#define THRESHOLD .05 */ /* inch */ +#define THRESHOLD 1 /* points (1/300 inch) */ +static inline void +splinerel(double px,double py,int flush) +{ + static int lx = 0 ,ly = 0; + static float pend = 0.0; + static int dx = 0,dy = 0, despx = 0, despy = 0, sigpend = 0; + int dxnew ,dynew, sg; + char xcoord[4],ycoord[4]; + float npend ; + + if (flush == -1) {lx = (int)px; ly = (int)py; return;}; + + if (flush == 0) { + dxnew = (int)px -lx; + dynew = (int)py -ly; + if ((dxnew == 0) && (dynew == 0)) return; + sg = (dxnew < 0)? -1 : 0; +/* fprintf(stderr,"s (%d,%d) (%d,%d)\n",dxnew,dynew,despx,despy);*/ + if (dynew == 0) { + despx = dxnew; + if ((sg == sigpend) && (dy == 0)){ + return; + }; + dy = 0; + } + else { + dy = 1; + npend = (1.0*dxnew)/dynew; + if (( npend == pend) && (sigpend == sg)) + { despy = dynew; despx = dxnew; return; } + else + { sigpend = sg; + pend = npend; + }; /* else (( npend == pend) && ... */ + }; /* else (if (dynew == 0)) */ + }; /* if (!flush ) */ + + /* if we've changed direction we must draw the line */ +/* fprintf(stderr," (%d) %.2f,%.2f\n",flush,(float)px,(float)py);*/ + if ((despx != 0) || (despy != 0)) vdmprintf("%s%s",vdmnum(despx,xcoord),\ + vdmnum(despy,ycoord)); + /*if ((despx != 0) || (despy != 0)) fprintf(stderr,"2 + *%d,%d\n",despx,despy);*/ + if (flush) { + dx = dxnew = dy = despx = despy = 0; + return; + }; /* if (flush) */ + dxnew -= despx; + dynew -= despy; + if ((dxnew != 0) || (dynew != 0)) vdmprintf("%s%s",vdmnum(dxnew,xcoord),\ + vdmnum(dynew,ycoord)); + +/* if ((dxnew != 0) || (dynew != 0)) fprintf(stderr,"3 + * %d,%d\n",dxnew,dynew);*/ + lx = (int)px; ly = (int)py; + dx = dxnew = dy = despx = despy = 0; + +}; /* splinerel */ + +/********************************************************************** + * The following code to draw splines is adapted from the transfig package + */ +static void +quadratic_spline(double a1,double b1, double a2, double b2, \ + double a3, double b3, double a4, double b4) +{ + double x1, y1, x4, y4; + double xmid, ymid; + + x1 = a1; y1 = b1; + x4 = a4; y4 = b4; + xmid = (a2 + a3)/2.0; + ymid = (b2 + b3)/2.0; + if ((fabs(x1 - xmid) < THRESHOLD) && (fabs(y1 - ymid) < THRESHOLD)) { + splinerel(xmid,ymid,0); +/* fprintf(tfp, "PA%.4f,%.4f;\n", xmid, ymid);*/ + } + else { + quadratic_spline(x1, y1, ((x1+a2)/2.0), ((y1+b2)/2.0), + ((3.0*a2+a3)/4.0), ((3.0*b2+b3)/4.0), xmid, ymid); + } + + if ((fabs(xmid - x4) < THRESHOLD) && (fabs(ymid - y4) < THRESHOLD)) { + splinerel(x4,y4,0); +/* fprintf(tfp, "PA%.4f,%.4f;\n", x4, y4);*/ + } + else { + quadratic_spline(xmid, ymid, ((a2+3.0*a3)/4.0), ((b2+3.0*b3)/4.0), + ((a3+x4)/2.0), ((b3+y4)/2.0), x4, y4); + }; +}; /* quadratic_spline */ + +#define XCOORD(i) numbers[(2*i)] +#define YCOORD(i) numbers[(2*i)+1] +static void +vdmspline(int numpoints, int ox,int oy, int *numbers) +{ + double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4; + double x1, y1, x2, y2; + char xcoord[4],ycoord[4]; + int i; + + /*p = s->points; + x1 = p->x/ppi;*/ + x1 = ox; + y1 = oy; +/* p = p->next; + x2 = p->x/ppi; + y2 = p->y/ppi;*/ + x2 = ox + XCOORD(0); + y2 = oy + YCOORD(0); + cx1 = (x1 + x2)/2.0; + cy1 = (y1 + y2)/2.0; + cx2 = (x1 + 3.0*x2)/4.0; + cy2 = (y1 + 3.0*y2)/4.0; + +/* fprintf(stderr,"Spline %d (%d,%d)\n",numpoints,(int)x1,(int)y1);*/ + vdmprintf("1%s%s",vdmnum((int)x1,xcoord),vdmnum((int)y1,ycoord)); + splinerel(x1,y1,-1); + splinerel(cx1,cy1,0); +/* fprintf(tfp, "PA%.4f,%.4f;PD%.4f,%.4f;\n", + x1, y1, cx1, cy1);*/ + + /*for (p = p->next; p != NULL; p = p->next) {*/ + for (i = 1; i < (numpoints); i++) { + x1 = x2; + y1 = y2; +/* x2 = p->x/ppi; + y2 = p->y/ppi;*/ + x2 = x1 + XCOORD(i); + y2 = y1 + YCOORD(i); + cx3 = (3.0*x1 + x2)/4.0; + cy3 = (3.0*y1 + y2)/4.0; + cx4 = (x1 + x2)/2.0; + cy4 = (y1 + y2)/2.0; + /* fprintf(stderr,"Point (%d,%d) - (%d,%d)\n",(int)x1,(int)(y1),(int)x2,(int)y2);*/ + quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4); + cx1 = cx4; + cy1 = cy4; + cx2 = (x1 + 3.0*x2)/4.0; + cy2 = (y1 + 3.0*y2)/4.0; + } + x1 = x2; + y1 = y2; +/* p = s->points->next; + x2 = p->x/ppi; + y2 = p->y/ppi;*/ + x2 = ox + XCOORD(0); + y2 = oy + YCOORD(0); + cx3 = (3.0*x1 + x2)/4.0; + cy3 = (3.0*y1 + y2)/4.0; + cx4 = (x1 + x2)/2.0; + cy4 = (y1 + y2)/2.0; + splinerel(x1,y1,0); + splinerel(x1,y1,1); + /*vdmprintf("%s%s",vdmnum((int)(x1-lx),xcoord),\ + vdmnum((int)(y1-ly),ycoord));*/ + vdmprintf("\x1e\n"); +/* fprintf(tfp, "PA%.4f,%.4f;PU;\n", x1, y1);*/ + + +}; /* vdmspline */ + + +#endif -- 2.11.4.GIT