/*
-----------------------------------------------------------------------------
Original:
txt2pdf; Copyright 1998
P. G. Womack, Diss, Norfolk, UK.
"BugBear"
Do what you like, but don't claim you wrote it.
-----------------------------------------------------------------------------
*
* Copyright (c) 2006 John S. Urban, USA. (urbanjost @ comcast. net)
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* JOHN S. URBAN ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. JOHN S. URBAN DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* John S. Urban requests users of this software to return to
*
* urbanjost @ comcast. net
*
* any improvements or extensions that they make and grant John S. Urban and the
* previous authors (see above ) the rights to redistribute these changes.
*
-----------------------------------------------------------------------------
Modified:
asa2pdf; John S. Urban, Apr 30, 2006
Needed to emulate an old ASA 60 line by 132 column lineprinter quicky with
output as a PDF file. Thanks, P.G.W.!
o Added bar shading.
o placed Adobe-recommended "binary" flag at top of PDF file.
o changed sizes to simulate a 60 line by 132 column lineprinter.
o changed so obeys ASA carriage control (' 01+' in column 1).
o user-settable gray scale value via environmental variable IMPACT_GRAY
-----------------------------------------------------------------------------
Next time in:
o user-specified lines and columns and page orientation (T 0.4)
o expand tabs (can use expand(1)) (T 0.1)
o command line options instead of environmental variables? (T 0.2)
o optional lines instead of shade; dash lines; shade spacing (T 0.5)
o 1/2 line feeds? (T 0.2)
o bold Courier font on overprint? (T 0.3)
o underline? font color? shade color? font size? (? 3.0)
But, if someone wants to get that fancy they can use
fpr(1)/asa(1)/nasa(1) to handle the ASA carriage control, and
something like a2ps(1)/enscript(1) and ps2pdf(1) if they have them
or build them for their system. (? 0.0 -- 10.0)
-----------------------------------------------------------------------------
Tested with xpdf, gv/ghostview, and acroread (PC version) PDF interpreters.
-----------------------------------------------------------------------------
*/
#include
#include
#include
float page_depth;
float page_width; /* Default is 72 points per inch */
float margin;
float lead_size;
float font_size;
int object_id = 1;
int page_tree_id;
float gray_scale;
typedef struct _PageList {
struct _PageList *next;
int page_id;
} PageList;
int num_pages = 0;
PageList *pages = NULL;
PageList **insert_page = &pages;
void store_page(int id){
PageList *n = (PageList *)malloc(sizeof(*n));
if(n == NULL)
{
fprintf(stderr,
"Unable to allocate array for page %d.", num_pages + 1);
exit(1);
}
n->next = NULL;
n->page_id = id;
*insert_page = n;
insert_page = &n->next;
num_pages++;
}
int num_xrefs = 0;
long *xrefs = NULL;
void start_object(int id){
if(id >= num_xrefs) {
long *new_xrefs;
int delta, new_num_xrefs;
delta = num_xrefs / 5;
if(delta < 1000) {
delta += 1000;
}
new_num_xrefs = num_xrefs + delta;
new_xrefs = (long *)malloc(new_num_xrefs * sizeof(*new_xrefs));
if(new_xrefs == NULL) {
fprintf(stderr, "Unable to allocate array for object %d.", id);
exit(1);
}
memcpy(new_xrefs, xrefs, num_xrefs * sizeof(*xrefs));
free(xrefs);
xrefs = new_xrefs;
num_xrefs = new_num_xrefs;
}
xrefs[id] = ftell(stdout);
printf("%d 0 obj\n", id);
}
int stream_id, stream_len_id;
long stream_start;
float ypos;
void print_bars(){
float x1;
float y1;
float height;
float width;
int ii;
fprintf(stdout,"%f g\n",gray_scale); /* gray-scale value */
/*
* If you want to add color,
* R G B rg where R G B are red, green, blue components
* in range 0.0 to 1.0 sets fill color, "RG" sets line
* color instead of fill color.
*
* 0.60 0.82 0.60 rg
*
* */
fprintf(stdout,"%d i\n",1); /* */
x1=margin-0.1*font_size;
height=2.0*lead_size;
y1 = page_depth - margin - height- 0.22*font_size;
width=page_width-margin-margin;
for ( ii=0; ii < 15; ii++ ){
fprintf(stdout,"%f %f %f %f re f\n",x1,y1,width,height);
/*
* x1 y1 m x2 y2 l S
* xxx w # line width
fprintf(stdout,"0.6 0.8 0.6 RG\n %f %f m %f %f l S\n",x1,y1,x1+width,y1);
*/
y1=y1-2.0*height;
}
fprintf(stdout,"%d G\n",0); /* */
fprintf(stdout,"%d g\n",0); /* gray-scale value */
}
void print_back(){
char *buffer;
char c;
int i;
buffer=getenv("IMPACT_TOP");
if(buffer != NULL ){
fprintf(stdout,"1.0 0.0 0.0 rg\n"); /* gray-scale value */
fprintf(stdout,"BT /F2 20.0 Tf 30 582 Td");
i=0;
putchar('(');
while((c = *buffer++) != '\0') {
switch(c) {
case '(':
case ')':
case '\\':
putchar('\\');
}
putchar(c);
}
fprintf(stdout,") Tj ET\n");
fprintf(stdout,"0.0 0.0 0.0 rg\n"); /* gray-scale value */
}
}
void start_page() {
stream_id = object_id++;
stream_len_id = object_id++;
start_object(stream_id);
printf("<< /Length %d 0 R >>\n", stream_len_id);
printf("stream\n");
stream_start = ftell(stdout);
print_bars();
print_back();
printf("BT\n/F0 %g Tf\n", font_size);
ypos = page_depth - margin;
printf("%g %g Td\n", margin, ypos);
printf("%g TL\n", lead_size);
}
void end_page(){
long stream_len;
int page_id = object_id++;
store_page(page_id);
printf("ET\n");
stream_len = ftell(stdout) - stream_start;
printf("endstream\nendobj\n");
start_object(stream_len_id);
printf("%ld\nendobj\n", stream_len);
start_object(page_id);
printf("<>\nendobj\n", page_tree_id, stream_id);
}
void do_text() {
char buffer[8192];
char ASA;
char c;
char *s;
int black;
int add;
start_page();
while(gets(buffer) != NULL) {
black=0;
add=0;
if(ypos < margin && strlen(buffer) != 0 && buffer[0] != '+' ) {
end_page();
start_page();
}
if(strlen(buffer) == 0){ /* blank line */
printf("T*\n");
}else{
ASA=buffer[0];
switch(ASA) {
case '1': /* start a new page before processing data on line */
if (ypos < page_depth - margin ){
end_page();
start_page();
}
break;
case '0': /* put out a blank line before processing data on line */
printf("T*\n");
ypos -= lead_size;
break;
case '-': /* put out two blank lines before processing data on line */
printf("T*\n");
ypos -= lead_size;
ypos -= lead_size;
break;
case '+': /* print at same y-position as previous line */
printf("0 %f Td\n",lead_size);
if (ypos < page_depth - margin ){ /* if not at top of page */
ypos += lead_size;
}
break;
case 'R': /* RED print at same y-position as previous line */
fprintf(stdout,"1.0 0.0 0.0 rg\n"); /* red text */
black=1;
printf("0 %f Td\n",lead_size);
if (ypos < page_depth - margin ){ /* if not at top of page */
ypos += lead_size;
}
break;
case 'G': /* GREEN print at same y-position as previous line */
fprintf(stdout,"0.0 1.0 0.0 rg\n"); /* green text */
black=1;
printf("0 %f Td\n",lead_size);
if (ypos < page_depth - margin ){ /* if not at top of page */
ypos += lead_size;
}
break;
case 'B': /* BLUE print at same y-position as previous line */
fprintf(stdout,"0.0 0.0 1.0 rg\n"); /* blue text */
black=1;
printf("0 %f Td\n",lead_size);
if (ypos < page_depth - margin ){ /* if not at top of page */
ypos += lead_size;
}
break;
case '^': /* print at same y-position as previous line like + but add 127 to character */
printf("0 %f Td\n",lead_size);
if (ypos < page_depth - margin ){ /* if not at top of page */
ypos += lead_size;
}
add=127;
break;
case '>': /* Unknown */
break;
case '\f': /* ctrl-L is a common form-feed character on Unix, but NOT ASA */
end_page();
start_page();
break;
case 'r':
fprintf(stdout,"1.0 0.0 0.0 rg\n"); /* red text */
black=1;
break;
case 'g':
fprintf(stdout,"0.0 1.0 0.0 rg\n"); /* green text */
black=1;
break;
case 'b':
fprintf(stdout,"0.0 0.0 1.0 rg\n"); /* blue text */
black=1;
break;
case ' ':
break;
default:
fprintf(stderr,"unknown ASA carriage control character %c\n",buffer[0]);
break;
}
s = &buffer[1];
putchar('(');
while((c = *s++) != '\0') {
switch(c+add) {
case '(':
case ')':
case '\\':
putchar('\\');
}
putchar(c+add);
}
printf(")'\n");
}
ypos -= lead_size;
if(black != 0){
fprintf(stdout,"0.0 0.0 0.0 rg\n"); /* black text */
}
}
end_page();
}
int main(int argc, char **argv) {
int i, catalog_id, font_id;
long start_xref;
char *varname;
varname=getenv("IMPACT_GRAY");
if (varname == (char)NULL ){
gray_scale=0.800781; /* gray-scale value */
}else if (varname[0] == '\0'){
gray_scale=0.800781; /* gray-scale value */
}else{
sscanf(varname,"%f",&gray_scale);
if(gray_scale < 0 ){
gray_scale=0.800781; /* gray-scale value */
}
}
printf("%%PDF-1.0\n");
/*
Note: If a PDF file contains binary data, as most do , it is
recommended that the header line be immediately followed by a
comment line containing at least four binary characters--that is,
characters whose codes are 128 or greater. This will ensure proper behavior of file
transfer applications that inspect data near the beginning of a
file to determine whether to treat the file's contents as text or as binary.
*/
fprintf(stdout,"%%%c%c%c%c\n",128,129,130,131);
fprintf(stdout,"%% PDF: Adobe Portable Document Format\n");
page_depth = 612.0;
page_width = 792.0; /* Default is 72 points per inch */
margin = 30.0;
lead_size=(page_depth-margin-margin)/60.0;
font_size=lead_size;
object_id = 1;
page_tree_id = object_id++;
do_text();
font_id = object_id++;
start_object(font_id);
printf("<>\nendobj\n");
start_object(page_tree_id);
printf("<
{
PageList *ptr = pages;
printf("/Kids[\n");
while(ptr != NULL) {
printf("%d 0 R\n", ptr->page_id);
ptr = ptr->next;
}
printf("]\n");
}
printf("/Resources< printf(" /F2<> >>\n");
printf(">>/MediaBox [ 0 0 %g %g ]\n", page_width, page_depth);
printf(">>\nendobj\n");
catalog_id = object_id++;
start_object(catalog_id);
printf("<>\nendobj\n", page_tree_id);
start_xref = ftell(stdout);
printf("xref\n");
printf("0 %d\n", object_id);
printf("0000000000 65535 f \n");
for(i = 1; i < object_id; i++){
printf("%010ld 00000 n \n", xrefs[i]);
}
printf("trailer\n<<\n/Size %d\n/Root %d 0 R\n>>\n", object_id, catalog_id);
printf("startxref\n%ld\n%%%%EOF\n", start_xref);
exit(0);
return 0;
}