/*


 KNOW-HOW.PRINT 



This text contain complete description of KNOW_HOW.PRINT 5.0x, the
product in the 5th version of library. It provide the following features:
    a) Creation of the graphics "page" of any size on hard disk.
    b) Data exchange between screen, "page" and PCX file. Color <---> B&W PCX
       conversion.
    c) Scrolling of the "page" in clip area on screen with any deformation.
    d) Direct drawing on the "page" (pixel-by-pixel).
    e) Print on EPSON or LJ-compatible printers with any deformation.
    f) Cut and paste operations with images.


 FILES 


 Files GLOBAL, COLOR and so on - see description of KNOW-HOW.INTERFACE
 Files PIXEL.H and PIXEL.CPP defines array of patterns for COLOR to
	B&W conversion and so on:
extern char pattern[][8];
	The put_pixel() functions works as pattern and random brushes.
extern void put_pixel(int x, int y, int pat, int bak = global_i[7],
    int attr = global_i[6]);
extern void put_pixel_error_prop(int x, int y, int weight, int pat,
    int bak = global_i[7], int attr = global_i[6]);
	Put your attention to the usage of global_i[6 and 7] elements (see
	description of KNOW-HOW.INTERFACE).

 File PATTERNS.CPP assign patterns (8x8). User could add his own
	patterns.
 File IMAGE_P.H and define image as a structure:

struct imageType
    {
    int xmax, ymax;
    unsigned char data[];
    };
typedef imageType* imageP;
      Now we could trace this objects of structure, change fields of structure
    and so on.

 Files IMAGEBUF.H and IMAGEBUF.CPP are usefull for COLOR->B&W
	conversions.
	The b&w() function returns BW pixel, BLACK of WHITE (1), depending on
	pattern for color. Defined in GBUF.H
extern bw_pix(int color, int x, int y);
       The ImageBuffer structure is used for realization of get_pixel() for
       image (not screen).
struct ImageBuffer
    {
    uchar pixels[8];
    loc coord;
    ImageBuffer() { coord.Y = -1; }
    uchar image_get_pixel(imageP image, int byte, int vert_shift);
    };

 Files IMAGE.H and IMAGE.CPP contains the simple toolkit for working
	with images. Images are in the (Borland) getimage() formate. We use
	the postulate, that color pictures have 4 planes, and BW pictures -
	one.

enum { BW, COLOR }; Enumeration define image type: 16 color or monochrome.

	Read pixel color from image.
extern int image_get_pixel(imageP image, loc pos, int bitpx = 1,
			   int nplanes = 4);
	Put pixel to the image, changing all planes, if necessary.
extern void image_put_pixel(imageP image, loc pos, int col,
			    int bitpx = 1, int nplanes = 4);

	Shows part of image on screen with deformation.
	Arguments: src - rectangle in source image, dest- left-top coordinates
	       on screen, ... , comp_s and comp_d - deformation of source
	       and destination, it corresponds to divx, divy, multx, multy,
	       flag == 1 - use image_get_pixel - for pixel - to - pixel
	       (not byte - to byte) output, trans contains directive to
	       use one of the colors as transparent (do not show it).
	       Default value is 16 (no transparent color).
extern void image_screen(imageP image, rect src, loc dest, int bitpx = 1,
		 int nplanes = 4, loc comp_s = loc(1, 1),
		 loc comp_d = loc(1, 1), int flag = 0);

	Copies part of screen to the part of image, no deformation.
extern void screen_image(imageP image, rect scr, loc dest);

 Files PCXSTRM.H and PCXSTRM.CPP work with PCX file as with stream,
	to speed up the calculations.

 Files PCX.H and PCX.CPP work with screen output of PCX. It define
	PCX file header as:

struct pcxheader {
     char       manuf;           // Always = 10 for Paintbrush
     char       hard;            // Version info
     char       encod;           // Coding ( = 1)
     char       bitpx;           // bit per pixel
     int        x1;              // Picture size (inclusive)
     int        y1;
     int        x2;
     int        y2;
     int        hres;            // horiz. resolution of display
     int        vres;            // vert. resolution of display
     char       clrma[48];       // Palette
     char       vmode;           // Ignored
     char       nplanes;         // Num. of planes (rel. 2.5 = 0)
     int        bplin;           // Bytes per line
     int        palinfo;         // Palette info (1=col.,2 = grey)
     int        shres;           // Scanner resolution
     int        svres;           //
     char       xtra[54];        // Filter
 };
	and some functions for manipulations with file in PCX formate:

void put_pcx_header(FILE* f, pcxheader* p, loc pos, int pal = 1,
    int planes = N_PLANES);
int get_pcx_header(pcxstream* s, pcxheader* p_h);
int get_pcx_header(FILE* file, pcxheader* p_h);
int get_pcx_header(char* name, pcxheader* p_h);

	The "pal" flag below could be set to 0 for speed, but resulting
	files will be compatible only with KNOW-HOW functions.
	Always 1 bit / pixel and 4 planes 16-color images
void pcx_scr_file(rect coord, char* name, int pal = 0);
int pcx_file_scr(char* name, loc pos, int* cells = NULL, int mode = COPY_PUT);

 Files IC_PART.H and IC_PART.CPP contains cut-and-paste functions.
 Files B&W.H and B&W.CPP process COLOR <----> B&W PCX convertion.

int pcx_bw_to_col(char* src_name, char* dest_name);
int pcx_col_to_bw(char* src_name, char* dest_name);

 Files MOVE.H and MOVE.CPP scroll the image.
 Files GBUF.H and GBUF.CPP realize graphical "page" on the disk.
	Graphics buffer is a file, which consists of the number of "bounds".
	Each "bound" is a part of virtual graphics page, with the same width,
	and relatively low height. We can load "bound" with given number to
	memory, change it, show it on screen, swap to disk buffer. Format of
	bound is the same as in image (int, int, bitmap).
	Do not use buffer < than screen.

   If you do not use interface library of KNOW-HOW, some files are
       not necessary, as event.lib, and other. It is possible to exclude
       them from project. In this case you should edit colors.cpp file,
       and remove some functions: pColorSet, init_Know_How and so on.
       You need only pScreenSet structure, declared in colors.h.

#define BOUND_SIZE 12500/2     // size of bound, bytes

enum { LEFT, UP, RIGHT, DN };  // Scroll directions
BGI function is not correct, so we need:
extern int image_size(int width, int heigth, int bitpx, int nplanes);

class GrafBuffer
    {
    public:
	int loaded;            // is the buffer ready?
	loc buf_dim;           // buffer dimentions, pixels
	loc bound_size;        // dimentions of bounds, bound_size.X == buf_dim.X
	rect screen_area;      // screen work area (l, t, r, b)
	rect screen_position;  // position of screen in buffer
	FILE* buffer;          // swap file
	char* file_name;       // swap file
	imageP image;          // image for bound
	int nplanes;           // number of planes
	int bitpx;             // bit per pixel in plane
	int change_palette;    // use or not the palette when loading or saving PCX
	int transparent;       // What color show as transparent
	int mode;              // COPY_PUT ...
    public:
	GrafBuffer(loc dim, char* swapName,
		   rect screen_area = rect(0, 0, getmaxx(), getmaxy()),
		   int bpx = 1, int np = 4);
	~GrafBuffer() { fclose(buffer); delete image; unlink(file_name);
			delete file_name; }

	long imagesize(); // if image > 64K, BGI function returns error
	int imagesize(int x, int y);

	void set_screen_area(rect a) { screen_area = a; }
	void set_screen_position(rect a) { screen_position = a; }
	int b_open();     // open swap file (created by constructor)
	void b_close();    // close swap file

	void clear();      // fills buffer file with '0'
	loc get_dim() { return buf_dim; }
	rect get_screen_pos() { return screen_position; }

	void set_mode(int m) { mode = m; }
	void set_trans(int t) { transparent = t; }

	imageP get_bound(int number);
	void put_bound(int number);
	void get_BW(int number);  // get bound and keep it as BW

	void bound_screen(int number,      // put image from bound to screen src - in image, dest - on screen
		 loc comp_s = loc(1, 1),   // divx, divy, multx, multy
		 loc comp_d = loc(1, 1));  // rects are the outlines

	void screen_bound(int number);  // load bound from disk to memory, update from screen, put back

	void screen_buffer();       // swap screen to buffer
	void buffer_screen(loc comp_s = loc(1, 1),   // from buffer to screen
			   loc comp_d = loc(1, 1));
	void buffer_screen(rect temp,
			   loc comp_s = loc(1, 1),   // from buffer to screen
			   loc comp_d = loc(1, 1));


	void buffer_disk(rect src, char* name);   // cut and paste

	void scroll(int shift, int direction, int show = 1);    // scrolling

	void pcx_buffer_file(rect src, char* name); // From buf to file
    friend int pcx_file_buffer(GrafBuffer* buf, loc pos, char* name,
			       int col = 16);

// Virtual BGI support
    friend void dither_BW(int** threshold, rect coord, loc dim,
			  GrafBuffer* buf);
    friend void bar(GrafBuffer* buf, rect coord);    // bar in buffer
    };

 Files PRINT.H and PRINT.CPP contains printer support code. Attention!
	WINDOWS use files with the same name: PRINT.H.
	PrintManager is the class, which may send buffer of GrafBuffer class
	to printers of different types. The algorithm is: load "bound", print
	it, load next...

#define MAXPAGE 2000    // maximum page width

enum { EPSON9 = 1, EPSON24, LASERJET_II };             // Printer type
enum { DD, QD, LJ_100, LJ_150 };                       // Print density
enum { PAPER_OFF = '8', PAPER_ON = '9' };              // Paper-end sensor

class PrintManager
    {
    protected:
	int printer_type;      // see enum of printer types
	int density;           // double or quadruple
	int pass;              // how much time to repeate each pass
	int mx, my, dx, dy;    // print time deformation
	int left;              // left indent
	int paper;             // paper-out sensor disable
	int parity;            // minimal number of lines in bound (* 4 for color)
    public:
	PrintManager(int t, int d, int p = 1, rect cmp = rect(1, 1, 1, 1),
	    int lt = 0, int ppr = PAPER_ON, int pa = 1)
	    { printer_type = t; density = d; pass = p; mx = cmp.origin.X;
	      my = cmp.origin.Y; dx = cmp.corner.X; dy = cmp.corner.Y;
	      left = lt; paper = ppr; parity = pa; }

	void set_type(int t) { printer_type = t; }
	void set_density(int d) { density = d; }
	void set_pass(int p) { pass = p; }
	void set_comp(int multx, int multy, int divx, int divy)
	    { mx = multx; my = multy; dx = divx; dy = divy; }
	void set_left(int l) { left = l; }
	void set_paper(int p) {paper = p; }

	void init_printer(int size, int sh);    // set current resolution and so on
	void draw_string(char* str);            // draws graphic string
	void draw_image(imageP image);          // print image
	void draw_buffer(GrafBuffer* buf);      // prints buffer

If page if very big, we print it on few pages
	void draw_pages(GrafBuffer* buf, char* work_name,
			int maxpage = MAXPAGE);
Print using page of maxpage width
	void print_part(rect src, GrafBuffer* buf, char* work_name);
    friend class GrafBuffer;
    };

..........................................................................
Example:
void main()
    {
Init Borland's graphics.
    int gdriver = DETECT;
    int gmode;
    initgraph(&gdriver, &gmode, "");
// Create Print manager and graphical buffer
    PrintManager p(EPSON9, DD, 2, rect(1, 1, 1, 1), 0, PAPER_ON, 6);
    GrafBuffer* g = new GrafBuffer(loc(750, 590), "work.buf",
				   rect(0, 0, 500, getmaxy() - 1));
// Create and clear page
    g->b_open();
    g->clear();
// Load PCX file and show it
    pcx_file_buffer(g, loc(0, 0), "about.pcy");
    g->buffer_screen();
// Print
    p.draw_buffer(g);
    p.draw_pages(g, "work1.buf", 320);
// Deformation
    p.set_comp(1, 2, 2, 1);
    p.draw_buffer(g);

    p.set_comp(1, 1, 2, 2);
    p.draw_buffer(g);
// Print part of the image
    p.print_part(rect(64, 50, 239, 200), g, "work1.buf");

    g->b_close();
    delete g;
    closegraph();
    }


