/* Treiber fr Canon BJ200 Drucker fr Atari DVI-Treiber (Version 2.30): Fr Quer- und Hochkant! - DVI-Druckertreiber fr Canon BJ200 Drucker. Der Sourcecode entspricht (immer noch) gr”átenteils der EPSON-Stylus Version. - WICHTIG: Dieser Treiber erwartet das der Canon BJ in der ____BJ-Emulation____ betrieben wird! Fr die EPSON-Emulation kann man den EPSON LQ800 Treiber benutzen. Letzterer bietet nur keine echten 360*360 dpi Aufl”sung (Eine Nadel wird in der EPSON-Emulation immer durch zwei Dsen emuliert) und auch keinen 48 Dsen Druck :-(. - Bemerkung: Ich habe diesen Treiber nur teilweise getestet! (Nicht nur) Deshalb: BENUTZUNG AUF EIGENE GEFAHR. ICH šBERNEHME KEINE VERANTWORTUNG FšR EVENTUELLE SCHŽDEN, DIE DURCH DIE BENUTZUNG DIESES TREIBERS VERURSACHT WURDEN. ICH BEHAUPTE AUCH NICHT, DASS DIESES PROGRAMM IRGENDEINEN ZWECK ERFšLLT. WER HIERMIT NICHT EINVERSTANDEN IST, DARF DIESEN TREIBER NICHT BENUTZEN!! Verbesserungsvorschl„ge sind willkommen: Derzeitige Adresse: Dietmar Herrend”rfer, Department of Physics, Trinity College, Dublin 2 Ireland email: dhrrndrf@tcd.ie - Version 1.2 ½ 1995, Dietmar Herrend”rfer. ½ Markus Pristovsek, fr die Teile, die aus anderen Treibern wurden. Bem.: Tabulatorabstand auf 4 Zeichen setzen. */ /* Weitere Bemerkung: Der Treiber wurde von mir (Markus Pristovsek) in neue Form eingepažt. Theoretisch sollte er funktionieren, kann jedoch von mir mangels Drucker nicht getestet werden. */ #include #include #include #include #include "treiber.h" /*** Ein paar Parameter: ***/ /*++ Seitenabmessungen - alle Pixelgr”áen bezogen auf 360dpi*360dpi: ++*/ #define TOP 43L /* Oberer Rand in Pixeln. */ #define BOTTOM 90L /* Unterer Rand in Pixeln. */ #define LEFT 47L /* Linker Rand in Pixeln. */ #define RIGHT 49L /* Rechter Rand in Pixel. */ #define A4WIDTH 2976L /* A4 Papierbreite in Pixeln. */ #define A4HEIGHT 4209L /* A4 Papierh”he in Pixeln. */ #define WIDTH (A4WIDTH-LEFT-RIGHT) /* max. Breite einer Grafikseite */ #define HEIGHT (A4HEIGHT-TOP-BOTTOM) /* max. Bitmap H”he */ #define BUF_SIZE WIDTH*6L+6L+256L /* Gr”áe des ben”tigten Zeilenpuffers. */ /*** Neudefinierte Typen: ***/ typedef struct { UBYTE id; /* Druckmodusnummer. */ WORD h_dpi; /* Horizontale Aufl”sung. */ WORD v_dpi; /* Vertikale Aufl”sung. */ WORD bytes; /* Bytes pro Druckkopf-Spalte. */ } MODI; /*** Lokale Variablen: ***/ /*++ Drucker Steuercodes und „hnliches Druckerspezifisches: ++*/ static UBYTE init[] = "\033[K\002\000\000\045"/* Reset & 1/360 dpi spacing. */ "\033[\\\004\000\000\000\150\001"; static UBYTE h_step[] = "\033d__"; /* Horizontale Druckkopfbewegung. */ static UBYTE v_step[] = "\034CJ\004_\015"; /* Zeilenvorschub in 360 dpi. */ static UBYTE v_skip[] = "\034CJ\000\200\015"; /* 256/360 Inch Zeilenvorschub. */ static UBYTE g_print[] = "\033[g"; /* Bitmap-Graphik drucken. */ static MODI cbj_mode[]= {{ 0, 60, 60, 1}, /* Canon BJ200 Druckermodi: */ { 1, 120, 60, 1}, { 2, 120, 60, 1}, { 3, 240, 60, 1}, { 8, 60, 180, 3}, { 9, 120, 180, 3}, { 11, 180, 180, 3}, { 12, 360, 180, 3}, { 13, 120, 360, 6}, { 14, 180, 360, 6}, { 15, 240, 360, 6}, { 16, 360, 360, 6}, { 0, 0, 0, 0}}; /* Markiert das Listenende !*/ /****************************************************************************************/ /*** Globale Variablen: ***/ LONG max_puffer_laenge = BUF_SIZE; /* Obergrenze der Gr”áe des Druckpuffers. */ /*** Lokale Variable: ***/ static UBYTE prt_buffer[BUF_SIZE]; /* Zwischenspeicher fr eine Zeile */ /* šberspringt "Rows" leerzeilen */ void skip_rows( WORD out_channel, LONG rows ) { v_step[4] = (UBYTE)255; /* Maximal 255 Zeilen pro Vorschub: */ while( rows>255L ) { print_block( 6L, v_step, out_channel ); rows -= 255L; } v_step[4] = (UBYTE)rows; /* und den Rest */ print_block( 6L, v_skip, out_channel ); } /* 7.10.95 */ /****************************************************************************************/ /* Ausdruck einer Seite als Landscape */ WORD drucke_quer(UBYTE *bitmap_ptr, LONG h_offset, LONG hsize_p, LONG vsize_p, LONG h_dpi, LONG v_dpi, WORD out_channel, WORD flag ) { UBYTE *bit_ptr, *prt_ptr; /* Pointer in die Bitmap und in den Druckpuffer. */ MODI *mode, *tmp_mode; /* Zeiger auf die Modus-Tabelle. */ LONG hdpi_diff, vdpi_diff; /* Zum Festlegen der Aufl”sung. */ register LONG tmp; /* Puffer fr alles m”gliche. */ register LONG hsize_b, hsize_m; /* Druckseitenbreite in Bytes, Bitmapbreite in Bytes. */ register LONG h_pos, rows_to_skip; /* Derzeitige Druck-Zeile, Anzahl leerer Zeilen. */ LONG l_margin, right, left; /* Linker Rand, Zeilenr„nder. */ LONG prt_columns, prt_bytes; /* Druckspalten pro Zeile, Spaltenh”he in Bytes. */ int active; /* Ein flag. */ (void)h_offset; /* ignorieren */ /*** Initialisierung: ***/ /*++ Gewnschte Aufl”sung an vorhandene Aufl”sungen anpassen: ++*/ /*++ Bem.: Die optimale Anpassung der vertikalen Aufl”sung geht vor. ++*/ tmp_mode = cbj_mode; hdpi_diff = vdpi_diff = LONG_MAX; /* Zun„chst maximale Abweichung. */ do { if( labs( tmp_mode->v_dpi - h_dpi )v_dpi - h_dpi); vdpi_diff = labs(tmp_mode->h_dpi - v_dpi); mode = tmp_mode; } if( labs( tmp_mode->v_dpi - h_dpi )==hdpi_diff ) { if( labs( tmp_mode->h_dpi - v_dpi )v_dpi - v_dpi); } } } while( (++tmp_mode)->bytes ); /* bytes == 0 => Ende. */ h_dpi = mode->v_dpi; /* Aufl”sung ggf. ab„ndern. */ v_dpi = mode->h_dpi; prt_bytes = mode->bytes; /*++ Diverse Variablen setzen: ++*/ strcpy(prt_buffer, g_print); /* Bitmap-Graphik Steuerkode kopieren */ hsize_b = (hsize_p < (HEIGHT*h_dpi)/360L) ? (hsize_p + 7L) >> 3 : (HEIGHT*h_dpi)/2880L; hsize_m = ((hsize_p + 15L) >> 4) << 1; /* -> die 'Bitmap' ist eine gerade Anzahl von Bytes hoch. */ /* Nicht druckbare R„nder berspringen. */ if( flag&1 ) { bitmap_ptr += (tmp = (((TOP*v_dpi)/360L + 7L) >> 3)) - hsize_m*((LEFT*h_dpi)/360L); hsize_b -= tmp; /* vertikale Gr”áe entsprechend korrigieren. */ } /* Breite der Seite berprfen: */ if( vsize_p>(tmp = (WIDTH*v_dpi)/360L) ) vsize_p = tmp; /*++ Testen ob die Seite leer ist: ++*/ rows_to_skip = 0; /* Zun„chst keine leeren Zeilen. */ for( l_margin=0; ist_next_leer( bitmap_ptr + l_margin, hsize_m, vsize_p) && l_margin < hsize_b; l_margin++ ) ; /* Leere Druckzeile ? */ if( l_margin==hsize_b ) { rows_to_skip = hsize_m; h_pos = hsize_m; } /*** Begin des Druckvorgangs: ***/ /*++ Reset: ++*/ if (flag & 1) print_block( 16L, init, out_channel ); h_pos = 0; /*++ Bytes im Puffer an den Drucker ausgeben: ++*/ active = TRUE; while( active && flag&2 ) { /*++ Leerzeilen gesondert abarbeiten: ++*/ while( h_pos+rows_to_skip < hsize_m && ist_next_leer( bitmap_ptr + rows_to_skip, hsize_b, vsize_p) ) ++rows_to_skip; h_pos += rows_to_skip; if( h_pos > hsize_b ) rows_to_skip = hsize_b - (h_pos - rows_to_skip); /* Ist diese Seite ist schon fertig? */ if( TRUE == (active = (h_pos < hsize_b)) ) { /* Leerzeilen zu berspringen ? */ if( rows_to_skip>0L ) skip_rows( out_channel, (rows_to_skip*2880L)/h_dpi ); /*++ R„nder einstellen: ++*/ for( right=0; right < vsize_p - 1L && ist_leerzeile(bitmap_ptr + right*hsize_m, prt_bytes); right++ ) ; --right; for( left = vsize_p - 1L; left > right && ist_leerzeile(bitmap_ptr + left*hsize_m, prt_bytes); left-- ) ; ++left; /* Linker Rand ? */ if( left>0 ) { left = (left/3)*3; /* Da in (ganzen) 120 dpi Schritten. */ tmp = ((vsize_p - left)*120)/v_dpi; h_step[2] = (UBYTE)tmp; h_step[3] = (UBYTE)(tmp >> 8); print_block(4L, h_step, out_channel); } /*++ Daten drucken: ++*/ prt_ptr = prt_buffer + 6; for( prt_columns=left-right; prt_columns!=0; prt_columns-- ) { bit_ptr = bitmap_ptr+(prt_columns)*hsize_m; for( tmp=1; tmp<=prt_bytes; tmp++ ) *prt_ptr++ = *bit_ptr++; } prt_columns = left - right; prt_buffer[3] = (UBYTE)(prt_columns*prt_bytes + 1L); prt_buffer[4] = (UBYTE)((prt_columns*prt_bytes + 1L) >> 8); prt_buffer[5] = (UBYTE)mode->id; /* šberagt Zeile unteren Rand ? */ if( h_pos+prt_bytes>hsize_b ) { register WORD bit, byte, and_it; /* => Abschneiden. */ bit = (WORD)(h_pos + prt_bytes - hsize_b); byte = bit >> 3; and_it = (0x00FF << (bit & 7)); for( rows_to_skip=0L; rows_to_skip byte ) prt_buffer[6 + rows_to_skip] = 0; } } print_block( 6L+prt_columns*prt_bytes, prt_buffer, out_channel ); rows_to_skip = prt_bytes; bitmap_ptr += prt_bytes; } } /*** Seitenende bearbeiten: ***/ if (flag & 4) print_block(1L, "\014\007", out_channel); /*** Das war es: ***/ return 0; } /* Žnderungen 7.10.95, M. Pristovsek */ /****************************************************************************************/ /*** Druckpuffer ausdrucken (fr Querdruck wird drucke_quer aufgerufen): **** **** > bitmap_ptr (UBYTE *) ; Puffer mit den zu druckenden Bytes. **** > v_offset (LONG) ; vertikale (horizontale) Startposition in der Bitmap. **** > hsize_p (LONG) ; Breite der Bitmap in Pixeln. **** > vsize_p (LONG) ; H”he der Bitmap in Pixeln. **** > h_dpi (LONG) ; gewnschte horizontale Aufl”sung. **** > v_dpi (LONG) ; gewnschte vertikale Aufl”sung. **** > out_channel (WORD) ; Ausgabekanal (siehe TOS: 'Fopen') **** > flag (WORD) ; Bitfeld: 1=Header, 2=Daten, 4=Ende **** > quer (WORD) ; Querdruck **** > opt (UBYTE *) ; String mit zus. Optionen (max. 16 Bytes) ***/ WORD drucke( UBYTE *bitmap_ptr, LONG v_offset, LONG hsize_p, LONG vsize_p, LONG h_dpi, LONG v_dpi, WORD out_channel, WORD flag, WORD quer, UBYTE *opt ) { /*** Lokale Variablen: ***/ MODI *mode, *tmp_mode; /* Zeiger auf die Modus-Tabelle. */ LONG hdpi_diff, vdpi_diff; /* Zum Festlegen der Aufl”sung. */ register LONG tmp; /* Puffer fr alles m”gliche. */ register LONG hsize_b, hsize_m; /* Druckseitenbreite in Bytes, Bitmapbreite in Bytes. */ register LONG v_pos, rows_to_skip; /* Derzeitige Druck-Zeile, Anzahl leerer Zeilen. */ LONG l_margin, right, left; /* Linker Rand, Zeilenr„nder. */ LONG prt_columns, prt_bits; /* Druckspalten pro Zeile, Spaltenh”he in Bits. */ int active; /* Ein flag. */ (void)opt; /* ignorieren */ if( quer ) return drucke_quer( bitmap_ptr, v_offset, hsize_p, vsize_p, h_dpi, v_dpi, out_channel, flag ); /*** Initialisierung: ***/ /*++ Gewnschte Aufl”sung an vorhandene Aufl”sungen anpassen: ++*/ /*++ Bem.: Die optimale Anpassung der horizontalen Aufl”sung geht vor. ++*/ tmp_mode = cbj_mode; hdpi_diff = vdpi_diff = LONG_MAX; /* Zun„chst maximale Abweichung. */ do { if( labs( tmp_mode->h_dpi - h_dpi )h_dpi - h_dpi); vdpi_diff = labs(tmp_mode->v_dpi - v_dpi); mode = tmp_mode; } if( labs( tmp_mode->h_dpi - h_dpi )==hdpi_diff ) { if( labs( tmp_mode->v_dpi - v_dpi )v_dpi - v_dpi); } } } while( (++tmp_mode)->bytes ); /* bytes == 0 => Ende. */ h_dpi = mode->h_dpi; /* Aufl”sung ggf. ab„ndern. */ v_dpi = mode->v_dpi; prt_bits = mode->bytes << 3; /*++ Diverse Variablen setzen: ++*/ strcpy(prt_buffer, g_print); /* Bitmap-Graphik Steuerkode kopieren */ hsize_b = (hsize_p < (WIDTH*h_dpi)/360L) ? (hsize_p + 7L) >> 3 : (WIDTH*h_dpi)/2880L; hsize_m = ((hsize_p + 15L) >> 4) << 1; /* -> die 'Bitmap' ist eine gerade Anzahl von Bytes weit. */ if( flag&1 ) { /* Nicht druckbare R„nder berspringen. */ bitmap_ptr += hsize_m*(tmp = (TOP*v_dpi)/360L) + (((LEFT*h_dpi)/360L + 7L) >> 3); vsize_p -= tmp; /* vertikale Gr”áe entsprechend korrigieren. */ } v_pos = v_offset; vsize_p += v_offset; /* H”he der Seite berprfen: */ if( vsize_p > (tmp = (HEIGHT*v_dpi)/360L) ) vsize_p = tmp; vsize_p -= v_offset; --vsize_p; /*++ Testen ob die Seite leer ist: ++*/ for (l_margin = 0; ist_next_leer(bitmap_ptr + l_margin, hsize_m, vsize_p) && l_margin < hsize_b; l_margin++); rows_to_skip = 0; /* Zun„chst keine leeren Zeilen. */ if( l_margin == hsize_b ) { /* Leere Druckseite ? */ rows_to_skip = vsize_p - v_pos; /* So tun, als ob das Ende der Seite erreicht ist. */ v_pos = vsize_p; } /*** Begin des Druckvorgangs: ***/ /*++ Reset: ++*/ if( flag&1 ) print_block(16L, init, out_channel); /*++ Bytes im Puffer an den Drucker ausgeben: ++*/ active = TRUE; while( active && v_pos l_margin && ist_next_leer(bitmap_ptr + right, hsize_m, prt_bits); right-- ) ; ++right; for( left=l_margin; ist_next_leer(bitmap_ptr + left, hsize_m, prt_bits) && left < right; left++ ) ; /* Linker Rand ? */ if( left>0 ) { left = (left/3)*3; /* Da in (ganzen) 120 dpi Schritten. */ tmp = ((left << 3)*120)/h_dpi; h_step[2] = (UBYTE)tmp; h_step[3] = (UBYTE)(tmp >> 8); print_block( 4L, h_step, out_channel ); } prt_columns = right - left; /*++ Daten drucken: ++*/ block_it( prt_buffer+6L, bitmap_ptr+left, prt_columns, hsize_m, mode->bytes ); prt_buffer[3] = (UBYTE)(prt_columns*prt_bits + 1L); prt_buffer[4] = (UBYTE)((prt_columns*prt_bits + 1L) >> 8); prt_buffer[5] = (UBYTE)mode->id; /* šberagt Zeile unteren Rand ? */ if (v_pos + prt_bits > vsize_p) { register WORD bit, byte, and_it; /* => Abschneiden. */ bit = (WORD)(v_pos + prt_bits - vsize_p); byte = bit >> 3; and_it = (0x00FF << (bit & 7)); for( rows_to_skip = 0L; rows_to_skip < prt_columns*prt_bits; rows_to_skip++ ) { if( rows_to_skip%mode->bytes == byte ) prt_buffer[6L + rows_to_skip] &= and_it; else if( rows_to_skip%mode->bytes > byte ) prt_buffer[6 + rows_to_skip] = 0; } print_block( 6L+prt_columns*prt_bits, prt_buffer, out_channel); rows_to_skip = bit; active = FALSE; } else { rows_to_skip = prt_bits; print_block( 6L+prt_columns*prt_bits, prt_buffer, out_channel ); bitmap_ptr += hsize_m * prt_bits; v_pos += rows_to_skip; } } } /*** Seitenende bearbeiten: ***/ /* Seite beenden ? */ if( flag&4 ) print_block( 1L, "\014\007", out_channel ); else { /* Evt. Rest ausgeben: Nur noch Leerzeilen */ /* Leerzeilen zu berspringen ? */ if( rows_to_skip != 0L ) skip_rows( out_channel, (rows_to_skip*360L)/v_dpi ); } /*** Das war es: ***/ flush_block( out_channel ); return 0; /* Fehler sind nicht vorgesehen. */ } /* Žnderungen 7.10.95, M. Pristovsek */