2016-02-08 05:01:25 +00:00
/*
2018-08-13 17:22:40 +00:00
GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT . txt for Copyright information
See LICENSE . txt for license ( GPL v2 )
*/
2016-02-08 05:01:25 +00:00
/*
* Copyright ( C ) 2002 - 2004 The DOSBox Team
*
* 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 Library 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 .
*/
/*
Modified for the GSport emulator by Christopher G . Mason 03 / 2014
Extensively rewritten to provide full emulation of the Apple ImageWriter II
and LQ printers .
2016-10-24 02:17:22 +00:00
Information used to write this emulator was provided by
2016-02-08 05:01:25 +00:00
Apple ' s " ImageWriter II Technical Reference Manual "
ISBN # 0 - 201 - 17766 - 8
and
Apple ' s " ImageWriter LQ Reference Manual "
ISBN # 0 - 201 - 17751 - X
*/
# include "imagewriter.h"
# include <math.h>
# include "support.h"
//#include "png.h"
//#pragma comment( lib, "libpng.lib" )
2016-10-24 02:17:22 +00:00
//#pragma comment (lib, "zdll.lib" )
2016-02-08 05:01:25 +00:00
static Imagewriter * defaultImagewriter = NULL ;
2016-10-24 02:17:22 +00:00
static FILE * textPrinterFile = NULL ;
2016-02-08 05:01:25 +00:00
# ifdef WIN32
const char * const textPrinterFileName = " . \\ printer.txt " ;
2016-10-24 02:17:22 +00:00
# else
2016-02-08 05:01:25 +00:00
const char * const textPrinterFileName = " ./printer.txt " ;
# endif
# define PARAM16(I) (params[I+1]*256+params[I])
# define PIXX ((Bitu)floor(curX*dpi+0.5))
# define PIXY ((Bitu)floor(curY*dpi+0.5))
//These ugly defines are so we can convert multibyte parameters from strings into some nice ints.
# define paramc(I) (params[I]-'0')
# define PARAM2(I) (paramc(I)*10+paramc(I+1))
# define PARAM3(I) (paramc(I)*100+paramc(I+1)*10+paramc(I+2))
# define PARAM4(I) (paramc(I)*1000+paramc(I+1)*100+paramc(I+2)*10+paramc(I+3))
static Bitu printer_timout ;
static bool timeout_dirty ;
static const char * document_path ;
extern " C " char * g_imagewriter_fixed_font ;
extern " C " char * g_imagewriter_prop_font ;
extern " C " int iw_scc_write ;
# include "iw_charmaps.h"
# ifdef HAVE_SDL
void Imagewriter : : FillPalette ( Bit8u redmax , Bit8u greenmax , Bit8u bluemax , Bit8u colorID , SDL_Palette * pal )
{
float red = redmax / 30.9 ;
float green = greenmax / 30.9 ;
float blue = bluemax / 30.9 ;
Bit8u colormask = colorID < < = 5 ;
for ( int i = 0 ; i < 32 ; i + + ) {
pal - > colors [ i + colormask ] . r = 255 - ( red * ( float ) i ) ;
pal - > colors [ i + colormask ] . g = 255 - ( green * ( float ) i ) ;
pal - > colors [ i + colormask ] . b = 255 - ( blue * ( float ) i ) ;
}
}
# endif // HAVE_SDL
Imagewriter : : Imagewriter ( Bit16u dpi , Bit16u paperSize , Bit16u bannerSize , char * output , bool multipageOutput )
{
# ifdef HAVE_SDL
if ( FT_Init_FreeType ( & FTlib ) )
{
page = NULL ;
}
else
{
SDL_Init ( SDL_INIT_EVERYTHING ) ;
this - > output = output ;
this - > multipageOutput = multipageOutput ;
this - > port = port ;
if ( bannerSize )
{
defaultPageWidth = ( ( Real64 ) paperSizes [ 0 ] [ 0 ] / ( Real64 ) 72 ) ;
defaultPageHeight = ( ( ( Real64 ) paperSizes [ 0 ] [ 1 ] * bannerSize ) / ( Real64 ) 72 ) ;
dpi = 144 ;
}
else
{
defaultPageWidth = ( ( Real64 ) paperSizes [ paperSize ] [ 0 ] / ( Real64 ) 72 ) ;
defaultPageHeight = ( ( Real64 ) paperSizes [ paperSize ] [ 1 ] / ( Real64 ) 72 ) ;
}
this - > dpi = dpi ;
// Create page
page = SDL_CreateRGBSurface (
2016-10-24 02:17:22 +00:00
SDL_SWSURFACE ,
( Bitu ) ( defaultPageWidth * dpi ) ,
( Bitu ) ( defaultPageHeight * dpi ) ,
8 ,
0 ,
0 ,
0 ,
2016-02-08 05:01:25 +00:00
0 ) ;
// Set a grey palette
SDL_Palette * palette = page - > format - > palette ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
for ( Bitu i = 0 ; i < 32 ; i + + )
{
palette - > colors [ i ] . r = 255 ;
palette - > colors [ i ] . g = 255 ;
palette - > colors [ i ] . b = 255 ;
}
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
// 0 = all white needed for logic 000
FillPalette ( 0 , 0 , 0 , 1 , palette ) ;
// 1 = magenta* 001
FillPalette ( 0 , 255 , 0 , 1 , palette ) ;
// 2 = cyan* 010
FillPalette ( 255 , 0 , 0 , 2 , palette ) ;
// 3 = "violet" 011
FillPalette ( 255 , 255 , 0 , 3 , palette ) ;
// 4 = yellow* 100
FillPalette ( 0 , 0 , 255 , 4 , palette ) ;
// 5 = red 101
FillPalette ( 0 , 255 , 255 , 5 , palette ) ;
// 6 = green 110
FillPalette ( 255 , 0 , 255 , 6 , palette ) ;
// 7 = black 111
FillPalette ( 255 , 255 , 255 , 7 , palette ) ;
// 0 = all white needed for logic 000
/*FillPalette( 0, 0, 0, 1, palette);
// 1 = yellow* 100 IW
FillPalette ( 0 , 0 , 255 , 1 , palette ) ;
// 2 = magenta* 001 IW
FillPalette ( 0 , 255 , 0 , 2 , palette ) ;
// 3 = cyan* 010 IW
FillPalette ( 255 , 0 , 0 , 3 , palette ) ;
// 4 = red 101 IW
FillPalette ( 0 , 255 , 255 , 4 , palette ) ;
// 5 = green 110 IW
FillPalette ( 255 , 0 , 255 , 5 , palette ) ;
// 6 = "violet" 011 IW
FillPalette ( 255 , 255 , 0 , 6 , palette ) ;
// 7 = black 111
FillPalette ( 255 , 255 , 255 , 7 , palette ) ; */
// yyyxxxxx bit pattern: yyy=color xxxxx = intensity: 31=max
// Printing colors on top of each other ORs them and gets the
// correct resulting color.
// i.e. magenta on blank page yyy=001
// then yellow on magenta 001 | 100 = 101 = red
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
color = COLOR_BLACK ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
curFont = NULL ;
charRead = false ;
autoFeed = false ;
outputHandle = NULL ;
resetPrinter ( ) ;
//Only initialize native printer here if multipage output is off. That way the user doesn't get prompted every page.
if ( strcasecmp ( output , " printer " ) = = 0 & & ! multipageOutput )
{
# if defined (WIN32)
// Show Print dialog to obtain a printer device context
ShowCursor ( 1 ) ;
PRINTDLG pd ;
2016-10-24 02:17:22 +00:00
pd . lStructSize = sizeof ( PRINTDLG ) ;
pd . hDevMode = ( HANDLE ) NULL ;
pd . hDevNames = ( HANDLE ) NULL ;
pd . Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE ;
pd . hwndOwner = NULL ;
pd . hDC = ( HDC ) NULL ;
pd . nFromPage = 0xFFFF ;
2016-02-08 05:01:25 +00:00
pd . nToPage = 0xFFFF ;
2016-10-24 02:17:22 +00:00
pd . nMinPage = 1 ;
pd . nMaxPage = 0xFFFF ;
pd . nCopies = 1 ;
pd . hInstance = NULL ;
pd . lCustData = 0L ;
pd . lpfnPrintHook = ( LPPRINTHOOKPROC ) NULL ;
pd . lpfnSetupHook = ( LPSETUPHOOKPROC ) NULL ;
pd . lpPrintTemplateName = ( LPCSTR ) NULL ;
pd . lpSetupTemplateName = ( LPCSTR ) NULL ;
pd . hPrintTemplate = ( HANDLE ) NULL ;
2016-02-08 05:01:25 +00:00
pd . hSetupTemplate = ( HANDLE ) NULL ;
if ( ! PrintDlg ( & pd ) )
{
2016-10-24 02:17:22 +00:00
//If user presses cancel, warn them with a dialog and switch output to bitmap files
2016-02-08 05:01:25 +00:00
this - > output = " bmp " ;
MessageBox ( NULL , " You did not select a printer. \n All printer output will be saved as bitmap files. \n To select a printer, press F4 and select 'Reset Virtual ImageWriter' " , NULL , MB_ICONEXCLAMATION ) ;
}
printerDC = pd . hDC ;
ShowCursor ( 0 ) ;
# endif // WIN32
}
}
# endif // HAVE_SDL
# ifndef HAVE_SDL
this - > output = output ;
this - > multipageOutput = multipageOutput ;
# endif // !HAVE_SDL
} ;
void Imagewriter : : resetPrinterHard ( )
{
# ifdef HAVE_SDL
charRead = false ;
resetPrinter ( ) ;
# endif // HAVE_SDL
}
void Imagewriter : : resetPrinter ( )
{
# ifdef HAVE_SDL
2016-10-24 02:17:22 +00:00
printRes = 0 ;
2016-02-08 05:01:25 +00:00
color = COLOR_BLACK ;
curX = curY = 0.0 ;
ESCSeen = false ;
FSSeen = false ;
ESCCmd = 0 ;
numParam = neededParam = 0 ;
topMargin = 0.0 ;
leftMargin = 0.25 ; //Most all Apple II software including GS/OS assume a 1/4 inch margin on an Imagewriter
rightMargin = pageWidth = defaultPageWidth ;
bottomMargin = pageHeight = defaultPageHeight ;
lineSpacing = ( Real64 ) 1 / 6 ;
cpi = 12.0 ;
printRes = 2 ;
style & = ( 0xffff - STYLE_PROP ) ;
definedUnit = 96 ;
curCharTable = 1 ;
style = 0 ;
extraIntraSpace = 0.0 ;
printUpperContr = true ;
bitGraph . remBytes = 0 ;
densk = 0 ;
densl = 1 ;
densy = 2 ;
densz = 3 ;
charTables [ 0 ] = 0 ; // Italics
charTables [ 1 ] = charTables [ 2 ] = charTables [ 3 ] = 437 ;
multipoint = false ;
multiPointSize = 0.0 ;
multicpi = 0.0 ;
hmi = - 1.0 ;
switcha = 0 ;
switchb = ' ' ;
numPrintAsChar = 0 ;
LQtypeFace = fixed ;
verticalDot = 0 ;
selectCodepage ( charTables [ curCharTable ] ) ;
updateFont ( ) ;
updateSwitch ( ) ;
# endif // HAVE_SDL
newPage ( false , true ) ;
# ifdef HAVE_SDL
// Default tabs => Each eight characters
/*for (Bitu i=0;i<32;i++)
horiztabs [ i ] = i * 8 * ( 1 / ( Real64 ) cpi ) ; */
numHorizTabs = 0 ;
numVertTabs = 0 ;
# endif // HAVE_SDL
}
Imagewriter : : ~ Imagewriter ( void )
{
# ifdef HAVE_SDL
finishMultipage ( ) ;
if ( page ! = NULL )
{
SDL_FreeSurface ( page ) ;
page = NULL ;
FT_Done_FreeType ( FTlib ) ;
}
# if defined (WIN32)
DeleteDC ( printerDC ) ;
# endif
# endif // HAVE_SDL
} ;
# ifdef HAVE_SDL
void Imagewriter : : selectCodepage ( Bit16u cp )
{
Bit16u * mapToUse = NULL ;
switch ( cp )
{
case 0 : // Italics, use cp437
case 437 :
mapToUse = ( Bit16u * ) & cp437Map ;
break ;
default :
//LOG(LOG_MISC,LOG_WARN)("Unsupported codepage %i. Using CP437 instead.", cp);
mapToUse = ( Bit16u * ) & cp437Map ;
}
for ( int i = 0 ; i < 256 ; i + + )
curMap [ i ] = mapToUse [ i ] ;
}
# endif // HAVE_SDL
# ifdef HAVE_SDL
void Imagewriter : : updateFont ( )
{
// char buffer[1000];
if ( curFont ! = NULL )
FT_Done_Face ( curFont ) ;
char * fontName ;
switch ( LQtypeFace )
{
case fixed :
fontName = g_imagewriter_fixed_font ;
break ;
case prop :
fontName = g_imagewriter_prop_font ;
break ;
default :
fontName = g_imagewriter_fixed_font ;
}
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
if ( FT_New_Face ( FTlib , fontName , 0 , & curFont ) )
{
2016-10-24 02:17:22 +00:00
printf ( " Unable to load font %s \n " , fontName ) ;
2016-02-08 05:01:25 +00:00
//LOG_MSG("Unable to load font %s", fontName);
curFont = NULL ;
}
Real64 horizPoints = 10 ;
Real64 vertPoints = 10 ;
if ( ! multipoint )
{
actcpi = cpi ;
if ( ! ( style & STYLE_CONDENSED ) ) {
horizPoints * = 10.0 / cpi ;
//vertPoints *= 10.0/cpi;
}
if ( ! ( style & STYLE_PROP ) ) {
if ( ( cpi = = 10.0 ) & & ( style & STYLE_CONDENSED ) ) {
actcpi = 17.14 ;
horizPoints * = 10.0 / 17.14 ;
}
if ( ( cpi = = 12.0 ) & & ( style & STYLE_CONDENSED ) ) {
actcpi = 20.0 ;
horizPoints * = 10.0 / 20.0 ;
vertPoints * = 10.0 / 12.0 ;
2016-10-24 02:17:22 +00:00
}
2016-02-08 05:01:25 +00:00
} else if ( style & STYLE_CONDENSED ) horizPoints / = 2.0 ;
if ( ( style & STYLE_DOUBLEWIDTH ) ) {
actcpi / = 2.0 ;
horizPoints * = 2.0 ;
}
} else { // multipoint true
actcpi = multicpi ;
horizPoints = vertPoints = multiPointSize ;
}
if ( style & STYLE_SUPERSCRIPT | | style & STYLE_SUBSCRIPT | | style & STYLE_HALFHEIGHT ) {
//horizPoints *= 2.0/3.0;
vertPoints * = 2.0 / 3.0 ;
//actcpi /= 2.0/3.0;
}
FT_Set_Char_Size ( curFont , ( Bit16u ) horizPoints * 64 , ( Bit16u ) vertPoints * 64 , dpi , dpi ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
if ( style & STYLE_ITALICS | | charTables [ curCharTable ] = = 0 )
{
FT_Matrix matrix ;
matrix . xx = 0x10000L ;
matrix . xy = ( FT_Fixed ) ( 0.20 * 0x10000L ) ;
matrix . yx = 0 ;
matrix . yy = 0x10000L ;
FT_Set_Transform ( curFont , & matrix , 0 ) ;
}
}
void Imagewriter : : updateSwitch ( )
{
//Set international character mappping (Switches A-1 to A3)
int charmap = switcha & = 7 ;
curMap [ 0x23 ] = intCharSets [ charmap ] [ 0 ] ;
curMap [ 0x40 ] = intCharSets [ charmap ] [ 1 ] ;
curMap [ 0x5b ] = intCharSets [ charmap ] [ 2 ] ;
curMap [ 0x5c ] = intCharSets [ charmap ] [ 3 ] ;
curMap [ 0x5d ] = intCharSets [ charmap ] [ 4 ] ;
curMap [ 0x60 ] = intCharSets [ charmap ] [ 5 ] ;
curMap [ 0x7b ] = intCharSets [ charmap ] [ 6 ] ;
curMap [ 0x7c ] = intCharSets [ charmap ] [ 7 ] ;
curMap [ 0x7d ] = intCharSets [ charmap ] [ 8 ] ;
curMap [ 0x7e ] = intCharSets [ charmap ] [ 9 ] ;
//MSB control (Switch B-6)
if ( ! ( switchb & 32 ) )
{
msb = 255 ;
}
else msb = 0 ;
}
void Imagewriter : : slashzero ( Bit16u penX , Bit16u penY )
{
FT_Face slashFont = curFont ;
FT_UInt slashindex = FT_Get_Char_Index ( slashFont , curMap [ 0x2f ] ) ;
FT_Load_Glyph ( slashFont , slashindex , FT_LOAD_DEFAULT ) ;
FT_Render_Glyph ( slashFont - > glyph , FT_RENDER_MODE_NORMAL ) ;
blitGlyph ( slashFont - > glyph - > bitmap , penX , penY , false ) ;
blitGlyph ( slashFont - > glyph - > bitmap , penX + 1 , penY , true ) ;
if ( style & STYLE_BOLD ) {
blitGlyph ( slashFont - > glyph - > bitmap , penX + 1 , penY , true ) ;
blitGlyph ( slashFont - > glyph - > bitmap , penX + 2 , penY , true ) ;
blitGlyph ( slashFont - > glyph - > bitmap , penX + 3 , penY , true ) ;
}
}
# endif // HAVE_SDL
# ifdef HAVE_SDL
bool Imagewriter : : processCommandChar ( Bit8u ch )
{
if ( ESCSeen | | FSSeen )
{
ESCCmd = ch ;
if ( FSSeen ) ESCCmd | = 0x800 ;
ESCSeen = FSSeen = false ;
numParam = 0 ;
switch ( ESCCmd ) {
case 0x21 : // Select bold font (ESC !) IW
case 0x22 : // Cancel bold font (ESC ") IW
case 0x24 : // Cancel MSB control and Mousetext (ESC $) IW
case 0x2b : // custom char width is 8 dots (ESC -) IW
case 0x2e : // custom char width is 8 dots (ESC +) IW
case 0x30 : // Clear all tabs (ESC 0) IW
case 0x31 : // Insert 1 intercharacter spaces (ESC 1) IW
case 0x32 : // Insert 2 intercharacter spaces (ESC 2) IW
case 0x33 : // Insert 3 intercharacter spaces (ESC 3) IW
case 0x34 : // Insert 4 intercharacter spaces (ESC 4) IW
case 0x35 : // Insert 5 intercharacter spaces (ESC 5) IW
case 0x36 : // Insert 6 intercharacter spaces (ESC 6) IW
case 0x3c : // bidirectional mode (one line) (ESC <) IW
case 0x3e : // Unidirectional mode (one line) (ESC >) IW
case 0x3f : // Send ID string (ESC ?) IW
case 0x41 : // Select 1/6-inch line spacing (ESC A) IW
case 0x42 : // Select 1/8-inch line spacing (ESC B) IW
case 0x45 : // 12 cpi, 96 dpi graphics (ESC E) IW
case 0x4d : // Same as ESC a2 (ESC M) IW
case 0x4e : // 10 cpi, 80 dpi graphics (ESC N) IW
case 0x4f : // Disable paper-out detector (ESC O) IW
case 0x50 : // Proportional, 160 dpi graphics (ESC P) IW
case 0x51 : // 17 cpi, 136 dpi graphics (ESC Q) IW
case 0x57 : // Cancel halfheight printing (ESC W) IW
case 0x58 : // Turn underline on (ESC X) IW
case 0x59 : // Turn underline off (ESC Y) IW
case 0x63 : // Initialize printer (ESC c) IW
case 0x65 : // 13.4 cpi, 107 dpi graphics (ESC e) IW
case 0x66 : // Select forward feed mode (ESC f) IW
case 0x6b : // Select optional font (ESC k) IW LQ
case 0x6d : // Same as ESC a0 (ESC m) IW
case 0x6e : // 9 cpi, 72 dpi graphics (ESC n) IW
case 0x6f : // Enable paper-out detector (ESC o) IW
case 0x70 : // Proportional, 144 dpi graphics (ESC p) IW
case 0x72 : // Select reverse feed mode (ESC r) IW
case 0x71 : // 15 cpi, 120 dpi graphics (ESC q) IW
case 0x77 : // Select halfheight printing (ESC w) IW
case 0x78 : // Select superscript printing (ESC x) IW
case 0x79 : // Select subscript printing (ESC y) IW
case 0x7a : // Cancel superscript/subscript printing (ESC z) IW
neededParam = 0 ;
break ;
case 0x3d : // Internal font ID (ESC = n) IW LQ
case 0x40 : // Select output bin (ESC @ n) IW LQ
case 0x4b : // Select printing color (ESC K n) IW
case 0x61 : // Select font (ESC a n) IW
case 0x6c : // Insert CR before LF and FF (ESC l n) IW
case 0x73 : // Set intercharacter space (ESC s n) IW
case 0x74 : // Shift printing downward n/216 inch (ESC t n) IW LQ
case 0x833 : // Feed n lines of blank space (US n) IW
neededParam = 1 ;
break ;
case 0x44 : // Set soft switches to closed (on)= 1 (ESC D nn) IW
case 0x54 : // Distance between lines to be nn/144 inch (ESC T nn) IW
case 0x5a : // Set soft switches to open (off) = 0 (ESC Z nn) IW
neededParam = 2 ;
break ;
case 0x4c : // Set left margin at column nnn (ESC L nnn) IW
2016-10-24 02:17:22 +00:00
case 0x67 : // Print graphics for next nnn * 8 databytes (ESC g nnn) IW
case 0x75 : // Add one tab stop at nnn (ESC u nnn) IW
2016-02-08 05:01:25 +00:00
neededParam = 3 ;
break ;
case 0x28 : // Set horizontal tabs (ESC ( nnn,) IW
numHorizTabs = 0 ;
case 0x29 : // Delete horizontal tabs (ESC ) nnn,) IW
case 0x43 : // Print hi-res graphics for next nnnn*3 databytes (ESC C nnnn) IW LQ
case 0x47 : // Print graphics for next nnnn databytes (ESC G nnnn) IW
case 0x46 : // Place printhead nnnn dots from left margin (ESC F nnnn) IW
case 0x48 : // Set pagelength to nnnn/144 (ESC H nnnn) IW
case 0x53 : // Print graphics for next nnnn databytes (ESC S nnnn) IW
case 0x52 : // Repeat character c nnn times (ESC R nnn c) IW
case 0x68 : // Place printhead nnnn hi-res dots from left margin (ESC h nnnn) IW LQ
neededParam = 4 ;
break ;
case 0x56 : //Repeat Print nnnn repetitions of dot column c (ESC V nnnn c) IW
neededParam = 5 ;
msb = 255 ;
break ;
case 0x55 : //Repeat Print nnnn repetitions of hi-res dot column abc (ESC U nnnn abc) IW LQ
neededParam = 7 ;
msb = 255 ;
break ;
case 0x27 : // Select user-defined set (ESC ')
case 0x49 : // Define user-defined characters (ESC I)
//LOG(LOG_MISC,LOG_ERROR)("User-defined characters not supported!");
return true ;
default :
/*LOG_MSG("PRINTER: Unknown command %c (%02Xh) %c , unable to skip parameters.",
( ESCCmd & 0x800 ) ? " FS " : " ESC " , ESCCmd , ESCCmd ) ; */
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
neededParam = 0 ;
ESCCmd = 0 ;
return true ;
}
if ( neededParam > 0 )
return true ;
}
if ( numParam < neededParam )
{
params [ numParam + + ] = ch ;
if ( numParam < neededParam )
return true ;
}
if ( ESCCmd ! = 0 )
{
switch ( ESCCmd )
{
case 0x19 : // Control paper loading/ejecting (ESC EM)
// We are not really loading paper, so most commands can be ignored
if ( params [ 0 ] = = ' R ' )
newPage ( true , false ) ; // TODO resetx?
break ;
case 0x73 : // Set intercharacter space (ESC s) IW
if ( style & STYLE_PROP )
{
extraIntraSpace = ( Real64 ) paramc ( 0 ) ;
updateFont ( ) ;
}
break ;
case 0x46 : // Set absolute horizontal print position (ESC F nnnn) IW
{
int x = 0 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
Real64 unitSize = definedUnit ;
if ( unitSize < 0 )
unitSize = ( Real64 ) 72.0 ;
Real64 newX = leftMargin + ( ( Real64 ) PARAM4 ( 0 ) / unitSize ) ;
if ( newX < = rightMargin )
curX = newX ;
}
break ;
case 0x68 : // Set absolute horizontal hi-res print position (ESC h nnnn) IW LQ
{
int x = 0 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
Real64 unitSize = definedUnit * 2 ;
if ( unitSize < 0 )
unitSize = ( Real64 ) 72.0 ;
Real64 newX = leftMargin + ( ( Real64 ) PARAM4 ( 0 ) / unitSize ) ;
if ( newX < = rightMargin )
curX = newX ;
}
break ;
case 0x31 : case 0x32 : case 0x33 : case 0x34 : case 0x35 : case 0x36 : // Insert 1-6 intercharacter spaces (ESC 1 to 6) IW
{
if ( style & STYLE_PROP ) //This function only works in proportional mode
{
Real64 unitSize = definedUnit ;
if ( unitSize < 0 )
unitSize = ( Real64 ) 72.0 ;
Real64 newX = ( ( Real64 ) ( ESCCmd - ' 0 ' ) / unitSize ) ;
if ( newX < = rightMargin )
curX = newX ;
}
break ;
}
case 0x47 : case 0x53 : // Print graphics (ESC G nnnn) IW
{
int x = 0 ;
printRes & = ~ 8 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
setupBitImage ( printRes , PARAM4 ( 0 ) ) ;
break ;
}
case 0x43 : // Print hi-res graphics (ESC G nnnn) IW LQ
{
int x = 0 ;
printRes | = 8 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
setupBitImage ( printRes , PARAM4 ( 0 ) ) ;
break ;
}
case 0x67 : // Print graphics (ESC g nnn) IW
{
int x = 0 ;
printRes & = ~ 8 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
setupBitImage ( printRes , ( PARAM3 ( 0 ) * 8 ) ) ;
break ;
}
case 0x56 : //Repeat Print nnnn repetitions of dot column byte c (ESC V nnnn c)IW
{
int x = 0 ;
printRes & = ~ 8 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
x = 0 ;
while ( x < PARAM4 ( 0 ) )
{
setupBitImage ( printRes , 1 ) ;
printBitGraph ( params [ 4 ] ) ;
x + + ;
}
msb = 0 ;
break ;
}
case 0x55 : //Repeat Print nnnn repetitions of hi-res dot column byte abc (ESC U nnnn abc) IW LQ
{
int x = 0 ;
printRes | = 8 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
x = 0 ;
while ( x < PARAM4 ( 0 ) )
{
setupBitImage ( printRes , 1 ) ;
printBitGraph ( params [ 4 ] ) ;
printBitGraph ( params [ 5 ] ) ;
printBitGraph ( params [ 6 ] ) ;
x + + ;
}
msb = 0 ;
break ;
}
case 0x74 : // Shift printing downward n/216 inch (ESC t n) IW LQ
{
verticalDot = paramc ( 0 ) ;
break ;
}
case 0x6e : // 9 cpi, 72/144 dpi graphics (ESC n) IW
cpi = 9.0 ;
style & = ( 0xffff - STYLE_PROP ) ;
printRes = 0 ;
definedUnit = 72 ;
extraIntraSpace = 0.0 ;
LQtypeFace = fixed ;
updateFont ( ) ;
break ;
case 0x4e : // 10 cpi, 80/160 dpi graphics (ESC N) IW
cpi = 10.0 ;
printRes = 1 ;
style & = ( 0xffff - STYLE_PROP ) ;
definedUnit = 80 ;
extraIntraSpace = 0.0 ;
LQtypeFace = fixed ;
updateFont ( ) ;
break ;
case 0x45 : // 12 cpi, 96/192 dpi graphics (ESC E) IW
cpi = 12.0 ;
printRes = 2 ;
style & = ( 0xffff - STYLE_PROP ) ;
definedUnit = 96 ;
extraIntraSpace = 0.0 ;
LQtypeFace = fixed ;
updateFont ( ) ;
break ;
case 0x65 : // 13.4 cpi, 107/216 dpi graphics (ESC e) IW
cpi = 13.4 ;
printRes = 3 ;
style & = ( 0xffff - STYLE_PROP ) ;
definedUnit = 107 ;
extraIntraSpace = 0.0 ;
LQtypeFace = fixed ;
updateFont ( ) ;
break ;
case 0x71 : // 15 cpi, 120/240 dpi graphics (ESC q) IW
cpi = 15 ;
printRes = 4 ;
style & = ( 0xffff - STYLE_PROP ) ;
definedUnit = 120 ;
extraIntraSpace = 0.0 ;
LQtypeFace = fixed ;
updateFont ( ) ;
break ;
case 0x51 : // 17 cpi, 136/272 dpi graphics (ESC Q) IW
cpi = 17 ;
printRes = 5 ;
style & = ( 0xffff - STYLE_PROP ) ;
definedUnit = 136 ;
extraIntraSpace = 0.0 ;
LQtypeFace = fixed ;
updateFont ( ) ;
break ;
case 0x70 : // Proportional, 144/288 dpi graphics (ESC p) IW
style | = STYLE_PROP ;
cpi = 10 ;
//printQuality = QUALITY_LQ;
printRes = 6 ;
definedUnit = 144 ;
LQtypeFace = prop ;
updateFont ( ) ;
break ;
case 0x50 : // Proportional, 160/320 dpi graphics (ESC P) IW
style | = STYLE_PROP ;
cpi = 12 ;
//printQuality = QUALITY_LQ;
printRes = 7 ;
definedUnit = 160 ;
LQtypeFace = prop ;
updateFont ( ) ;
break ;
case 0x54 : // Set n/144-inch line spacing (ESC T nn) IW
lineSpacing = ( Real64 ) PARAM2 ( 0 ) / 144 ;
break ;
case 0x59 : // Turn underline off (ESC Y) IW
style & = ~ STYLE_UNDERLINE ;
updateFont ( ) ;
break ;
case 0x58 : // Turn underline on (ESC X) IW
style | = STYLE_UNDERLINE ;
score = SCORE_SINGLE ;
updateFont ( ) ;
break ;
case 0x42 : // Select 1/8-inch line spacing (ESC B) IW
lineSpacing = ( Real64 ) 1 / 8 ;
break ;
case 0x41 : // Select 1/6-inch line spacing (ESC A) IW
lineSpacing = ( Real64 ) 1 / 6 ;
break ;
case 0x3c : case 0x3e : // Unidirectional mode (one line) (ESC <)
// We don't have a print head, so just ignore this
break ;
case 0x63 : // Initialize printer (ESC c) IW
resetPrinter ( ) ;
break ;
case 0x48 : // Set page length in lines (ESC H nnnn) IW
{
int x = 0 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
pageHeight = ( Real64 ) PARAM4 ( 0 ) / 144 ;
bottomMargin = pageHeight ;
topMargin = 0.0 ;
break ;
}
case 0x21 : // Select bold font (ESC !) IW
style | = STYLE_BOLD ;
updateFont ( ) ;
break ;
case 0x22 : // Cancel bold font (ESC ") IW
style & = ~ STYLE_BOLD ;
updateFont ( ) ;
break ;
case 0x78 : // Select superscript printing (ESC x) IW
style | = STYLE_SUPERSCRIPT ;
updateFont ( ) ;
break ;
case 0x79 : // Select subscript printing (ESC y) IW
style | = STYLE_SUBSCRIPT ;
updateFont ( ) ;
break ;
case 0x7a : // Cancel superscript/subscript printing (ESC z) IW
style & = 0xFFFF - STYLE_SUPERSCRIPT - STYLE_SUBSCRIPT ;
updateFont ( ) ;
break ;
case 0x77 : // Select halfheight printing (ESC w) IW
style | = STYLE_HALFHEIGHT ;
updateFont ( ) ;
break ;
case 0x57 : // Cancel halfheight printing (ESC W) IW
style & = ~ STYLE_HALFHEIGHT ;
updateFont ( ) ;
break ;
case 0x72 : // Reverse paper feed (ESC r) IW
{
printf ( " Reverse Feed \n " ) ;
if ( lineSpacing > 0 ) lineSpacing * = - 1 ;
break ;
}
case 0x66 : // Forward paper feed (ESC f) IW
{
if ( lineSpacing < 0 ) lineSpacing * = - 1 ;
break ;
}
case 0x61 : // Select typeface (ESC a n) IW worry about this later
break ;
case 0x6d : case 0x4d : //Same as ESC a n commands
break ;
case 0x4c : // Set left margin (ESC L nnn) IW
{
int x = 0 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
leftMargin = ( Real64 ) ( PARAM3 ( 0 ) - 1.0 ) / ( Real64 ) cpi ;
if ( curX < leftMargin )
curX = leftMargin ;
break ;
}
case 0x4b : // Select printing color (ESC K) IW
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
switch ( paramc ( 0 ) )
{
case 0 : break ;
case 1 : params [ 0 ] = 4 ; break ;
case 2 : params [ 0 ] = 1 ; break ;
case 3 : params [ 0 ] = 2 ; break ;
case 4 : params [ 0 ] = 5 ; break ;
case 5 : params [ 0 ] = 6 ; break ;
case 6 : params [ 0 ] = 3 ; break ;
}
if ( paramc ( 0 ) = = 0 ) color = COLOR_BLACK ;
2016-10-24 02:17:22 +00:00
else color = params [ 0 ] < < 5 ;
2016-02-08 05:01:25 +00:00
break ;
case 0x3d : // Internal font ID (ESC = n) IW LQ
//Ignore for now
break ;
case 0x3f : //Send ID string to computer (ESC ?) IW
//insert SCC send code here
printf ( " Sending ID String \n " ) ;
iw_scc_write = true ;
break ;
case 0x52 : // Repeat character c for nnn times (ESC R nnn c) IW
{
int x = 0 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
x = 0 ;
ESCCmd = 0 ;
while ( x < PARAM3 ( 0 ) )
2016-10-24 02:17:22 +00:00
{
2016-02-08 05:01:25 +00:00
printChar ( params [ 3 ] ) ;
x + + ;
}
break ;
}
case 0x30 : //Clear all tabs
numHorizTabs = 0 ;
break ;
case 0x28 : // Set horizontal tabs (ESC ( nnn,) IW
{
int x = 0 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
if ( params [ 3 ] = = ' . ' | | ( numHorizTabs > 0 & & horiztabs [ numHorizTabs - 1 ] > ( Real64 ) PARAM3 ( 0 ) * ( 1 / ( Real64 ) cpi ) ) )
{
horiztabs [ numHorizTabs + + ] = ( Real64 ) PARAM3 ( 0 ) * ( 1 / ( Real64 ) cpi ) ;
//printf("Adding tab %d, and end\n",PARAM3(0));
//printf("Number of Tabs:%d\n",numHorizTabs);
}
else if ( params [ 3 ] = = ' , ' & & numHorizTabs < 32 )
{
horiztabs [ numHorizTabs + + ] = ( Real64 ) PARAM3 ( 0 ) * ( 1 / ( Real64 ) cpi ) ;
numParam = 0 ;
neededParam = 4 ;
//printf("Adding tab %d, plus more\n", PARAM3(0));
//printf("Number of Tabs:%d\n",numHorizTabs);
return true ;
}
x = 0 ;
break ;
}
case 0x29 : // Delete horizontal tabs (ESC ) nnn,) IW
{
int x = 0 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
x = 0 ;
while ( x < numHorizTabs )
{
2016-10-24 02:17:22 +00:00
if ( horiztabs [ x ] = = ( Real64 ) PARAM3 ( 0 ) * ( 1 / ( Real64 ) cpi ) )
2016-02-08 05:01:25 +00:00
{ printf ( " Tab Found %d \n " , PARAM3 ( 0 ) ) ;
horiztabs [ x ] = 0 ;
}
x + + ;
}
if ( params [ 3 ] = = ' . ' )
{
printf ( " Deleting tab %d, and end \n " , PARAM3 ( 0 ) ) ;
}
else if ( params [ 3 ] = = ' , ' )
{
numParam = 0 ;
neededParam = 4 ;
//printf("Deleting tab %d, plus more\n", PARAM3(0));
return true ;
}
x = 0 ;
break ;
}
case 0x5a : // Set switches to open (off) (ESC Z nn) IW
//printf ("switcha is: %x switchb is: %x\n",switcha,switchb);
//printf ("(Setting to 0) param 0 is: %x param 1 is: %x\n",params[0],params[1]);
switcha & = ~ params [ 0 ] ;
switchb & = ~ params [ 1 ] ;
//printf ("switcha is now: %x switchb is now: %x\n",switcha,switchb);
updateSwitch ( ) ;
break ;
case 0x44 : // Set switches to closed (on) (ESC D nn) IW
//printf ("switcha is: %x switchb is: %x\n",switcha,switchb);
//printf ("(Setting to 1) param 0 is: %x param 1 is: %x\n",params[0],params[1]);
switcha | = params [ 0 ] ;
switchb | = params [ 1 ] ;
//printf ("switcha is now: %x switchb is now: %x\n",switcha,switchb);
updateSwitch ( ) ;
break ;
case 0x75 : // Add one tab stop at nnn (ESC u nnn) IW
{
bool haveStop = false ;
int lastEmpty ;
//If the list is full, we assume there are no empty spaces to fill until the list is scanned
if ( numHorizTabs = = 32 ) lastEmpty = 33 ;
else lastEmpty = numHorizTabs ;
int x = 0 ;
//convert any leading spaces in parameters to zeros
while ( x < 4 )
{
if ( params [ x ] = = ' ' ) params [ x ] = ' 0 ' ;
x + + ;
}
x = 0 ;
//see if we have the tab stop already on the list and check for any deleted entries to reuse
while ( x < numHorizTabs )
{
if ( horiztabs [ x ] = = ( Real64 ) PARAM3 ( 0 ) * ( 1 / ( Real64 ) cpi ) )
2016-10-24 02:17:22 +00:00
{
2016-02-08 05:01:25 +00:00
//printf("We have this tab already! at list entry: %d\n", x);
haveStop = true ;
}
if ( horiztabs [ x ] = = 0 ) lastEmpty = x ;
//printf("at list entry: %d\n", x);
x + + ;
}
if ( ! haveStop & & lastEmpty < 33 )
{
//printf("Adding tab %d\n", PARAM3(0));
horiztabs [ lastEmpty ] = ( Real64 ) PARAM3 ( 0 ) * ( 1 / ( Real64 ) cpi ) ;
if ( lastEmpty = = numHorizTabs ) numHorizTabs + + ; //only increase if we don't reuse an empty tab entry
//printf("Number of Tabs:%d\n",numHorizTabs);
}
}
break ;
case 0x833 : // Feed n lines of blank space (US n) IW
{
int x = 0 ;
while ( x < paramc ( 0 ) )
{
curY + = lineSpacing ;
if ( curY > bottomMargin )
newPage ( true , false ) ;
x + + ;
}
}
break ;
default :
if ( ESCCmd < 0x100 ) ;
//LOG(LOG_MISC,LOG_WARN)
//LOG_MSG("PRINTER: Skipped unsupported command ESC %c (%02X)", ESCCmd, ESCCmd);
else ;
//LOG(LOG_MISC,LOG_WARN)
//LOG_MSG("PRINTER: Skipped unsupported command ESC ( %c (%02X)", ESCCmd-0x200, ESCCmd-0x200);
}
ESCCmd = 0 ;
return true ;
}
switch ( ch )
{
case 0x00 : // NUL is ignored by the printer
return true ;
case 0x07 : // Beeper (BEL)
// BEEEP!
return true ;
case 0x08 : // Backspace (BS)
{
Real64 newX = curX - ( 1 / ( Real64 ) actcpi ) ;
if ( hmi > 0 )
newX = curX - hmi ;
if ( newX > = leftMargin )
curX = newX ;
}
return true ;
case 0x09 : // Tab horizontally (HT)
{
// Find tab right to current pos
Real64 moveTo = - 1 ;
for ( Bit8u i = 0 ; i < numHorizTabs ; i + + )
if ( horiztabs [ i ] > curX )
moveTo = horiztabs [ i ] ;
// Nothing found => Ignore
if ( moveTo > 0 & & moveTo < rightMargin )
curX = moveTo ;
}
return true ;
case 0x0b : // Tab vertically (VT)
if ( numVertTabs = = 0 ) // All tabs cancelled => Act like CR
curX = leftMargin ;
else if ( numVertTabs = = 255 ) // No tabs set since reset => Act like LF
{
curX = leftMargin ;
curY + = lineSpacing ;
if ( curY > bottomMargin )
newPage ( true , false ) ;
}
else
{
// Find tab below current pos
Real64 moveTo = - 1 ;
for ( Bit8u i = 0 ; i < numVertTabs ; i + + )
if ( verttabs [ i ] > curY )
moveTo = verttabs [ i ] ;
// Nothing found => Act like FF
if ( moveTo > bottomMargin | | moveTo < 0 )
newPage ( true , false ) ;
else
curY = moveTo ;
}
return true ;
case 0x0c : // Form feed (FF)
newPage ( true , true ) ;
return true ;
case 0x0d : // Carriage Return (CR)
curX = leftMargin ;
if ( ( switcha & = 128 ) ) curY + = lineSpacing ; // If switch A-8 is set, send a LF after CR
if ( ! autoFeed )
return true ;
case 0x0a : // Line feed
//curX = leftMargin;
curY + = lineSpacing ;
if ( curY > bottomMargin )
newPage ( true , false ) ;
return true ;
case 0x0e : //Select double width printing (SO) IW
style | = STYLE_DOUBLEWIDTH ;
updateFont ( ) ;
return true ;
case 0x0f : // Dis-select double width printing (SI) IW
style & = ~ STYLE_DOUBLEWIDTH ;
updateFont ( ) ;
return true ;
case 0x11 : // Select printer (DC1)
// Ignore
return true ;
case 0x12 : // Cancel condensed printing (DC2)
hmi = - 1 ;
style & = ~ STYLE_CONDENSED ;
updateFont ( ) ;
return true ;
case 0x13 : // Deselect printer (DC3)
// Ignore
return true ;
case 0x14 : // Cancel double-width printing (one line) (DC4)
return true ;
case 0x18 : // Cancel line (CAN)
return true ;
case 0x1b : // ESC
ESCSeen = true ;
return true ;
case 0x1f : // unit seperator (US) Feed 1 to 15 line commands
FSSeen = true ;
return true ;
default :
return false ;
}
return false ;
}
# endif // HAVE_SDL
//static void PRINTER_EventHandler(Bitu param);
void Imagewriter : : newPage ( bool save , bool resetx )
{
//PIC_RemoveEvents(PRINTER_EventHandler);
if ( printer_timout ) timeout_dirty = false ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
# ifdef HAVE_SDL
if ( save )
outputPage ( ) ;
if ( resetx ) curX = leftMargin ;
curY = topMargin ;
SDL_Rect rect ;
rect . x = 0 ;
rect . y = 0 ;
rect . w = page - > w ;
rect . h = page - > h ;
SDL_FillRect ( page , & rect , SDL_MapRGB ( page - > format , 255 , 255 , 255 ) ) ;
/*for(int i = 0; i < 256; i++)
{
* ( ( Bit8u * ) page - > pixels + i ) = i ;
} */
# endif // HAVE_SDL
if ( strcasecmp ( output , " text " ) = = 0 ) { /* Text file */
if ( textPrinterFile ) {
fclose ( textPrinterFile ) ;
textPrinterFile = NULL ;
}
}
}
void Imagewriter : : printChar ( Bit8u ch )
{
# ifdef HAVE_SDL
charRead = true ;
if ( page = = NULL ) return ;
// Apply MSB if desired, but only if we aren't printing graphics!
if ( msb ! = 255 ) {
if ( ! bitGraph . remBytes ) ch & = 0x7F ;
}
# endif // HAVE_SDL
if ( strcasecmp ( output , " text " ) = = 0 ) {
if ( ! textPrinterFile ) {
textPrinterFile = fopen ( textPrinterFileName , " ab " ) ;
}
fprintf ( textPrinterFile , " %c " , ch ) ;
fflush ( textPrinterFile ) ;
return ;
}
# ifdef HAVE_SDL
// Are we currently printing a bit graphic?
if ( bitGraph . remBytes > 0 ) {
printBitGraph ( ch ) ;
return ;
}
// Print everything?
if ( numPrintAsChar > 0 ) numPrintAsChar - - ;
else if ( processCommandChar ( ch ) ) return ;
// Do not print if no font is available
if ( ! curFont ) return ;
if ( ch = = 0x1 ) ch = 0x20 ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
// Find the glyph for the char to render
FT_UInt index = FT_Get_Char_Index ( curFont , curMap [ ch ] ) ;
2016-10-24 02:17:22 +00:00
// Load the glyph
2016-02-08 05:01:25 +00:00
FT_Load_Glyph ( curFont , index , FT_LOAD_DEFAULT ) ;
// Render a high-quality bitmap
FT_Render_Glyph ( curFont - > glyph , FT_RENDER_MODE_NORMAL ) ;
Bit16u penX = PIXX + curFont - > glyph - > bitmap_left ;
Bit16u penY = PIXY - curFont - > glyph - > bitmap_top + curFont - > size - > metrics . ascender / 64 ;
//if (style & STYLE_SUBSCRIPT) penY += curFont->glyph->bitmap.rows / 2;
//if (style & STYLE_HALFHEIGHT) penY += curFont->glyph->bitmap.rows / 4;
if ( style & STYLE_SUBSCRIPT ) penY + = 20 ;
if ( style & STYLE_SUPERSCRIPT ) penY - = 10 ;
if ( style & STYLE_HALFHEIGHT ) penY + = 15 ;
// Copy bitmap into page
SDL_LockSurface ( page ) ;
blitGlyph ( curFont - > glyph - > bitmap , penX , penY , false ) ;
blitGlyph ( curFont - > glyph - > bitmap , penX + 1 , penY , true ) ;
// Bold => Print the glyph a second time one pixel to the right
// or be a bit more bold...
if ( style & STYLE_BOLD ) {
blitGlyph ( curFont - > glyph - > bitmap , penX + 1 , penY , true ) ;
blitGlyph ( curFont - > glyph - > bitmap , penX + 2 , penY , true ) ;
blitGlyph ( curFont - > glyph - > bitmap , penX + 3 , penY , true ) ;
}
SDL_UnlockSurface ( page ) ;
// For line printing
Bit16u lineStart = PIXX ;
// Print a slashed zero if the softswitch B-1 is set
if ( switchb & 1 & & ch = = ' 0 ' ) slashzero ( penX , penY ) ;
// advance the cursor to the right
Real64 x_advance ;
if ( style & STYLE_PROP )
x_advance = ( Real64 ) ( ( Real64 ) ( curFont - > glyph - > advance . x ) / ( Real64 ) ( dpi * 64 ) ) ;
else {
x_advance = 1 / ( Real64 ) actcpi ;
}
x_advance + = extraIntraSpace ;
curX + = x_advance ;
// Draw lines if desired
2016-10-24 02:17:22 +00:00
if ( ( score ! = SCORE_NONE ) & & ( style &
2016-02-08 05:01:25 +00:00
( STYLE_UNDERLINE ) ) )
{
// Find out where to put the line
Bit16u lineY = PIXY ;
double height = ( curFont - > size - > metrics . height > > 6 ) ; // TODO height is fixed point madness...
if ( style & STYLE_UNDERLINE ) lineY = PIXY + ( Bit16u ) ( height * 0.9 ) ;
drawLine ( lineStart , PIXX , lineY , score = = SCORE_SINGLEBROKEN | | score = = SCORE_DOUBLEBROKEN ) ;
// draw second line if needed
if ( ( score = = SCORE_DOUBLE ) | | ( score = = SCORE_DOUBLEBROKEN ) )
drawLine ( lineStart , PIXX , lineY + 5 , score = = SCORE_SINGLEBROKEN | | score = = SCORE_DOUBLEBROKEN ) ;
}
// If the next character would go beyond the right margin, line-wrap.
if ( ( curX + x_advance ) > rightMargin ) {
curX = leftMargin ;
curY + = lineSpacing ;
if ( curY > bottomMargin ) newPage ( true , false ) ;
}
# endif // HAVE_SDL
}
# ifdef HAVE_SDL
void Imagewriter : : blitGlyph ( FT_Bitmap bitmap , Bit16u destx , Bit16u desty , bool add ) {
for ( Bitu y = 0 ; y < bitmap . rows ; y + + ) {
for ( Bitu x = 0 ; x < bitmap . width ; x + + ) {
// Read pixel from glyph bitmap
Bit8u source = * ( bitmap . buffer + x + y * bitmap . pitch ) ;
// Ignore background and don't go over the border
if ( source > 0 & & ( destx + x < page - > w ) & & ( desty + y < page - > h ) ) {
Bit8u * target = ( Bit8u * ) page - > pixels + ( x + destx ) + ( y + desty ) * page - > pitch ;
source > > = 3 ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
if ( add ) {
if ( ( ( * target ) & 0x1f ) + source > 31 ) * target | = ( color | 0x1f ) ;
else {
* target + = source ;
* target | = color ;
}
}
else * target = source | color ;
}
}
}
}
void Imagewriter : : drawLine ( Bitu fromx , Bitu tox , Bitu y , bool broken )
{
SDL_LockSurface ( page ) ;
Bitu breakmod = dpi / 15 ;
Bitu gapstart = ( breakmod * 4 ) / 5 ;
// Draw anti-aliased line
for ( Bitu x = fromx ; x < = tox ; x + + )
{
// Skip parts if broken line or going over the border
if ( ( ! broken | | ( x % breakmod < = gapstart ) ) & & ( x < page - > w ) )
{
if ( y > 0 & & ( y - 1 ) < page - > h )
* ( ( Bit8u * ) page - > pixels + x + ( y - 1 ) * page - > pitch ) = 240 ;
if ( y < page - > h )
* ( ( Bit8u * ) page - > pixels + x + y * page - > pitch ) = ! broken ? 255 : 240 ;
if ( y + 1 < page - > h )
* ( ( Bit8u * ) page - > pixels + x + ( y + 1 ) * page - > pitch ) = 240 ;
}
}
SDL_UnlockSurface ( page ) ;
}
void Imagewriter : : setAutofeed ( bool feed ) {
autoFeed = feed ;
}
bool Imagewriter : : getAutofeed ( ) {
return autoFeed ;
}
bool Imagewriter : : isBusy ( ) {
// We're never busy
return false ;
}
bool Imagewriter : : ack ( ) {
// Acknowledge last char read
if ( charRead ) {
charRead = false ;
return true ;
}
return false ;
}
void Imagewriter : : setupBitImage ( Bit8u dens , Bit16u numCols ) {
switch ( dens )
{
case 0 :
bitGraph . horizDens = 72 ;
bitGraph . vertDens = 72 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 1 ;
break ;
case 1 :
bitGraph . horizDens = 80 ;
bitGraph . vertDens = 72 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 1 ;
break ;
case 2 :
bitGraph . horizDens = 96 ;
bitGraph . vertDens = 72 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 1 ;
break ;
case 3 :
bitGraph . horizDens = 107 ;
bitGraph . vertDens = 72 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 1 ;
break ;
case 4 :
bitGraph . horizDens = 120 ;
bitGraph . vertDens = 72 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 1 ;
break ;
case 5 :
bitGraph . horizDens = 136 ;
bitGraph . vertDens = 72 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 1 ;
break ;
case 6 :
bitGraph . horizDens = 144 ;
bitGraph . vertDens = 72 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 1 ;
break ;
case 7 :
bitGraph . horizDens = 160 ;
bitGraph . vertDens = 72 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 1 ;
break ;
//Imagewriter LQ resolutions
case 8 :
bitGraph . horizDens = 144 ;
bitGraph . vertDens = 216 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 3 ;
break ;
case 9 :
bitGraph . horizDens = 160 ;
bitGraph . vertDens = 216 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 3 ;
break ;
case 10 :
bitGraph . horizDens = 192 ;
bitGraph . vertDens = 216 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 3 ;
break ;
case 11 :
bitGraph . horizDens = 216 ;
bitGraph . vertDens = 216 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 3 ;
break ;
case 12 :
bitGraph . horizDens = 240 ;
bitGraph . vertDens = 216 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 3 ;
break ;
case 13 :
bitGraph . horizDens = 272 ;
bitGraph . vertDens = 216 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 3 ;
break ;
case 14 :
bitGraph . horizDens = 288 ;
bitGraph . vertDens = 216 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 3 ;
break ;
case 15 :
bitGraph . horizDens = 320 ;
bitGraph . vertDens = 216 ;
bitGraph . adjacent = true ;
bitGraph . bytesColumn = 3 ;
break ;
default :
//break;
printf ( " PRINTER: Unsupported bit image density " ) ;
}
bitGraph . remBytes = numCols * bitGraph . bytesColumn ;
bitGraph . readBytesColumn = 0 ;
}
void Imagewriter : : printBitGraph ( Bit8u ch )
{
bitGraph . column [ bitGraph . readBytesColumn + + ] = ch ;
bitGraph . remBytes - - ;
// Only print after reading a full column
if ( bitGraph . readBytesColumn < bitGraph . bytesColumn )
return ;
Real64 oldY = curY ;
SDL_LockSurface ( page ) ;
// When page dpi is greater than graphics dpi, the drawn pixels get "bigger"
2016-10-24 02:17:22 +00:00
Bitu pixsizeX = 1 ;
2016-02-08 05:01:25 +00:00
Bitu pixsizeY = 1 ;
if ( bitGraph . adjacent ) {
pixsizeX = dpi / bitGraph . horizDens > 0 ? dpi / bitGraph . horizDens : 1 ;
if ( dpi % bitGraph . horizDens & & bitGraph . horizDens < dpi )
{
if ( PIXX % ( bitGraph . horizDens * 8 ) | | ( PIXX = = 0 ) ) //Primative scaling function
{
pixsizeX + + ;
}
}
pixsizeY = dpi / bitGraph . vertDens > 0 ? dpi / bitGraph . vertDens : 1 ;
if ( bitGraph . vertDens = = 216 )
{
if ( PIXY % ( bitGraph . vertDens * 8 ) | | ( PIXY = = 0 ) ) //Primative scaling function
{
pixsizeY + + ;
}
}
}
if ( ( printRes > 7 ) & & ( verticalDot ! = 0 ) ) //for ESC t
{
curY + = ( Real64 ) verticalDot / ( Real64 ) bitGraph . vertDens ;
}
// TODO figure this out for 360dpi mode in windows
// Bitu pixsizeX = dpi/bitGraph.horizDens > 0? dpi/bitGraph.horizDens : 1;
// Bitu pixsizeY = dpi/bitGraph.vertDens > 0? dpi/bitGraph.vertDens : 1;
for ( Bitu i = 0 ; i < bitGraph . bytesColumn ; i + + ) // for each byte
{
for ( Bitu j = 1 ; j < 256 ; j < < = 1 ) { // for each bit
if ( bitGraph . column [ i ] & j ) {
for ( Bitu xx = 0 ; xx < pixsizeX ; xx + + )
for ( Bitu yy = 0 ; yy < pixsizeY ; yy + + ) {
if ( ( ( PIXX + xx ) < page - > w ) & & ( ( PIXY + yy ) < page - > h ) )
* ( ( Bit8u * ) page - > pixels + ( PIXX + xx ) + ( PIXY + yy ) * page - > pitch ) | = ( color | 0x1F ) ;
}
} // else white pixel
curY + = ( Real64 ) 1 / ( Real64 ) bitGraph . vertDens ; // TODO line wrap?
}
}
SDL_UnlockSurface ( page ) ;
curY = oldY ;
bitGraph . readBytesColumn = 0 ;
// Advance to the left
curX + = ( Real64 ) 1 / ( Real64 ) bitGraph . horizDens ;
}
# endif // HAVE_SDL
void Imagewriter : : formFeed ( )
{
# ifdef HAVE_SDL
// Don't output blank pages
newPage ( ! isBlank ( ) , true ) ;
finishMultipage ( ) ;
# endif // HAVE_SDL
}
# ifdef HAVE_SDL
static void findNextName ( char * front , char * ext , char * fname )
{
document_path = " " ;
Bitu i = 1 ;
Bitu slen = strlen ( document_path ) ;
if ( slen > ( 200 - 15 ) ) {
fname [ 0 ] = 0 ;
return ;
}
FILE * test = NULL ;
do
{
strcpy ( fname , document_path ) ;
2016-10-24 02:17:22 +00:00
printf ( " %s " , fname ) ;
2016-02-08 05:01:25 +00:00
# ifdef WIN32
const char * const pathstring = " . \\ %s%d%s " ;
2016-10-24 02:17:22 +00:00
# else
2016-02-08 05:01:25 +00:00
const char * const pathstring = " ./%s%d%s " ;
# endif
sprintf ( fname + strlen ( fname ) , pathstring , front , i + + , ext ) ;
test = fopen ( fname , " rb " ) ;
if ( test ! = NULL )
fclose ( test ) ;
}
while ( test ! = NULL ) ;
}
2016-10-24 02:17:22 +00:00
void Imagewriter : : outputPage ( )
2016-02-08 05:01:25 +00:00
{ /*
SDL_Surface * screen ;
screen = SDL_SetVideoMode ( 1024 , 768 , 16 , SDL_DOUBLEBUF | SDL_RESIZABLE ) ;
if ( screen = = NULL ) {
printf ( " Unable to set video mode: %s \n " , SDL_GetError ( ) ) ;
}
SDL_Surface * image ;
SDL_LockSurface ( page ) ;
image = SDL_DisplayFormat ( page ) ;
SDL_UnlockSurface ( page ) ;
SDL_Rect src , dest ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
src . x = 0 ;
src . y = 0 ;
src . w = image - > w ;
src . h = image - > h ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
dest . x = 100 ;
dest . y = 100 ;
dest . w = image - > w ;
dest . h = image - > h ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
SDL_BlitSurface ( image , & src , screen , & dest ) ;
SDL_Flip ( screen ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
SDL_Delay ( 2000 ) ;
SDL_FreeSurface ( image ) ; */
char fname [ 200 ] ;
if ( strcasecmp ( output , " printer " ) = = 0 )
{
# if defined (WIN32)
if ( multipageOutput & & outputHandle = = NULL )
{
ShowCursor ( 1 ) ;
PRINTDLG pd ;
2016-10-24 02:17:22 +00:00
pd . lStructSize = sizeof ( PRINTDLG ) ;
pd . hDevMode = ( HANDLE ) NULL ;
pd . hDevNames = ( HANDLE ) NULL ;
pd . Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE ;
pd . hwndOwner = NULL ;
pd . hDC = ( HDC ) NULL ;
pd . nFromPage = 0xFFFF ;
2016-02-08 05:01:25 +00:00
pd . nToPage = 0xFFFF ;
2016-10-24 02:17:22 +00:00
pd . nMinPage = 1 ;
pd . nMaxPage = 0xFFFF ;
pd . nCopies = 1 ;
pd . hInstance = NULL ;
pd . lCustData = 0L ;
pd . lpfnPrintHook = ( LPPRINTHOOKPROC ) NULL ;
pd . lpfnSetupHook = ( LPSETUPHOOKPROC ) NULL ;
pd . lpPrintTemplateName = ( LPCSTR ) NULL ;
pd . lpSetupTemplateName = ( LPCSTR ) NULL ;
pd . hPrintTemplate = ( HANDLE ) NULL ;
pd . hSetupTemplate = ( HANDLE ) NULL ;
2016-02-08 05:01:25 +00:00
if ( ! PrintDlg ( & pd ) )
{
//If user clicks cancel, show warning dialog and force all output to bitmaps as failsafe.
MessageBox ( NULL , " You did not select a printer. \n All output from this print job will be saved as bitmap files. " , NULL , MB_ICONEXCLAMATION ) ;
2016-10-24 02:17:22 +00:00
findNextName ( ( char * ) " page " , ( char * ) " .bmp " , & fname [ 0 ] ) ;
2016-02-08 05:01:25 +00:00
SDL_SaveBMP ( page , fname ) ; //Save first page as bitmap.
outputHandle = printerDC ;
printerDC = NULL ;
ShowCursor ( 0 ) ;
return ;
}
else
{
//Create device context.
printerDC = pd . hDC ;
ShowCursor ( 0 ) ;
}
}
if ( ! printerDC ) //Fall thru for subsequent pages if printer dialog was cancelled.
{
2016-10-24 02:17:22 +00:00
findNextName ( ( char * ) " page " , ( char * ) " .bmp " , & fname [ 0 ] ) ;
2016-02-08 05:01:25 +00:00
SDL_SaveBMP ( page , fname ) ; //Save remaining pages.
return ;
}
Bit32u physW = GetDeviceCaps ( printerDC , PHYSICALWIDTH ) ;
Bit32u physH = GetDeviceCaps ( printerDC , PHYSICALHEIGHT ) ;
Bit16u printeroffsetW = GetDeviceCaps ( printerDC , PHYSICALOFFSETX ) ; //printer x offset in actual pixels
Bit16u printeroffsetH = GetDeviceCaps ( printerDC , PHYSICALOFFSETY ) ; //printer y offset in actual pixels
Bit16u deviceDPIW = GetDeviceCaps ( printerDC , LOGPIXELSX ) ;
Bit16u deviceDPIH = GetDeviceCaps ( printerDC , LOGPIXELSY ) ;
Real64 physoffsetW = ( Real64 ) printeroffsetW / deviceDPIW ; //printer x offset in inches
Real64 physoffsetH = ( Real64 ) printeroffsetH / deviceDPIH ; //printer y offset in inches
Bit16u dpiW = page - > w / defaultPageWidth ; //Get currently set DPI of the emulated printer in an indirect way
Bit16u dpiH = page - > h / defaultPageHeight ;
Real64 soffsetW = physoffsetW * dpiW ; //virtual page x offset in actual pixels
Real64 soffsetH = physoffsetH * dpiH ; //virtual page y offset in actual pixels
HDC memHDC = CreateCompatibleDC ( printerDC ) ;
BITMAPINFO * BitmapInfo ;
HBITMAP bitmap ;
// Start new printer job?
if ( outputHandle = = NULL )
{
DOCINFO docinfo ;
docinfo . cbSize = sizeof ( docinfo ) ;
docinfo . lpszDocName = " GSport Virtual ImageWriter " ;
docinfo . lpszOutput = NULL ;
docinfo . lpszDatatype = NULL ;
docinfo . fwType = 0 ;
StartDoc ( printerDC , & docinfo ) ;
multiPageCounter = 1 ;
}
SDL_LockSurface ( page ) ;
StartPage ( printerDC ) ;
DWORD TotalSize ;
HGDIOBJ Prev ;
void * Pixels ;
BitmapInfo = ( BITMAPINFO * )
malloc ( sizeof ( BITMAPINFO ) + 255 * sizeof ( RGBQUAD ) ) ;
memset ( BitmapInfo , 0 , sizeof ( bitmap ) ) ;
BitmapInfo - > bmiHeader . biSize = sizeof ( BITMAPINFOHEADER ) ;
BitmapInfo - > bmiHeader . biWidth = page - > w ;
BitmapInfo - > bmiHeader . biHeight = - page - > h ;
BitmapInfo - > bmiHeader . biPlanes = 1 ;
BitmapInfo - > bmiHeader . biBitCount = page - > format - > BitsPerPixel ;
BitmapInfo - > bmiHeader . biCompression = BI_RGB ;
BitmapInfo - > bmiHeader . biSizeImage = page - > h * page - > pitch ;
BitmapInfo - > bmiHeader . biXPelsPerMeter = 0 ;
BitmapInfo - > bmiHeader . biYPelsPerMeter = 0 ;
BitmapInfo - > bmiHeader . biClrUsed = page - > format - > palette - > ncolors ;
BitmapInfo - > bmiHeader . biClrImportant = 0 ;
if ( page - > format - > palette ) {
for ( int I = 0 ; I < page - > format - > palette - > ncolors ; I + + ) {
BitmapInfo - > bmiColors [ I ] . rgbRed =
( page - > format - > palette - > colors + I ) - > r ;
BitmapInfo - > bmiColors [ I ] . rgbGreen =
( page - > format - > palette - > colors + I ) - > g ;
BitmapInfo - > bmiColors [ I ] . rgbBlue =
( page - > format - > palette - > colors + I ) - > b ;
}
}
memHDC = CreateCompatibleDC ( printerDC ) ;
if ( memHDC ) {
bitmap = CreateDIBSection ( memHDC , BitmapInfo , DIB_RGB_COLORS ,
( & Pixels ) , NULL , 0 ) ;
if ( bitmap ) {
memcpy ( Pixels , page - > pixels ,
BitmapInfo - > bmiHeader . biSizeImage ) ;
Prev = SelectObject ( memHDC , bitmap ) ;
StretchBlt ( printerDC , 0 , 0 , physW , physH , memHDC , soffsetW , soffsetH , page - > w , page - > h , SRCCOPY ) ;
SelectObject ( memHDC , Prev ) ;
DeleteObject ( bitmap ) ;
}
}
free ( BitmapInfo ) ;
SDL_UnlockSurface ( page ) ;
EndPage ( printerDC ) ;
if ( multipageOutput )
{
multiPageCounter + + ;
outputHandle = printerDC ;
}
else
{
EndDoc ( printerDC ) ;
outputHandle = NULL ;
}
DeleteObject ( bitmap ) ;
DeleteDC ( memHDC ) ;
# else
//LOG_MSG("PRINTER: Direct printing not supported under this OS");
# endif
}
# ifdef C_LIBPNG
else if ( strcasecmp ( output , " png " ) = = 0 )
{
// Find a page that does not exists
2016-10-24 02:17:22 +00:00
findNextName ( ( char * ) " page " , ( char * ) " .png " , & fname [ 0 ] ) ;
2016-02-08 05:01:25 +00:00
png_structp png_ptr ;
png_infop info_ptr ;
png_bytep * row_pointers ;
png_color palette [ 256 ] ;
Bitu i ;
/* Open the actual file */
FILE * fp = fopen ( fname , " wb " ) ;
2016-10-24 02:17:22 +00:00
if ( ! fp )
2016-02-08 05:01:25 +00:00
{
//LOG(LOG_MISC,LOG_ERROR)("PRINTER: Can't open file %s for printer output", fname);
return ;
}
/* First try to alloacte the png structures */
png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING , NULL , NULL , NULL ) ;
if ( ! png_ptr ) return ;
info_ptr = png_create_info_struct ( png_ptr ) ;
if ( ! info_ptr ) {
png_destroy_write_struct ( & png_ptr , ( png_infopp ) NULL ) ;
return ;
}
/* Finalize the initing of png library */
png_init_io ( png_ptr , fp ) ;
png_set_compression_level ( png_ptr , Z_BEST_COMPRESSION ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
/* set other zlib parameters */
png_set_compression_mem_level ( png_ptr , 8 ) ;
png_set_compression_strategy ( png_ptr , Z_DEFAULT_STRATEGY ) ;
png_set_compression_window_bits ( png_ptr , 15 ) ;
png_set_compression_method ( png_ptr , 8 ) ;
png_set_compression_buffer_size ( png_ptr , 8192 ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
png_set_IHDR ( png_ptr , info_ptr , page - > w , page - > h ,
8 , PNG_COLOR_TYPE_PALETTE , PNG_INTERLACE_NONE ,
PNG_COMPRESSION_TYPE_DEFAULT , PNG_FILTER_TYPE_DEFAULT ) ;
2016-10-24 02:17:22 +00:00
for ( i = 0 ; i < 256 ; i + + )
2016-02-08 05:01:25 +00:00
{
palette [ i ] . red = page - > format - > palette - > colors [ i ] . r ;
palette [ i ] . green = page - > format - > palette - > colors [ i ] . g ;
palette [ i ] . blue = page - > format - > palette - > colors [ i ] . b ;
}
png_set_PLTE ( png_ptr , info_ptr , palette , 256 ) ;
png_set_packing ( png_ptr ) ;
SDL_LockSurface ( page ) ;
// Allocate an array of scanline pointers
row_pointers = ( png_bytep * ) malloc ( page - > h * sizeof ( png_bytep ) ) ;
2016-10-24 02:17:22 +00:00
for ( i = 0 ; i < page - > h ; i + + )
2016-02-08 05:01:25 +00:00
row_pointers [ i ] = ( ( Bit8u * ) page - > pixels + ( i * page - > pitch ) ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
// tell the png library what to encode.
png_set_rows ( png_ptr , info_ptr , row_pointers ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
// Write image to file
png_write_png ( png_ptr , info_ptr , 0 , NULL ) ;
SDL_UnlockSurface ( page ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
/*close file*/
fclose ( fp ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
/*Destroy PNG structs*/
png_destroy_write_struct ( & png_ptr , & info_ptr ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
/*clean up dynamically allocated RAM.*/
free ( row_pointers ) ;
}
# endif
else if ( strcasecmp ( output , " colorps " ) = = 0 )
{
FILE * psfile = NULL ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
// Continue postscript file?
if ( outputHandle ! = NULL )
psfile = ( FILE * ) outputHandle ;
// Create new file?
if ( psfile = = NULL )
{
if ( ! multipageOutput )
2016-10-24 02:17:22 +00:00
findNextName ( ( char * ) " page " , ( char * ) " .ps " , & fname [ 0 ] ) ;
2016-02-08 05:01:25 +00:00
else
2016-10-24 02:17:22 +00:00
findNextName ( ( char * ) " doc " , ( char * ) " .ps " , & fname [ 0 ] ) ;
2016-02-08 05:01:25 +00:00
psfile = fopen ( fname , " wb " ) ;
2016-10-24 02:17:22 +00:00
if ( ! psfile )
2016-02-08 05:01:25 +00:00
{
//LOG(LOG_MISC,LOG_ERROR)("PRINTER: Can't open file %s for printer output", fname);
return ;
}
// Print header
fprintf ( psfile , " %%!PS-Adobe-3.0 \n " ) ;
fprintf ( psfile , " %%%%Pages: (atend) \n " ) ;
fprintf ( psfile , " %%%%BoundingBox: 0 0 %i %i \n " , ( Bit16u ) ( defaultPageWidth * 72 ) , ( Bit16u ) ( defaultPageHeight * 72 ) ) ;
fprintf ( psfile , " %%%%Creator: GSport Virtual Printer \n " ) ;
fprintf ( psfile , " %%%%DocumentData: Clean7Bit \n " ) ;
fprintf ( psfile , " %%%%LanguageLevel: 2 \n " ) ;
fprintf ( psfile , " %%%%EndComments \n " ) ;
multiPageCounter = 1 ;
}
fprintf ( psfile , " %%%%Page: %i %i \n " , multiPageCounter , multiPageCounter ) ;
fprintf ( psfile , " %i %i scale \n " , ( Bit16u ) ( defaultPageWidth * 72 ) , ( Bit16u ) ( defaultPageHeight * 72 ) ) ;
fprintf ( psfile , " %i %i 8 [%i 0 0 -%i 0 %i] \n " , page - > w , page - > h , page - > w , page - > h , page - > h ) ;
fprintf ( psfile , " currentfile \n " ) ;
fprintf ( psfile , " /ASCII85Decode filter \n " ) ;
fprintf ( psfile , " /RunLengthDecode filter \n " ) ;
fprintf ( psfile , " false 3 \n " ) ;
fprintf ( psfile , " colorimage \n " ) ;
SDL_LockSurface ( page ) ;
Bit8u * templine ;
templine = ( Bit8u * ) malloc ( page - > w * 3 ) ;
Bit32u x = 0 ;
Bit32u numy = page - > h ;
Bit32u numx = page - > w ;
Bit32u numpix = page - > w * 3 ;
Bit32u pix = 0 ;
Bit32u currDot = 0 ;
Bit32u y = 0 ;
Bit32u plane = 0 ;
Bit8u r , g , b ;
ASCII85BufferPos = ASCII85CurCol = 0 ;
for ( y = 0 ; y < numy ; y + + )
{
currDot = 0 ;
for ( x = 0 ; x < numx ; x + + )
{
SDL_GetRGB ( getxyPixel ( x , y ) , page - > format , & r , & g , & b ) ;
templine [ currDot ] = ~ r ; currDot + + ;
templine [ currDot ] = ~ g ; currDot + + ;
templine [ currDot ] = ~ b ; currDot + + ;
}
// Compress data using RLE
pix = 0 ;
while ( pix < numpix )
{
if ( ( pix < numpix - 2 ) & & ( templine [ pix ] = = templine [ pix + 1 ] ) & & ( templine [ pix ] = = templine [ pix + 2 ] ) )
{
// Found three or more pixels with the same color
Bit8u sameCount = 3 ;
Bit8u col = templine [ pix ] ;
while ( sameCount < 128 & & sameCount + pix < numpix & & col = = templine [ pix + sameCount ] )
sameCount + + ;
fprintASCII85 ( psfile , 257 - sameCount ) ;
fprintASCII85 ( psfile , 255 - col ) ;
// Skip ahead
pix + = sameCount ;
}
else
{
// Find end of heterogenous area
Bit8u diffCount = 1 ;
2016-10-24 02:17:22 +00:00
while ( diffCount < 128 & & diffCount + pix < numpix & &
2016-02-08 05:01:25 +00:00
(
( diffCount + pix < numpix - 2 )
| | ( templine [ pix + diffCount ] ! = templine [ pix + diffCount + 1 ] )
| | ( templine [ pix + diffCount ] ! = templine [ pix + diffCount + 2 ] )
) )
diffCount + + ;
fprintASCII85 ( psfile , diffCount - 1 ) ;
for ( Bit8u i = 0 ; i < diffCount ; i + + )
fprintASCII85 ( psfile , 255 - templine [ pix + + ] ) ;
}
}
}
// Write EOD for RLE and ASCII85
fprintASCII85 ( psfile , 128 ) ;
fprintASCII85 ( psfile , 256 ) ;
SDL_UnlockSurface ( page ) ;
free ( templine ) ;
fprintf ( psfile , " showpage \n " ) ;
if ( multipageOutput )
{
multiPageCounter + + ;
outputHandle = psfile ;
}
else
{
fprintf ( psfile , " %%%%Pages: 1 \n " ) ;
fprintf ( psfile , " %%%%EOF \n " ) ;
fclose ( psfile ) ;
outputHandle = NULL ;
}
}
else if ( strcasecmp ( output , " ps " ) = = 0 )
{
FILE * psfile = NULL ;
printf ( " %d \n " , getPixel ( 2 ) ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
// Continue postscript file?
if ( outputHandle ! = NULL )
psfile = ( FILE * ) outputHandle ;
// Create new file?
if ( psfile = = NULL )
{
if ( ! multipageOutput )
2016-10-24 02:17:22 +00:00
findNextName ( ( char * ) " page " , ( char * ) " .ps " , & fname [ 0 ] ) ;
2016-02-08 05:01:25 +00:00
else
2016-10-24 02:17:22 +00:00
findNextName ( ( char * ) " doc " , ( char * ) " .ps " , & fname [ 0 ] ) ;
2016-02-08 05:01:25 +00:00
psfile = fopen ( fname , " wb " ) ;
2016-10-24 02:17:22 +00:00
if ( ! psfile )
2016-02-08 05:01:25 +00:00
{
//LOG(LOG_MISC,LOG_ERROR)("PRINTER: Can't open file %s for printer output", fname);
return ;
}
// Print header
fprintf ( psfile , " %%!PS-Adobe-3.0 \n " ) ;
fprintf ( psfile , " %%%%Pages: (atend) \n " ) ;
fprintf ( psfile , " %%%%BoundingBox: 0 0 %i %i \n " , ( Bit16u ) ( defaultPageWidth * 72 ) , ( Bit16u ) ( defaultPageHeight * 72 ) ) ;
fprintf ( psfile , " %%%%Creator: GSport Virtual Printer \n " ) ;
fprintf ( psfile , " %%%%DocumentData: Clean7Bit \n " ) ;
fprintf ( psfile , " %%%%LanguageLevel: 2 \n " ) ;
fprintf ( psfile , " %%%%EndComments \n " ) ;
multiPageCounter = 1 ;
}
fprintf ( psfile , " %%%%Page: %i %i \n " , multiPageCounter , multiPageCounter ) ;
fprintf ( psfile , " %i %i scale \n " , ( Bit16u ) ( defaultPageWidth * 72 ) , ( Bit16u ) ( defaultPageHeight * 72 ) ) ;
fprintf ( psfile , " %i %i 8 [%i 0 0 -%i 0 %i] \n " , page - > w , page - > h , page - > w , page - > h , page - > h ) ;
fprintf ( psfile , " currentfile \n " ) ;
fprintf ( psfile , " /ASCII85Decode filter \n " ) ;
fprintf ( psfile , " /RunLengthDecode filter \n " ) ;
fprintf ( psfile , " image \n " ) ;
SDL_LockSurface ( page ) ;
Bit32u pix = 0 ;
Bit32u numpix = page - > h * page - > w ;
ASCII85BufferPos = ASCII85CurCol = 0 ;
while ( pix < numpix )
{
// Compress data using RLE
if ( ( pix < numpix - 2 ) & & ( getPixel ( pix ) = = getPixel ( pix + 1 ) ) & & ( getPixel ( pix ) = = getPixel ( pix + 2 ) ) )
{
// Found three or more pixels with the same color
Bit8u sameCount = 3 ;
Bit8u col = getPixel ( pix ) ;
while ( sameCount < 128 & & sameCount + pix < numpix & & col = = getPixel ( pix + sameCount ) )
sameCount + + ;
fprintASCII85 ( psfile , 257 - sameCount ) ;
fprintASCII85 ( psfile , 255 - col ) ;
// Skip ahead
pix + = sameCount ;
}
else
{
// Find end of heterogenous area
Bit8u diffCount = 1 ;
2016-10-24 02:17:22 +00:00
while ( diffCount < 128 & & diffCount + pix < numpix & &
2016-02-08 05:01:25 +00:00
(
( diffCount + pix < numpix - 2 )
| | ( getPixel ( pix + diffCount ) ! = getPixel ( pix + diffCount + 1 ) )
| | ( getPixel ( pix + diffCount ) ! = getPixel ( pix + diffCount + 2 ) )
) )
diffCount + + ;
fprintASCII85 ( psfile , diffCount - 1 ) ;
for ( Bit8u i = 0 ; i < diffCount ; i + + )
fprintASCII85 ( psfile , 255 - getPixel ( pix + + ) ) ;
}
}
// Write EOD for RLE and ASCII85
fprintASCII85 ( psfile , 128 ) ;
fprintASCII85 ( psfile , 256 ) ;
SDL_UnlockSurface ( page ) ;
fprintf ( psfile , " showpage \n " ) ;
if ( multipageOutput )
{
multiPageCounter + + ;
outputHandle = psfile ;
}
else
{
fprintf ( psfile , " %%%%Pages: 1 \n " ) ;
fprintf ( psfile , " %%%%EOF \n " ) ;
fclose ( psfile ) ;
outputHandle = NULL ;
}
}
else
2016-10-24 02:17:22 +00:00
{
2016-02-08 05:01:25 +00:00
// Find a page that does not exists
2016-10-24 02:17:22 +00:00
findNextName ( ( char * ) " page " , ( char * ) " .bmp " , & fname [ 0 ] ) ;
2016-02-08 05:01:25 +00:00
SDL_SaveBMP ( page , fname ) ;
}
}
void Imagewriter : : fprintASCII85 ( FILE * f , Bit16u b )
{
if ( b ! = 256 )
{
if ( b < 256 )
ASCII85Buffer [ ASCII85BufferPos + + ] = ( Bit8u ) b ;
if ( ASCII85BufferPos = = 4 | | b = = 257 )
{
Bit32u num = ( Bit32u ) ASCII85Buffer [ 0 ] < < 24 | ( Bit32u ) ASCII85Buffer [ 1 ] < < 16 | ( Bit32u ) ASCII85Buffer [ 2 ] < < 8 | ( Bit32u ) ASCII85Buffer [ 3 ] ;
// Deal with special case
if ( num = = 0 & & b ! = 257 )
{
fprintf ( f , " z " ) ;
if ( + + ASCII85CurCol > = 79 )
{
ASCII85CurCol = 0 ;
fprintf ( f , " \n " ) ;
}
}
else
{
char buffer [ 5 ] ;
for ( Bit8s i = 4 ; i > = 0 ; i - - )
{
buffer [ i ] = ( Bit8u ) ( ( Bit32u ) num % ( Bit32u ) 85 ) ;
buffer [ i ] + = 33 ;
num / = ( Bit32u ) 85 ;
}
// Make sure a line never starts with a % (which may be mistaken as start of a comment)
if ( ASCII85CurCol = = 0 & & buffer [ 0 ] = = ' % ' )
fprintf ( f , " " ) ;
2016-10-24 02:17:22 +00:00
2016-02-08 05:01:25 +00:00
for ( int i = 0 ; i < ( ( b ! = 257 ) ? 5 : ASCII85BufferPos + 1 ) ; i + + )
{
fprintf ( f , " %c " , buffer [ i ] ) ;
if ( + + ASCII85CurCol > = 79 )
{
ASCII85CurCol = 0 ;
fprintf ( f , " \n " ) ;
}
}
}
ASCII85BufferPos = 0 ;
}
}
else // Close string
{
// Partial tupel if there are still bytes in the buffer
if ( ASCII85BufferPos > 0 )
{
for ( Bit8u i = ASCII85BufferPos ; i < 4 ; i + + )
ASCII85Buffer [ i ] = 0 ;
fprintASCII85 ( f , 257 ) ;
}
fprintf ( f , " ~ " ) ;
fprintf ( f , " > \n " ) ;
}
}
void Imagewriter : : finishMultipage ( )
{
if ( outputHandle ! = NULL )
{
if ( strcasecmp ( output , " ps " ) = = 0 )
{
FILE * psfile = ( FILE * ) outputHandle ;
fprintf ( psfile , " %%%%Pages: %i \n " , multiPageCounter ) ;
fprintf ( psfile , " %%%%EOF \n " ) ;
fclose ( psfile ) ;
}
if ( strcasecmp ( output , " colorps " ) = = 0 )
{
FILE * psfile = ( FILE * ) outputHandle ;
fprintf ( psfile , " %%%%Pages: %i \n " , multiPageCounter ) ;
fprintf ( psfile , " %%%%EOF \n " ) ;
fclose ( psfile ) ;
}
else if ( strcasecmp ( output , " printer " ) = = 0 )
{
# if defined (WIN32)
EndDoc ( printerDC ) ;
# endif
}
outputHandle = NULL ;
}
}
bool Imagewriter : : isBlank ( ) {
bool blank = true ;
SDL_LockSurface ( page ) ;
for ( Bit16u y = 0 ; y < page - > h ; y + + )
for ( Bit16u x = 0 ; x < page - > w ; x + + )
if ( * ( ( Bit8u * ) page - > pixels + x + ( y * page - > pitch ) ) ! = 0 )
blank = false ;
SDL_UnlockSurface ( page ) ;
return blank ;
}
Bit8u Imagewriter : : getxyPixel ( Bit32u x , Bit32u y ) {
Bit8u * p ;
/* get the X/Y values within the bounds of this surface */
if ( ( unsigned ) x > ( unsigned ) page - > w - 1u )
x = ( x < 0 ) ? 0 : page - > w - 1 ;
if ( ( unsigned ) y > ( unsigned ) page - > h - 1u )
y = ( y < 0 ) ? 0 : page - > h - 1 ;
/* Set a pointer to the exact location in memory of the pixel
in question : */
p = ( Bit8u * ) ( ( ( Bit8u * ) page - > pixels ) + /* Start at top of RAM */
( y * page - > pitch ) + /* Go down Y lines */
x ) ; /* Go in X pixels */
/* Return the correctly-sized piece of data containing the
* pixel ' s value ( an 8 - bit palette value , or a 16 - , 24 - or 32 - bit
* RGB value ) */
return ( * p ) ;
}
Bit8u Imagewriter : : getPixel ( Bit32u num ) {
Bit32u pixel = * ( ( Bit8u * ) page - > pixels + ( num % page - > w ) + ( ( num / page - > w ) * page - > pitch ) ) ;
return * ( ( Bit8u * ) page - > pixels + ( num % page - > w ) + ( ( num / page - > w ) * page - > pitch ) ) ;
}
# endif // HAVE_SDL
2016-10-24 02:17:22 +00:00
//Interfaces to C code
2016-02-08 05:01:25 +00:00
extern " C " void imagewriter_init ( int pdpi , int ppaper , int banner , char * poutput , bool mpage )
{
if ( defaultImagewriter ! = NULL ) return ; //if Imagewriter on this port is initialized, reuse it
defaultImagewriter = new Imagewriter ( pdpi , ppaper , banner , poutput , mpage ) ;
}
extern " C " void imagewriter_loop ( Bit8u pchar )
{
if ( defaultImagewriter = = NULL ) return ;
defaultImagewriter - > printChar ( pchar ) ;
}
extern " C " void imagewriter_close ( )
{
delete defaultImagewriter ;
defaultImagewriter = NULL ;
}
extern " C " void imagewriter_feed ( )
{
if ( defaultImagewriter = = NULL ) return ;
defaultImagewriter - > formFeed ( ) ;
}