kolibrios/programs/media/unrtf/ps.c

611 lines
18 KiB
C
Raw Normal View History

/*=============================================================================
GNU UnRTF, a command-line program to convert RTF documents to other formats.
Copyright (C) 2000,2001 Zachary Thayer Smith
This program 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 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
The author is reachable by electronic mail at tuorfa@yahoo.com.
=============================================================================*/
/*----------------------------------------------------------------------
* Module name: ps
* Author name: Zach Smith
* Create date: 18 Sep 01
* Purpose: PostScript(TM)-specific output module
*----------------------------------------------------------------------
* Changes:
* 22 Sep 01, tuorfa@yahoo.com: added function-level comment blocks
* 23 Sep 01, tuorfa@yahoo.com: added shadow, outline, strikethru, underline
* 23 Sep 01, tuorfa@yahoo.com: revised PS program to use ISOLatin1Encoding
* 28 Sep 01, tuorfa@yahoo.com: added support for Helvetica,Courier,Symbol
*--------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "malloc.h"
#include "defs.h"
#include "error.h"
#include "main.h"
#include "output.h"
static char*
ascii [96] = {
/* 0x20 */ " ", "!", "\"", "#", "$", "\%", "&", "'",
/* 0x28 */ "\\(", "\\)", "*", "+", ",", "-", ".", "/",
/* 0x30 */ "0", "1", "2", "3", "4", "5", "6", "7",
/* 0x38 */ "8", "9", ":", ";", "<", "=", ">", "?",
/* 0x40 */ "@", "A", "B", "C", "D", "E", "F", "G",
/* 0x48 */ "H", "I", "J", "K", "L", "M", "N", "O",
/* 0x50 */ "P", "Q", "R", "S", "T", "U", "V", "W",
/* 0x58 */ "X", "Y", "Z", "\\[", "\\\\", "\\]", "^", "_",
/* 0x60 */ "`", "a", "b", "c", "d", "e", "f", "g",
/* 0x68 */ "h", "i", "j", "k", "l", "m", "n", "o",
/* 0x70 */ "p", "q", "r", "s", "t", "u", "v", "w",
/* 0x78 */ "x", "y", "z", "{", "|", "}", "~", "",
};
static char* ansi [] = {
/* 0x80 */ "\\200","\\201","\\202","\\203",
/* 0x84 */ "\\204","\\205","\\206","\\207",
/* 0x88 */ "\\210","\\211","\\212","\\213",
/* 0x8c */ "\\214","\\215","\\216","\\217",
/* 0x90 */ "\\220","\\221","\\222","\\223",
/* 0x94 */ "\\224","\\225","\\226","\\227",
/* 0x98 */ "\\230","\\231","\\232","\\233",
/* 0x9c */ "\\234","\\235","\\236","\\237",
/* 0xa0 */ "\\240","\\241","\\242","\\243",
/* 0xa4 */ "\\244","\\245","\\246","\\247",
/* 0xa8 */ "\\250","\\251","\\252","\\253",
/* 0xac */ "\\254","\\255","\\256","\\257",
/* 0xb0 */ "\\260","\\261","\\262","\\263",
/* 0xb4 */ "\\264","\\265","\\266","\\267",
/* 0xb8 */ "\\270","\\271","\\272","\\273",
/* 0xbc */ "\\274","\\275","\\276","\\277",
/* 0xc0 */ "\\300","\\301","\\302","\\303",
/* 0xc4 */ "\\304","\\305","\\306","\\307",
/* 0xc8 */ "\\310","\\311","\\312","\\313",
/* 0xcc */ "\\314","\\315","\\316","\\317",
/* 0xd0 */ "\\320","\\321","\\322","\\323",
/* 0xd4 */ "\\324","\\325","\\326","\\327",
/* 0xd8 */ "\\330","\\331","\\332","\\333",
/* 0xdc */ "\\334","\\335","\\336","\\337",
/* 0xe0 */ "\\340","\\341","\\342","\\343",
/* 0xe4 */ "\\344","\\345","\\346","\\347",
/* 0xe8 */ "\\350","\\351","\\352","\\353",
/* 0xec */ "\\354","\\355","\\356","\\357",
/* 0xf0 */ "\\360","\\361","\\362","\\363",
/* 0xf4 */ "\\364","\\365","\\366","\\367",
/* 0xf8 */ "\\370","\\371","\\372","\\373",
/* 0xfc */ "\\374","\\375","\\376","\\377",
};
static char* mac [] = {
"?",
};
static char* cp437 [] = {
"?",
};
static char* cp850 [] = {
"?",
};
#define PS_END "\
%% --------- \n\n\
didShowPage not { \n\
showpage \n\
} if\n\n\
%%%%EOF\n"
#define PS_START "\
%%%%!PS\n\
%%--------------------------------------------------------------------------\n\
%% GNU UnRTF, a command-line program to convert RTF documents to other formats.\n\
%% Copyright (C) 2000,2001 Zachary Thayer Smith\n\
%%\n\
%% This program is free software; you can redistribute it and/or modify\n\
%% it under the terms of the GNU General Public License as published by\n\
%% the Free Software Foundation; either version 2 of the License, or\n\
%% (at your option) any later version.\n\
%%\n\
%% This program is distributed in the hope that it will be useful,\n\
%% but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
%% GNU General Public License for more details.\n\
%%\n\
%% You should have received a copy of the GNU General Public License\n\
%% along with this program; if not, write to the Free Software\n\
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\
%%\n\
%% The author is reachable by electronic mail at tuorfa@yahoo.com.\n\
%%--------------------------------------------------------------------------\n\
%%%%EndComments \n\
%%\n\
%% --------- Note, this PS code is unfinished -------- \n\
%% --------- Note, this PS code is unfinished -------- \n\
%% --------- Note, this PS code is unfinished -------- \n\
%% --------- Note, this PS code is unfinished -------- \n\
%% --------- Note, this PS code is unfinished -------- \n\
%%\n\
%% ----------- Variables ------------\n\
/fontFamily /Times def\n\
/fontAscent 0 def %% ascent for current font\n\
/fontDescent 0 def %% descent for current font\n\
/lineAscent 0 def \n\
/lineDescent 0 def \n\
/pageWidthInches 8.5 def \n\
/pageHeightInches 11 def \n\
/leftMargin 20 def \n\
/rightMargin 20 def \n\
/topMargin 20 def \n\
/bottomMargin 20 def \n\
/DPI 72 def \n\
/pageWidth pageWidthInches DPI mul def \n\
/rightLimit pageWidth rightMargin sub def \n\
/pageHeight pageHeightInches DPI mul def \n\
/x 0 def \n\
/y 0 def \n\
/bold false def \n\
/italic false def \n\
/underline false def \n\
/overline false def \n\
/intercharSpace 0 def \n\
/strike false def \n\
/outline false def \n\
/shadow false def \n\
/fontSize 12 def \n\
/didBR false def \n\
/didParSkip false def \n\
/didShowPage false def \n\
%%------------------------------------------------------\n\
%% Set up the ISO fonts \n\
%% Times \n\
%% ----- \n\
/Times-Roman findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/TRomanISO exch definefont pop \n\
/Times-Bold findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/TBoldISO exch definefont pop \n\
/Times-BoldItalic findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/TBoldItalicISO exch definefont pop \n\
/Times-Italic findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/TItalicISO exch definefont pop \n\
%% Courier \n\
%% ----- \n\
/Courier-Roman findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/CRomanISO exch definefont pop \n\
/Courier-Bold findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/CBoldISO exch definefont pop \n\
/Courier-BoldItalic findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/CBoldItalicISO exch definefont pop \n\
/Courier-Italic findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/CItalicISO exch definefont pop \n\
%% Symbol \n\
%% ----- \n\
/Symbol-Roman findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/SRomanISO exch definefont pop \n\
/Symbol-Bold findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/SBoldISO exch definefont pop \n\
/Symbol-BoldItalic findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/SBoldItalicISO exch definefont pop \n\
/Symbol-Italic findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/SItalicISO exch definefont pop \n\
%% Helvetica \n\
%% --------- \n\
/Helvetica-Roman findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/HRomanISO exch definefont pop \n\
/Helvetica-Bold findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/HBoldISO exch definefont pop \n\
/Helvetica-BoldOblique findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/HBoldItalicISO exch definefont pop \n\
/Helvetica-Oblique findfont dup length dict begin { \n\
1 index /FID ne { def } { pop pop } ifelse \n\
} forall \n\
/Encoding ISOLatin1Encoding def \n\
currentdict end \n\
/HItalicISO exch definefont pop \n\
%% \n\
%% Ideally, before we can draw a line of text, we need to collect all the\n\
%% words that will be on it, just as I do in my Beest HTML viewer, as well\n\
%% as character attributes for each word. But for now, this implementation \n\
%% does not bother. It determines the maximize ascent and descent after\n\
%% drawing the text, not before. XX\n\
%% \n\
%% ----------- Functions ------------\n\
/updateFont { \n\
/f0 null def \n\
(Times) fontFamily eq (Times New Roman) fontFamily eq or { bold { \n\
italic { /TBoldItalicISO } { /TBoldISO } ifelse \n\
} { \n\
italic { /TItalicISO } { /TRomanISO } ifelse \n\
} \n\
ifelse \n\
} if (Helvetica) fontFamily eq (Arial) fontFamily eq or { bold { \n\
italic { /HBoldItalicISO } { /HBoldISO } ifelse \n\
} { \n\
italic { /HItalicISO } { /HRomanISO } ifelse \n\
} \n\
ifelse \n\
} if (Courier) fontFamily eq (Courier New) fontFamily eq or { bold { \n\
italic { /CBoldItalicISO } { /CBoldISO } ifelse \n\
} { \n\
italic { /CItalicISO } { /CRomanISO } ifelse \n\
} \n\
ifelse \n\
} if (Symbol) fontFamily eq { bold { \n\
italic { /SBoldItalicISO } { /SBoldISO } ifelse \n\
} { \n\
italic { /SItalicISO } { /SRomanISO } ifelse \n\
} \n\
ifelse \n\
} if findfont /f0 exch def \n\
/bboxBottom f0 /FontBBox get 1 get 1000 div fontSize mul -1 mul def \n\
/bboxTop f0 /FontBBox get 3 get 1000 div fontSize mul def \n\
f0 fontSize scalefont setfont \n\
lineAscent bboxTop lt { /lineAscent bboxTop def } if \n\
lineDescent bboxBottom lt { /lineDescent bboxBottom def } if \n\
/fontAscent bboxTop def \n\
/fontDescent bboxBottom def \n\
} def\n\
/FS { \n\
/fontSize exch def updateFont \n\
} def \n\
/F { \n\
/fontFamily exch def updateFont \n\
} def \n\
/resetX { \n\
/x leftMargin def\n\
} def \n\
/resetY { \n\
/y pageHeight topMargin sub def \n\
} def \n\
/BR { \n\
/oldx x def \n\
/y y lineAscent lineDescent add sub def \n\
resetX \n\
y bottomMargin lt { \n\
showpage \n\
/didShowPage true \n\
resetY \n\
} if \n\
oldx 0 eq didBR and { /didParSkip true def } if \n\
/didBR true def \n\
% /lineAscent 0 def \n\
% /lineDescent 0 def \n\
} def \n\
/P { \n\
didParSkip not { BR } if \n\
didParSkip not { BR } if \n\
} \n\
def \n\
/acharpath { \n\
/acstr exch def pop /acsp exch def newpath str { /ch exch def 1 string 0 ch put false charpath acsp 0 rmoveto } forall} def \n\
/A { \n\
/str exch def \n\
/w str stringwidth pop \n\
str length intercharSpace mul add \n\
def \n\
x w add rightLimit ge { BR } if \n\
x y moveto \n\
outline { \n\
shadow { \n\
1 -0.1 0 { \n\
/offset exch def \n\
offset setgray \n\
x offset 3 mul add y offset 3 mul sub moveto intercharSpace 0 str acharpath \n\
%% str false charpath \n\
fontSize 30 div setlinewidth stroke \n\
} for \n\
0 setgray \n\
} { \n\
intercharSpace 0 str acharpath \n\
%% str false charpath \n\
fontSize 30 div setlinewidth stroke \n\
} ifelse \n\
} { \n\
shadow { \n\
1 -0.1 0 { \n\
/offset exch def \n\
offset setgray \n\
x offset 3 mul add y offset 3 mul sub moveto intercharSpace 0 str ashow \n\
%% str show \n\
} for \n\
0 setgray } { \n\
intercharSpace 0 str ashow \n\
%% str show \n\
} ifelse \n\
} ifelse \n\
strike { \n\
newpath fontSize 20 div setlinewidth \n\
x y fontAscent 0.32 mul add dup /y2 exch def moveto \n\
x w add y2 lineto stroke \n\
} if \n\
underline { \n\
newpath fontSize 20 div setlinewidth \n\
x y fontAscent 0.2 mul sub dup /y2 exch def moveto \n\
x w add y2 lineto stroke \n\
} if \n\
overline { \n\
%% I don't think RTF supports this, but it can be used later. \n\
newpath fontSize 20 div setlinewidth \n\
x y fontAscent 1.2 mul add dup /y2 exch def moveto \n\
x w add y2 lineto stroke \n\
} if \n\
/x x w add def \n\
/didBR false def \n\
/didShowPage false def \n\
} def \n\
\n\
%% These are only binary for now \n\
/X1 { /intercharSpace exch def } def\n\
/X0 { /intercharSpace 0 def } def\n\
/O1 { /outline false def } def\n\
/O0 { /outline false def } def\n\
/H1 { /shadow true def } def\n\
/H0 { /shadow false def } def\n\
/S1 { /strike true def } def\n\
/S0 { /strike false def } def\n\
/B1 { /bold true def updateFont } def\n\
/B0 { /bold false def updateFont } def\n\
/I1 { /italic true def updateFont } def\n\
/I0 { /italic false def updateFont } def\n\
/U1 { /underline true def } def\n\
/U0 { /underline false def } def\n\
updateFont \n\
resetX resetY \n\
\n\
"
/*========================================================================
* Name: ps_init
* Purpose: Generates an OutputPersonality object for the PostScript(TM)
* format.
* Args: None.
* Returns: OutputPersonality.
*=======================================================================*/
OutputPersonality *
ps_init (void)
{
OutputPersonality* op;
op = op_create();
op->comment_begin = "%% ";
op->comment_end = "\n";
op->word_begin = "(";
op->word_end = ")A ";
op->document_begin = PS_START;
op->document_end = PS_END;
op->header_begin = "%% header begin\n";
op->header_end = "%% header end\n";
op->document_title_begin = "%%%%Title: ";
op->document_title_end = "\n";
op->document_author_begin = "%%%%Creator: ";
op->document_author_end = "\n";
op->document_changedate_begin = "%% CHANGED: ";
op->document_changedate_end = "\n";
op->body_begin = "\n\n%% ---------- Document Body ------------\n";
op->body_end = "\n";
op->paragraph_begin = "P ";
op->paragraph_end = "\n";
op->center_begin = "";
op->center_end = "";
op->justify_begin = "";
op->justify_end = "";
op->align_left_begin = "";
op->align_left_end = "";
op->align_right_begin = "";
op->align_right_end = "";
op->forced_space = " ";
op->line_break = "BR\n";
op->page_break = "\n";
op->hyperlink_begin = "U1(";
op->hyperlink_end = ")A U0 ";
op->imagelink_begin = "";
op->imagelink_end = "";
op->table_begin = "\n% TABLE BEGINS (not implemented)\nP\n(TABLE)A BR\n";
op->table_end = "\n% TABLE ENDS (not implemented)\nP\n";
op->table_row_begin = "( )A ";
op->table_row_end = "( |)A BR\n";
op->table_cell_begin = "( | )A ";
op->table_cell_end = "";
/* Character attributes */
op->font_begin = "(%s) F ";
op->font_end = "";
op->fontsize_begin = "%s FS ";
op->fontsize_end = "";
op->smaller_begin = "";
op->smaller_end = "";
op->bigger_begin = "";
op->bigger_end = "";
op->foreground_begin = "";
op->foreground_end = "";
op->background_begin = "";
op->background_end = "";
op->bold_begin = "B1 ";
op->bold_end = "B0 ";
op->italic_begin = "I1 ";
op->italic_end = "I0 ";
op->underline_begin = "U1 ";
op->underline_end = "U0 ";
op->dbl_underline_begin = "U1 ";
op->dbl_underline_end = "U0 ";
op->superscript_begin = "";
op->superscript_end = "";
op->subscript_begin = "";
op->subscript_end = "";
op->strikethru_begin = "S1 ";
op->strikethru_end = "S0 ";
op->dbl_strikethru_begin = "S1 ";
op->dbl_strikethru_end = "S0 ";
op->emboss_begin="";
op->emboss_end = "";
op->engrave_begin = "";
op->engrave_end = "";
op->shadow_begin= "H1 ";
op->shadow_end= "H0 ";
op->outline_begin= "O1 ";
op->outline_end= "O0 ";
op->expand_begin = "%s X1 ";
op->expand_end = "X0 ";
op->simulate_small_caps = TRUE;
op->simulate_all_caps = TRUE;
op->simulate_word_underline = TRUE;
op->ascii_translation_table = ascii;
op->ansi_translation_table = ansi;
op->ansi_first_char = 0x80;
op->ansi_last_char = 0xff;
op->cp437_translation_table = cp437;
op->cp437_first_char = 0x80;
op->cp437_last_char = 0x80;
op->cp850_translation_table = cp850;
op->cp850_first_char = 0x80;
op->cp850_last_char = 0x80;
op->mac_translation_table = mac;
op->mac_first_char = 0x80;
op->mac_last_char = 0x80;
op->chars.right_quote = "'";
op->chars.left_quote = "`";
op->chars.right_dbl_quote = "''";
op->chars.left_dbl_quote = "``";
return op;
}