gsplus/src/imagewriter.cpp

2243 lines
59 KiB
C++
Raw Normal View History

2016-02-08 05:01:25 +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.\nAll printer output will be saved as bitmap files.\nTo 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.\nAll 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();
}