424
423
static gx_color_index
425
424
lxm3200_map_rgb_color(gx_device *dev, const gx_color_value cv[])
428
gx_color_value r, g, b;
430
gx_color_value tmpcv[3];
432
r = cv[0]; g = cv[1]; b = cv[2];
433
/* In case R, G and B values are equal, ghostscript
434
* prescribes that the color value must be turned
435
* into a gray shade. In our case this means either
446
/* Calculate CMY values from RGB. This is *overly*
447
* simple, but it's enough to print something.
453
/* Now encode the calculated color into the internal
454
* format. This means simply to turn on or off the
455
* bits representing each color depending on the value
456
* of the appropriate CMY component.
457
* Note that we are not doing black separation or any
458
* other fancy stuff: this is spartane code just to
459
* make the printer work.
462
if(y > HALFTONE)col |= YELLOW;
464
switch(((lxm_device *)dev)->rendermode)
467
if(c > HALFTONE)col |= CYAN;
468
if(m > HALFTONE)col |= MAGENTA;
475
if(c > ONETHIRD)col |= LIGHTCYAN;
480
if(m > ONETHIRD)col |= LIGHTMAGENTA;
484
tmpcv[0] = r; tmpcv[1] = g; tmpcv[2] = b;
485
col = gdev_prn_map_rgb_color(dev, tmpcv);
427
gx_color_value r, g, b;
429
gx_color_value tmpcv[3];
431
r = cv[0]; g = cv[1]; b = cv[2];
432
/* In case R, G and B values are equal, ghostscript
433
* prescribes that the color value must be turned
434
* into a gray shade. In our case this means either
445
/* Calculate CMY values from RGB. This is *overly*
446
* simple, but it's enough to print something.
452
/* Now encode the calculated color into the internal
453
* format. This means simply to turn on or off the
454
* bits representing each color depending on the value
455
* of the appropriate CMY component.
456
* Note that we are not doing black separation or any
457
* other fancy stuff: this is spartane code just to
458
* make the printer work.
461
if(y > HALFTONE)col |= YELLOW;
463
switch(((lxm_device *)dev)->rendermode)
466
if(c > HALFTONE)col |= CYAN;
467
if(m > HALFTONE)col |= MAGENTA;
474
if(c > ONETHIRD)col |= LIGHTCYAN;
479
if(m > ONETHIRD)col |= LIGHTMAGENTA;
483
tmpcv[0] = r; tmpcv[1] = g; tmpcv[2] = b;
484
col = gdev_prn_map_rgb_color(dev, tmpcv);
492
491
/* Function called by ghostscript to map the
493
492
* internal representation of a color to a
497
496
lxm3200_map_color_rgb(gx_device *dev, gx_color_index color,
498
gx_color_value prgb[3])
497
gx_color_value prgb[3])
518
/* Calculate back CMY components from the internal
519
* representation of the color
525
switch(((lxm_device *)dev)->rendermode)
528
color &= (CYAN|MAGENTA|YELLOW);
529
if(color & CYAN)c = 2;
530
if(color & MAGENTA)m = 2;
531
if(color & YELLOW)y = 2;
536
color &= (CYAN|MAGENTA|YELLOW|LIGHTCYAN|LIGHTMAGENTA);
537
if(color & LIGHTCYAN)c = 1;
538
if(color & LIGHTMAGENTA)m = 1;
539
if(color & YELLOW)y = 2;
540
if(color & CYAN)c = 2;
541
if(color & MAGENTA)m = 2;
545
/* And now turn CMY to RGB, in the usual spartane way */
547
prgb[0] = (gx_color_value)((2 - c) * HALFTONE);
548
prgb[1] = (gx_color_value)((2 - m) * HALFTONE);
549
prgb[2] = (gx_color_value)((2 - y) * HALFTONE);
517
/* Calculate back CMY components from the internal
518
* representation of the color
524
switch(((lxm_device *)dev)->rendermode)
527
color &= (CYAN|MAGENTA|YELLOW);
528
if(color & CYAN)c = 2;
529
if(color & MAGENTA)m = 2;
530
if(color & YELLOW)y = 2;
535
color &= (CYAN|MAGENTA|YELLOW|LIGHTCYAN|LIGHTMAGENTA);
536
if(color & LIGHTCYAN)c = 1;
537
if(color & LIGHTMAGENTA)m = 1;
538
if(color & YELLOW)y = 2;
539
if(color & CYAN)c = 2;
540
if(color & MAGENTA)m = 2;
544
/* And now turn CMY to RGB, in the usual spartane way */
546
prgb[0] = (gx_color_value)((2 - c) * HALFTONE);
547
prgb[1] = (gx_color_value)((2 - m) * HALFTONE);
548
prgb[2] = (gx_color_value)((2 - y) * HALFTONE);
554
553
/* Main routine of the driver. This takes care of
555
* all parameters and static data initialization
554
* all parameters and static data initialization
556
555
* and calls the proper page printing routines
557
* depending on the selected printing mode.
556
* depending on the selected printing mode.
560
559
lxm3200_print_page(gx_device_printer *pdev, FILE *prn_stream)
562
/* Store data passed by ghostscript to the driver */
563
gendata.dev = (lxm_device *)pdev;
564
gendata.stream = prn_stream;
565
gendata.rendermode = (gendata.dev)->rendermode;
567
/* Snap resolution on one of the three supported setting
568
* (300, 600, 1200 dpi) depending on the input resoution value.
569
* Horizontal and vertical resolution are treated independently.
561
/* Store data passed by ghostscript to the driver */
562
gendata.dev = (lxm_device *)pdev;
563
gendata.stream = prn_stream;
564
gendata.rendermode = (gendata.dev)->rendermode;
566
/* Snap resolution on one of the three supported setting
567
* (300, 600, 1200 dpi) depending on the input resoution value.
568
* Horizontal and vertical resolution are treated independently.
572
if((gendata.dev)->x_pixels_per_inch < 450)gendata.xres = 300;
573
if((gendata.dev)->x_pixels_per_inch > 900)gendata.xres = 1200;
574
gendata.xrmul = 1200 / gendata.xres;
577
if((gendata.dev)->y_pixels_per_inch < 450)gendata.yres = 300;
578
if((gendata.dev)->y_pixels_per_inch > 900)gendata.yres = 1200;
579
gendata.yrmul = 1200 / gendata.yres;
581
/* Cache horizontal and vertical starting offsets */
582
gendata.topoffset = (gendata.dev)->topoffset;
583
gendata.leftoffset = (gendata.dev)->leftoffset;
585
/* Build lookup table for pen offset, adjusting for
586
* vertical resolution setting
588
penofs[0] = (PEN0OFS * 2) / gendata.yrmul;
589
penofs[1] = (PEN1OFS * 2) / gendata.yrmul;
590
penofs[2] = (PEN2OFS * 2) / gendata.yrmul;
592
/* Build lookup table for vertical heads alignment,
593
* adjusting for vertical resolution setting
595
valign[COLORVALIGN] = (COLORVALIGN_V * 2) / gendata.yrmul;
596
valign[BLACKVALIGN] = (BLACKVALIGN_V * 2) / gendata.yrmul;
597
valign[PHOTOVALIGN] = (PHOTOVALIGN_V * 2) / gendata.yrmul;
599
/* Build lookup tables for initial horizontal offsets,
600
* adjusting for horizontal resolution setting
602
/* choose whether to use lxm3200 or Z12 settings */
571
if((gendata.dev)->x_pixels_per_inch < 450)gendata.xres = 300;
572
if((gendata.dev)->x_pixels_per_inch > 900)gendata.xres = 1200;
573
gendata.xrmul = 1200 / gendata.xres;
576
if((gendata.dev)->y_pixels_per_inch < 450)gendata.yres = 300;
577
if((gendata.dev)->y_pixels_per_inch > 900)gendata.yres = 1200;
578
gendata.yrmul = 1200 / gendata.yres;
580
/* Cache horizontal and vertical starting offsets */
581
gendata.topoffset = (gendata.dev)->topoffset;
582
gendata.leftoffset = (gendata.dev)->leftoffset;
584
/* Build lookup table for pen offset, adjusting for
585
* vertical resolution setting
587
penofs[0] = (PEN0OFS * 2) / gendata.yrmul;
588
penofs[1] = (PEN1OFS * 2) / gendata.yrmul;
589
penofs[2] = (PEN2OFS * 2) / gendata.yrmul;
591
/* Build lookup table for vertical heads alignment,
592
* adjusting for vertical resolution setting
594
valign[COLORVALIGN] = (COLORVALIGN_V * 2) / gendata.yrmul;
595
valign[BLACKVALIGN] = (BLACKVALIGN_V * 2) / gendata.yrmul;
596
valign[PHOTOVALIGN] = (PHOTOVALIGN_V * 2) / gendata.yrmul;
598
/* Build lookup tables for initial horizontal offsets,
599
* adjusting for horizontal resolution setting
601
/* choose whether to use lxm3200 or Z12 settings */
603
602
gendata.modelprint=(gendata.dev)->model; /* which model? */
604
603
gendata.z31margin=(gendata.dev)->z31m; /*which additional margin for z31*/
605
604
switch(gendata.modelprint){
606
605
case 1: /* we use the Lexmark Z12 */
607
606
hoffset[LEFT][LEFT] = LHSTART_z12;
608
hoffset[RIGHT][LEFT] = RHSTART_z12 + gendata.lrhalign;
607
hoffset[RIGHT][LEFT] = RHSTART_z12 + gendata.lrhalign;
610
609
default: /* default (if one uses the Lexmark 3200 or the Lexmark Z31) */
611
610
hoffset[LEFT][LEFT] = LHSTART;
612
611
hoffset[RIGHT][LEFT] = RHSTART + gendata.lrhalign;
615
hoffset[LEFT][RIGHT] = hoffset[LEFT][LEFT] - LRPASSHOFS;
614
hoffset[LEFT][RIGHT] = hoffset[LEFT][LEFT] - LRPASSHOFS;
616
615
hoffset[RIGHT][RIGHT] = hoffset[RIGHT][LEFT] - LRPASSHOFS;
618
/* Initialization of general parameters */
619
gendata.outdata = NULL;
620
gendata.scanbuf = NULL;
621
gendata.curheadpos = 0;
624
gendata.lastblack = 0;
625
gendata.curvline = 0;
626
gendata.firstline = 0;
627
gendata.fullflag = FALSE;
628
gendata.direction = LEFT;
631
gendata.bidirprint = (gendata.dev)->bidir;
632
gendata.numpasses = (gendata.dev)->numpass;
635
/* Set some parameters that depend on resolution and
636
* printing mode. We calculate all at 600dpi (the native
637
* resolution) and then correct later for different
638
* resolution settings.
640
switch(gendata.rendermode)
642
/* In monochrome mode we try to use all 208 nozzles of
643
* the black cartridge to speed up printing. But if we
644
* are printing at 1200 dpi horizontal, only 192 nozzles
645
* are available anyway (it seems an hardware limitation).
646
* We print a full buffer at every pass, so the number of
647
* lines in the buffer is the same as the number of nozzles
651
gendata.numblines = 208;
652
gendata.numlines = 208;
653
gendata.select = 0x10;
654
if(gendata.xres == 1200)
656
gendata.numblines = 192;
657
gendata.numlines = 192;
658
gendata.select = 0x00;
662
/* In color or photo mode we must use 192 nozzles only in
663
* the black cartridge, to cope with the color and photo
664
* cartridges (which have 3 color pen of 64 nozzles each,
665
* for a total of 192 nozzles). But the color pens are
666
* vertically spaced and misaligned with respect to the
667
* black pen. To solve this problem, we need a buffer which
668
* is larger than 192 lines and then we print only the
669
* proper "windows" from it. We choose to set the buffer
670
* height to 256, which is the smallest power of two large
671
* enough to hold all the needed data. We use a power of
672
* two for speed, since in this way the modulo operation
673
* in the inner loops (needed to take care of buffer rolling)
674
* becomes a simple and much faster bitwise AND.
678
gendata.numblines = 256;
679
gendata.numlines = 192;
680
gendata.select = 0x00;
684
/* Correct the number of lines of the buffer to take care
685
* of different vertical resolution modes. Since the buffer
686
* does cover a constant vertical spacing, we must double the
687
* number of lines at 1200dpi and half it at 300dpi, to take
688
* into account the different thickness of the lines at the
689
* three different vertical resolutions.
691
gendata.numblines = (gendata.numblines * 2) / gendata.yrmul;
693
/* Now correct the "select" field to adjust the horizontal
694
* motor speed depending on position. Meanwhile, if we are
695
* at 1200 dpi, double the number of horizontal passes
696
* because each stripe at 1200 dpi horizontal must be printed
702
gendata.select |= 0x60;
706
gendata.select |= 0x40;
707
gendata.numpasses *= 2;
711
/* Now store some useful info taken from the ghostscript
712
* device structure to speed up access.
714
gendata.numcols = (gendata.dev)->width;
715
gendata.numvlines = (gendata.dev)->height;
716
gendata.lrhalign = (gendata.dev)->algnA;
717
gendata.vertalign = (gendata.dev)->algnB;
718
gendata.bwsep = (gendata.dev)->algnC;
719
gendata.colsep = (gendata.dev)->algnD;
720
gendata.goffset = (max(gendata.bwsep, gendata.colsep) * 2) / gendata.xrmul;
721
gendata.numbytes = gendata.numcols + (2 * gendata.goffset);
722
gendata.numrbytes = gdev_mem_bytes_per_scan_line(gendata.dev);
724
/* Calculate number of lines in the page and initialize the
725
* counter of the lines to eject. At the end of the printing,
726
* to eject the paper sheet we must send to the printer a
727
* command to move the paper forward. The amount to move is
728
* the length of paper which is still inside the printer plus
729
* two inches (the number is expressed in 1200ths of an inch,
730
* so "plus two inches" means "add 2400").
732
gendata.linetoeject = gendata.numvlines * gendata.yrmul;
733
gendata.linetoeject += 2400;
735
/* Allocate memory for the buffers and
736
* verify that the allocation was done properly.
738
gendata.scanbuf = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, gendata.numblines,
739
"lxm3200_print_page(scanbuf)");
741
gendata.outdata = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, 30,
742
"lxm3200_print_page(outdata)");
744
if(gendata.scanbuf == NULL ||
745
gendata.outdata == NULL)
748
return_error(gs_error_VMerror);
751
/* Send initialization sequence to the printer */
752
if(gendata.modelprint==1) fwrite(z12_init_sequence, sizeof(z12_init_sequence), 1, prn_stream);
753
else fwrite(init_sequence, sizeof(init_sequence), 1, prn_stream);
755
/* Choose the right page printing routine
756
* depending on the printing mode.
758
switch(gendata.rendermode)
774
/* Output the end-of-page epilogue */
777
/* Free the allocated resources */
780
/* Done. Bye bye, see you on next page. */
617
/* Initialization of general parameters */
618
gendata.outdata = NULL;
619
gendata.scanbuf = NULL;
620
gendata.curheadpos = 0;
623
gendata.lastblack = 0;
624
gendata.curvline = 0;
625
gendata.firstline = 0;
626
gendata.fullflag = FALSE;
627
gendata.direction = LEFT;
630
gendata.bidirprint = (gendata.dev)->bidir;
631
gendata.numpasses = (gendata.dev)->numpass;
633
/* Set some parameters that depend on resolution and
634
* printing mode. We calculate all at 600dpi (the native
635
* resolution) and then correct later for different
636
* resolution settings.
638
switch(gendata.rendermode)
640
/* In monochrome mode we try to use all 208 nozzles of
641
* the black cartridge to speed up printing. But if we
642
* are printing at 1200 dpi horizontal, only 192 nozzles
643
* are available anyway (it seems an hardware limitation).
644
* We print a full buffer at every pass, so the number of
645
* lines in the buffer is the same as the number of nozzles
649
gendata.numblines = 208;
650
gendata.numlines = 208;
651
gendata.select = 0x10;
652
if(gendata.xres == 1200)
654
gendata.numblines = 192;
655
gendata.numlines = 192;
656
gendata.select = 0x00;
660
/* In color or photo mode we must use 192 nozzles only in
661
* the black cartridge, to cope with the color and photo
662
* cartridges (which have 3 color pen of 64 nozzles each,
663
* for a total of 192 nozzles). But the color pens are
664
* vertically spaced and misaligned with respect to the
665
* black pen. To solve this problem, we need a buffer which
666
* is larger than 192 lines and then we print only the
667
* proper "windows" from it. We choose to set the buffer
668
* height to 256, which is the smallest power of two large
669
* enough to hold all the needed data. We use a power of
670
* two for speed, since in this way the modulo operation
671
* in the inner loops (needed to take care of buffer rolling)
672
* becomes a simple and much faster bitwise AND.
676
gendata.numblines = 256;
677
gendata.numlines = 192;
678
gendata.select = 0x00;
682
/* Correct the number of lines of the buffer to take care
683
* of different vertical resolution modes. Since the buffer
684
* does cover a constant vertical spacing, we must double the
685
* number of lines at 1200dpi and half it at 300dpi, to take
686
* into account the different thickness of the lines at the
687
* three different vertical resolutions.
689
gendata.numblines = (gendata.numblines * 2) / gendata.yrmul;
691
/* Now correct the "select" field to adjust the horizontal
692
* motor speed depending on position. Meanwhile, if we are
693
* at 1200 dpi, double the number of horizontal passes
694
* because each stripe at 1200 dpi horizontal must be printed
700
gendata.select |= 0x60;
704
gendata.select |= 0x40;
705
gendata.numpasses *= 2;
709
/* Now store some useful info taken from the ghostscript
710
* device structure to speed up access.
712
gendata.numcols = (gendata.dev)->width;
713
gendata.numvlines = (gendata.dev)->height;
714
gendata.lrhalign = (gendata.dev)->algnA;
715
gendata.vertalign = (gendata.dev)->algnB;
716
gendata.bwsep = (gendata.dev)->algnC;
717
gendata.colsep = (gendata.dev)->algnD;
718
gendata.goffset = (max(gendata.bwsep, gendata.colsep) * 2) / gendata.xrmul;
719
gendata.numbytes = gendata.numcols + (2 * gendata.goffset);
720
gendata.numrbytes = gdev_mem_bytes_per_scan_line(gendata.dev);
722
/* Calculate number of lines in the page and initialize the
723
* counter of the lines to eject. At the end of the printing,
724
* to eject the paper sheet we must send to the printer a
725
* command to move the paper forward. The amount to move is
726
* the length of paper which is still inside the printer plus
727
* two inches (the number is expressed in 1200ths of an inch,
728
* so "plus two inches" means "add 2400").
730
gendata.linetoeject = gendata.numvlines * gendata.yrmul;
731
gendata.linetoeject += 2400;
733
/* Allocate memory for the buffers and
734
* verify that the allocation was done properly.
736
gendata.scanbuf = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, gendata.numblines,
737
"lxm3200_print_page(scanbuf)");
739
gendata.outdata = (byte *)gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), gendata.numbytes, 30,
740
"lxm3200_print_page(outdata)");
742
if(gendata.scanbuf == NULL ||
743
gendata.outdata == NULL)
746
return_error(gs_error_VMerror);
749
/* Send initialization sequence to the printer */
750
if(gendata.modelprint==1) fwrite(z12_init_sequence, sizeof(z12_init_sequence), 1, prn_stream);
751
else fwrite(init_sequence, sizeof(init_sequence), 1, prn_stream);
753
/* Choose the right page printing routine
754
* depending on the printing mode.
756
switch(gendata.rendermode)
772
/* Output the end-of-page epilogue */
775
/* Free the allocated resources */
778
/* Done. Bye bye, see you on next page. */
784
782
/* Function that Ghostscript calls to ask the driver
785
* the value of its parameters. This function is based
783
* the value of its parameters. This function is based
786
784
* on the equivalent from the HP850 driver (gdevcd8.c)
787
785
* by Uli Wortmann.
788
786
* I won't comment it because I haven't even tried
903
901
((lxm_device *)pdev)->model = model; /* Model selection: lxm3200, Z12, Z31. */
904
902
((lxm_device *)pdev)->z31m = z31m; /* Additional margin for the Z31 */
906
/* Depending on the selected rendering mode, change the
907
* driver's parameters that ghostscript needs for the
908
* dithering. We need to do it here because the "get_params"
909
* and "put_params" are the only routines in the driver that
910
* ghostscript calls before using the dithering parameters.
915
pdev->color_info.num_components = 1;
916
pdev->color_info.max_gray = 1;
917
pdev->color_info.max_color = 0;
918
pdev->color_info.dither_grays = 2;
919
pdev->color_info.dither_colors = 0;
923
pdev->color_info.num_components = 3;
924
pdev->color_info.max_gray = 1;
925
pdev->color_info.max_color = 1;
926
pdev->color_info.dither_grays = 2;
927
pdev->color_info.dither_colors = 2;
931
pdev->color_info.num_components = 3;
932
pdev->color_info.max_gray = 1;
933
pdev->color_info.max_color = 2;
934
pdev->color_info.dither_grays = 2;
935
pdev->color_info.dither_colors = 3;
904
/* Depending on the selected rendering mode, change the
905
* driver's parameters that ghostscript needs for the
906
* dithering. We need to do it here because the "get_params"
907
* and "put_params" are the only routines in the driver that
908
* ghostscript calls before using the dithering parameters.
913
pdev->color_info.num_components = 1;
914
pdev->color_info.max_gray = 1;
915
pdev->color_info.max_color = 0;
916
pdev->color_info.dither_grays = 2;
917
pdev->color_info.dither_colors = 0;
921
pdev->color_info.num_components = 3;
922
pdev->color_info.max_gray = 1;
923
pdev->color_info.max_color = 1;
924
pdev->color_info.dither_grays = 2;
925
pdev->color_info.dither_colors = 2;
929
pdev->color_info.num_components = 3;
930
pdev->color_info.max_gray = 1;
931
pdev->color_info.max_color = 2;
932
pdev->color_info.dither_grays = 2;
933
pdev->color_info.dither_colors = 3;
943
940
/* --------- Internal routines --------- */
945
942
/* Free the resources allocated by the driver */
947
944
freeresources(gx_device *pdev)
950
gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.scanbuf, gendata.numbytes, gendata.numblines,
951
"lxm3200:freeresources(scanbuf)");
947
gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.scanbuf, gendata.numbytes, gendata.numblines,
948
"lxm3200:freeresources(scanbuf)");
954
gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.outdata, gendata.numbytes, 30,
955
"lxm3200:freeresources(outdata)");
951
gs_free(gs_lib_ctx_get_non_gc_memory_t(), (char *)gendata.outdata, gendata.numbytes, 30,
952
"lxm3200:freeresources(outdata)");
958
955
/* Calculate the checksum of an escape sequence.
959
* It is defined as the sum modulo 256 of the
956
* It is defined as the sum modulo 256 of the
960
957
* six bytes following the escape character.
962
959
* data: pointer to the first of the 8 characters
963
960
* of an escape sequence.
966
963
calccheck8(byte *data)
971
for(i=1; i<7; i++)ck += data[i];
968
for(i=1; i<7; i++)ck += data[i];
976
973
/* Output the page epilogue. This procedure outputs
977
974
* the escape sequence needed to eject the page and
978
975
* take the printheads to the "park" position.
981
978
outputepilogue(void)
986
/* Page eject sequence */
990
trailer[3] = gendata.linetoeject >> 8;
991
trailer[4] = gendata.linetoeject & 0xff;
994
trailer[7] = calccheck8(trailer);
996
/* Calculate the value we need to take the head back
997
* to the park position. This is the current head position
998
* if we printed the last stripe left-to-right, and the
999
* current head position minus 168 (0xa8) if we printed the
1000
* last stripe right-to-left.
1002
pos = gendata.curheadpos;
1003
if(gendata.bidirprint && gendata.direction == LEFT)pos -= 0xa8;
1006
/* Horizontal back sequence */
1010
trailer[11] = pos >> 8;
1011
trailer[12] = pos & 0xff;
1014
trailer[15] = calccheck8(trailer+8);
1016
/* Reset sequence */
1026
fwrite(trailer, 8, 3, gendata.stream);
983
/* Page eject sequence */
987
trailer[3] = gendata.linetoeject >> 8;
988
trailer[4] = gendata.linetoeject & 0xff;
991
trailer[7] = calccheck8(trailer);
993
/* Calculate the value we need to take the head back
994
* to the park position. This is the current head position
995
* if we printed the last stripe left-to-right, and the
996
* current head position minus 168 (0xa8) if we printed the
997
* last stripe right-to-left.
999
pos = gendata.curheadpos;
1000
if(gendata.bidirprint && gendata.direction == LEFT)pos -= 0xa8;
1003
/* Horizontal back sequence */
1007
trailer[11] = pos >> 8;
1008
trailer[12] = pos & 0xff;
1011
trailer[15] = calccheck8(trailer+8);
1013
/* Reset sequence */
1023
fwrite(trailer, 8, 3, gendata.stream);
1029
1026
/* Output a "page forward" escape sequence,
1072
1069
* bytes: total number of bytes in the stripe, including directories
1073
1070
* (but excluding the 24 bytes of the header).
1076
1073
fillheader(int head, int numcol, int firstcol, int bytes)
1078
int len, offs1, startabs;
1079
int endabs, select, fwd;
1080
int back, nabspos, sep;
1083
header = gendata.header;
1085
/* Correct the measures: firstcol and len need to
1086
* be in 1200ths of an inch.
1088
firstcol *= gendata.xrmul;
1089
len = numcol * gendata.xrmul;
1091
/* Alter select to choose direction */
1092
select = gendata.select | (gendata.direction == LEFT ? 0x01 : 0x00);
1094
/* Calculate the proper horizontal offset */
1095
offs1 = hoffset[head][gendata.direction];
1097
/* Now calculate the correct separation depending on the
1098
* head type and adjust "select" to choose between left
1103
sep = (gendata.bwsep * 2) / gendata.xrmul;
1107
sep = (gendata.colsep * 2) / gendata.xrmul;
1111
/* Now calculate absolute starting and ending positions
1112
* of this stripe, taking into account the printing direction
1114
startabs = firstcol + offs1;
1116
if(gendata.direction == LEFT)
1117
endabs = startabs + len;
1119
endabs = startabs - len;
1121
/* And now, basing on current head position,
1122
* transform the absolute coordinates in a
1123
* relative movement of the head.
1124
* The formulas used for this are "black magic",
1125
* since this is a part of the protocol which is
1126
* still not well known. What you see here is an
1127
* empyrical formula devised by examination and
1128
* parameter fitting on the data output by the
1131
if(gendata.direction == LEFT)
1133
nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
1134
fwd = nabspos - gendata.curheadpos;
1139
nabspos = (((endabs - 4800) >> 3) & 0xfff0) + 9;
1141
nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
1142
fwd = gendata.curheadpos - nabspos;
1145
gendata.curheadpos += (gendata.direction == LEFT ? fwd : -fwd);
1147
/* If we are printing unidirectionally, calculate
1148
* the backward movement to return the printing head
1149
* at the beginning of this stripe.
1152
if(gendata.bidirprint == FALSE)
1155
nabspos = ((startabs - 4800) >> 3) & 0xfff0;
1157
nabspos = ((startabs - 3600) >> 3) & 0xfff0;
1159
if(gendata.direction == LEFT)
1160
back = gendata.curheadpos - nabspos;
1162
back = nabspos - gendata.curheadpos;
1165
gendata.curheadpos -= (gendata.direction == LEFT ? back : -back);
1167
/* First part of the header */
1170
header[2] = select; /* Printing type flags */
1171
header[3] = numcol >> 8; /* MSB of the number of columns to print */
1172
header[4] = numcol & 0xff; /* LSB of the number of columns to print */
1173
header[5] = fwd >> 8; /* MSB of the relative forward head motion */
1174
header[6] = fwd & 0xff; /* LSB of the relative forward head motion */
1175
header[7] = calccheck8(&header[0]);
1177
/* Second part of the header */
1181
if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
1182
header[11] = back >> 8; /* MSB of the relative backward head motion */
1183
header[12] = back & 0xff; /* LSB of the relative backward head motion */
1184
header[13] = 0x00; /* MSB of the relative downward head motion */
1185
header[14] = 0x00; /* LSB of the relative downward head motion */
1186
header[15] = calccheck8(&header[8]);
1188
/* Third (and last) part of the header */
1191
header[18] = (bytes >> 16) & 0xff;
1192
header[19] = (bytes >> 8) & 0xff;
1193
header[20] = bytes & 0xff; /* LSB of the number of bytes in this stripe */
1194
header[21] = startabs >> 8; /* MSB of the starting column of this stripe */
1195
header[22] = startabs & 0xff; /* LSB of the starting column of this stripe */
1196
header[23] = calccheck8(&header[16]);
1198
/* Signal to other routines that the output buffer
1199
* is full and how many bytes it is long.
1201
gendata.stripebytes = bytes;
1202
gendata.fullflag = TRUE;
1204
/* If bidirectional printing is in effect, change
1205
* the printing direction for the next stripe
1207
if(gendata.bidirprint)
1208
gendata.direction = (gendata.direction == LEFT ? RIGHT : LEFT);
1075
int len, offs1, startabs;
1076
int endabs, select, fwd;
1077
int back, nabspos, sep;
1080
header = gendata.header;
1082
/* Correct the measures: firstcol and len need to
1083
* be in 1200ths of an inch.
1085
firstcol *= gendata.xrmul;
1086
len = numcol * gendata.xrmul;
1088
/* Alter select to choose direction */
1089
select = gendata.select | (gendata.direction == LEFT ? 0x01 : 0x00);
1091
/* Calculate the proper horizontal offset */
1092
offs1 = hoffset[head][gendata.direction];
1094
/* Now calculate the correct separation depending on the
1095
* head type and adjust "select" to choose between left
1100
sep = (gendata.bwsep * 2) / gendata.xrmul;
1104
sep = (gendata.colsep * 2) / gendata.xrmul;
1108
/* Now calculate absolute starting and ending positions
1109
* of this stripe, taking into account the printing direction
1111
startabs = firstcol + offs1;
1113
if(gendata.direction == LEFT)
1114
endabs = startabs + len;
1116
endabs = startabs - len;
1118
/* And now, basing on current head position,
1119
* transform the absolute coordinates in a
1120
* relative movement of the head.
1121
* The formulas used for this are "black magic",
1122
* since this is a part of the protocol which is
1123
* still not well known. What you see here is an
1124
* empyrical formula devised by examination and
1125
* parameter fitting on the data output by the
1128
if(gendata.direction == LEFT)
1130
nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
1131
fwd = nabspos - gendata.curheadpos;
1136
nabspos = (((endabs - 4800) >> 3) & 0xfff0) + 9;
1138
nabspos = (((endabs - 3600) >> 3) & 0xfff0) + 9;
1139
fwd = gendata.curheadpos - nabspos;
1142
gendata.curheadpos += (gendata.direction == LEFT ? fwd : -fwd);
1144
/* If we are printing unidirectionally, calculate
1145
* the backward movement to return the printing head
1146
* at the beginning of this stripe.
1149
if(gendata.bidirprint == FALSE)
1152
nabspos = ((startabs - 4800) >> 3) & 0xfff0;
1154
nabspos = ((startabs - 3600) >> 3) & 0xfff0;
1156
if(gendata.direction == LEFT)
1157
back = gendata.curheadpos - nabspos;
1159
back = nabspos - gendata.curheadpos;
1162
gendata.curheadpos -= (gendata.direction == LEFT ? back : -back);
1164
/* First part of the header */
1167
header[2] = select; /* Printing type flags */
1168
header[3] = numcol >> 8; /* MSB of the number of columns to print */
1169
header[4] = numcol & 0xff; /* LSB of the number of columns to print */
1170
header[5] = fwd >> 8; /* MSB of the relative forward head motion */
1171
header[6] = fwd & 0xff; /* LSB of the relative forward head motion */
1172
header[7] = calccheck8(&header[0]);
1174
/* Second part of the header */
1178
if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
1179
header[11] = back >> 8; /* MSB of the relative backward head motion */
1180
header[12] = back & 0xff; /* LSB of the relative backward head motion */
1181
header[13] = 0x00; /* MSB of the relative downward head motion */
1182
header[14] = 0x00; /* LSB of the relative downward head motion */
1183
header[15] = calccheck8(&header[8]);
1185
/* Third (and last) part of the header */
1188
header[18] = (bytes >> 16) & 0xff;
1189
header[19] = (bytes >> 8) & 0xff;
1190
header[20] = bytes & 0xff; /* LSB of the number of bytes in this stripe */
1191
header[21] = startabs >> 8; /* MSB of the starting column of this stripe */
1192
header[22] = startabs & 0xff; /* LSB of the starting column of this stripe */
1193
header[23] = calccheck8(&header[16]);
1195
/* Signal to other routines that the output buffer
1196
* is full and how many bytes it is long.
1198
gendata.stripebytes = bytes;
1199
gendata.fullflag = TRUE;
1201
/* If bidirectional printing is in effect, change
1202
* the printing direction for the next stripe
1204
if(gendata.bidirprint)
1205
gendata.direction = (gendata.direction == LEFT ? RIGHT : LEFT);
1211
/* Set final information in the header and output all
1208
/* Set final information in the header and output all
1212
1209
* the data passes. This routine is needed because the
1213
1210
* actual values of two fields of the header (final
1214
1211
* head position and number of vertical lines to reach
1218
1215
* vskip : number of lines to skip to reach next stripe
1219
1216
* newhead: head used for the next stripe (LEFT or RIGHT)
1222
1219
finalizeheader(int vskip, int newhead)
1224
int offs2, nstartabs, back, fwd;
1225
int habs, p, dir, endabs, col;
1229
header = gendata.header;
1231
/* Check the printing direction this stripe
1232
* was originally intended for.
1234
dir = (header[2] & 0x01 ? LEFT : RIGHT);
1236
/* Retrieve the horizontal offset for the next stripe */
1237
offs2 = hoffset[newhead][gendata.direction];
1239
/* Calculate the separation adjust in 1200ths of an inch */
1241
sep = (gendata.bwsep * 2) / gendata.xrmul;
1243
sep = (gendata.colsep * 2) / gendata.xrmul;
1245
/* Now calculate the correct starting column
1246
* of the next stripe
1248
if(gendata.direction == LEFT)
1249
newstart = (gendata.left * gendata.xrmul) - sep;
1251
newstart = (gendata.right * gendata.xrmul);
1253
vskip *= gendata.yrmul;
1255
/* Calculate absolute starting position of new stripe */
1256
nstartabs = newstart + offs2;
1258
/* Calculate absolute ending position of this stripe
1259
* by summing (with proper sign) the starting position
1262
endabs = header[21]*256 + header[22]; /* Starting position */
1263
col = (header[3]*256 + header[4]); /* Width in columns */
1264
col *= gendata.xrmul; /* Transformed in 1200ths of an inch */
1267
endabs += col; /* Printing left-to-right */
1269
endabs -= col; /* Printing right-to-left */
1271
/* Correct head position neutralizing the effect
1272
* of the last issued head movement commands. The
1273
* head movement for this stripe needs to be
1274
* recalculated from scratch to take into account
1275
* the correct beginning position of the next stripe.
1279
gendata.curheadpos += header[11]*256 + header[12]; /* Back movement */
1280
gendata.curheadpos -= header[5]*256 + header[6]; /* Forward movement */
1284
gendata.curheadpos -= header[11]*256 + header[12]; /* Back movement */
1285
gendata.curheadpos += header[5]*256 + header[6]; /* Forward movement */
1288
/* We use a convention of passing a negative value for
1289
* "newhead" to mean that this is the last stripe of the
1290
* sheet, so we don't need to care for the next stripe.
1294
/* Last stripe: we only need to calculate proper forward
1295
* motion to print all the current stripe.
1297
fwd = ((header[5]*256 + header[6]) & 0xfff0) + 9;
1301
/* This is not the last stripe, so we need to calculate
1302
* the forward (in the printing direction) movement
1303
* that will take the printing head at the end of the
1304
* current stripe or at the beginning of the next,
1305
* whichever is farther. Note that we are always
1306
* talking relative to printing direction, so we must
1307
* take into proper account if we are printing from left
1308
* to right or from right to left.
1312
p = max(endabs, nstartabs);
1313
habs = (((p - 3600) >> 3) & 0xfff0) + 9;
1314
fwd = habs - gendata.curheadpos;
1316
/* part for the Lexmark Z31!!! */
1317
if(gendata.modelprint==2) fwd += gendata.z31margin;
1322
p = min(endabs, nstartabs);
1324
habs = (((p - 4800) >> 3) & 0xfff0);
1326
habs = (((p - 3600) >> 3) & 0xfff0);
1327
fwd = gendata.curheadpos - habs;
1331
/* Now update the current head position to take into
1332
* account the forward movement just computed
1334
gendata.curheadpos += (dir == LEFT ? fwd : -fwd);
1336
/* Now calculate the value of the needed backward movement
1337
* to poisition the head correctly for the start of the
1340
if(newhead < 0 || gendata.bidirprint)
1342
/* If this is the last stripe of the page,
1343
* there is no need to take back the head:
1344
* it will be done by the parking command.
1345
* Or if we are printing bidirectionally,
1346
* the forward command has taken the head to
1347
* the correct position, so no need to move it.
1353
/* Calculate the right backward movement basing
1354
* on the start of the next stripe.
1356
if(nstartabs > 4856)
1357
habs = ((nstartabs - 4840) >> 3) & 0xfff0;
1359
habs = ((nstartabs - 3600) >> 3) & 0xfff0;
1361
back = gendata.curheadpos - habs;
1363
/* If the next stripe starts at the right
1364
* of this one, "back" will be too small or
1365
* negative, so correct it.
1366
* It appears that 16 is the minimum allowable
1367
* backward movement that does not make the 3200
1368
* misbehave in the next stripe. This does not hold
1369
* if we are changing printing direction (in such a
1370
* case backward movement may be zero). This means
1371
* we are moving the head a little more than needed,
1372
* but it seems unavoidable.
1374
if(back < 16)back = 16;
1221
int offs2, nstartabs, back, fwd;
1222
int habs, p, dir, endabs, col;
1226
header = gendata.header;
1228
/* Check the printing direction this stripe
1229
* was originally intended for.
1231
dir = (header[2] & 0x01 ? LEFT : RIGHT);
1233
/* Retrieve the horizontal offset for the next stripe */
1234
offs2 = hoffset[newhead][gendata.direction];
1236
/* Calculate the separation adjust in 1200ths of an inch */
1238
sep = (gendata.bwsep * 2) / gendata.xrmul;
1240
sep = (gendata.colsep * 2) / gendata.xrmul;
1242
/* Now calculate the correct starting column
1243
* of the next stripe
1245
if(gendata.direction == LEFT)
1246
newstart = (gendata.left * gendata.xrmul) - sep;
1248
newstart = (gendata.right * gendata.xrmul);
1250
vskip *= gendata.yrmul;
1252
/* Calculate absolute starting position of new stripe */
1253
nstartabs = newstart + offs2;
1255
/* Calculate absolute ending position of this stripe
1256
* by summing (with proper sign) the starting position
1259
endabs = header[21]*256 + header[22]; /* Starting position */
1260
col = (header[3]*256 + header[4]); /* Width in columns */
1261
col *= gendata.xrmul; /* Transformed in 1200ths of an inch */
1264
endabs += col; /* Printing left-to-right */
1266
endabs -= col; /* Printing right-to-left */
1268
/* Correct head position neutralizing the effect
1269
* of the last issued head movement commands. The
1270
* head movement for this stripe needs to be
1271
* recalculated from scratch to take into account
1272
* the correct beginning position of the next stripe.
1276
gendata.curheadpos += header[11]*256 + header[12]; /* Back movement */
1277
gendata.curheadpos -= header[5]*256 + header[6]; /* Forward movement */
1281
gendata.curheadpos -= header[11]*256 + header[12]; /* Back movement */
1282
gendata.curheadpos += header[5]*256 + header[6]; /* Forward movement */
1285
/* We use a convention of passing a negative value for
1286
* "newhead" to mean that this is the last stripe of the
1287
* sheet, so we don't need to care for the next stripe.
1291
/* Last stripe: we only need to calculate proper forward
1292
* motion to print all the current stripe.
1294
fwd = ((header[5]*256 + header[6]) & 0xfff0) + 9;
1298
/* This is not the last stripe, so we need to calculate
1299
* the forward (in the printing direction) movement
1300
* that will take the printing head at the end of the
1301
* current stripe or at the beginning of the next,
1302
* whichever is farther. Note that we are always
1303
* talking relative to printing direction, so we must
1304
* take into proper account if we are printing from left
1305
* to right or from right to left.
1309
p = max(endabs, nstartabs);
1310
habs = (((p - 3600) >> 3) & 0xfff0) + 9;
1311
fwd = habs - gendata.curheadpos;
1313
/* part for the Lexmark Z31!!! */
1314
if(gendata.modelprint==2) fwd += gendata.z31margin;
1319
p = min(endabs, nstartabs);
1321
habs = (((p - 4800) >> 3) & 0xfff0);
1323
habs = (((p - 3600) >> 3) & 0xfff0);
1324
fwd = gendata.curheadpos - habs;
1328
/* Now update the current head position to take into
1329
* account the forward movement just computed
1331
gendata.curheadpos += (dir == LEFT ? fwd : -fwd);
1333
/* Now calculate the value of the needed backward movement
1334
* to poisition the head correctly for the start of the
1337
if(newhead < 0 || gendata.bidirprint)
1339
/* If this is the last stripe of the page,
1340
* there is no need to take back the head:
1341
* it will be done by the parking command.
1342
* Or if we are printing bidirectionally,
1343
* the forward command has taken the head to
1344
* the correct position, so no need to move it.
1350
/* Calculate the right backward movement basing
1351
* on the start of the next stripe.
1353
if(nstartabs > 4856)
1354
habs = ((nstartabs - 4840) >> 3) & 0xfff0;
1356
habs = ((nstartabs - 3600) >> 3) & 0xfff0;
1358
back = gendata.curheadpos - habs;
1360
/* If the next stripe starts at the right
1361
* of this one, "back" will be too small or
1362
* negative, so correct it.
1363
* It appears that 16 is the minimum allowable
1364
* backward movement that does not make the 3200
1365
* misbehave in the next stripe. This does not hold
1366
* if we are changing printing direction (in such a
1367
* case backward movement may be zero). This means
1368
* we are moving the head a little more than needed,
1369
* but it seems unavoidable.
1371
if(back < 16)back = 16;
1377
1374
/* Lastly, update the current head position with the
1378
* backward movement just calculated.
1380
gendata.curheadpos -= (dir == LEFT ? back : -back);
1382
/* Modify first part of the header */
1383
header[5] = fwd >> 8;
1384
header[6] = fwd & 0xff;
1385
header[7] = calccheck8(&header[0]);
1387
/* Modify second part of the header */
1391
if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
1392
header[11] = back >> 8; /* MSB of the relative backward head motion */
1393
header[12] = back & 0xff; /* LSB of the relative backward head motion */
1394
header[13] = vskip >> 8; /* MSB of the relative downward head motion */
1395
header[14] = vskip & 0xff; /* LSB of the relative downward head motion */
1396
header[15] = calccheck8(&header[8]);
1398
/* Now output the data, signalling that the output
1399
* buffer is now empty.
1401
fwrite(header, 3, 8, gendata.stream);
1402
fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
1403
gendata.fullflag = FALSE;
1375
* backward movement just calculated.
1377
gendata.curheadpos -= (dir == LEFT ? back : -back);
1379
/* Modify first part of the header */
1380
header[5] = fwd >> 8;
1381
header[6] = fwd & 0xff;
1382
header[7] = calccheck8(&header[0]);
1384
/* Modify second part of the header */
1388
if(gendata.modelprint==1) header[10] = 0x10; /* Lexmark Z12 protocol */
1389
header[11] = back >> 8; /* MSB of the relative backward head motion */
1390
header[12] = back & 0xff; /* LSB of the relative backward head motion */
1391
header[13] = vskip >> 8; /* MSB of the relative downward head motion */
1392
header[14] = vskip & 0xff; /* LSB of the relative downward head motion */
1393
header[15] = calccheck8(&header[8]);
1395
/* Now output the data, signalling that the output
1396
* buffer is now empty.
1398
fwrite(header, 3, 8, gendata.stream);
1399
fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
1400
gendata.fullflag = FALSE;
1406
/* Convert a buffer data stream into
1403
/* Convert a buffer data stream into
1407
1404
* directory/data representation, using the
1408
1405
* shortest coding (either direct or RLE)
1415
1412
convbuf(int head, int numcols, int firstcol)
1418
int x, i, c, p, q, cnt, rle, std;
1419
int nby, ofs, dts0, dtr0, dtr1;
1422
/* Initialize the pointers. We use the same buffer
1423
* for both input and output (we can do it because
1424
* the output data is at most as long as the input).
1425
* Note that the encode routines skipped 4 bytes at
1426
* each column to make room for the directory word.
1428
read = gendata.outdata + 4;
1429
write = gendata.outdata;
1431
/* Set the parameters that will be used to create the directory and
1432
* to access the data. These parameters define the structure of the
1433
* directory word (32 bit) and depend on the number of nozzles that
1434
* are used. Note that the directory bitfield is initialized to all
1435
* ones (but read below for further info) because it works in negative
1436
* logic (i.e. a change is marked by a zero bit).
1437
* Below, nby is the number of bytes needed in the input data to map
1438
* a column (each nozzle is 1 bit, so 208 nozzles are 26 bytes and
1439
* 192 nozzles are 24 bytes). Ofs is the number of the first bit of
1440
* the directory bitfield in the directory word (with 208 nozzles we
1441
* need 26 bits, from 6 to 31, with 192 nozzles we need 24 bits, from
1442
* 8 to 31). The other three parameters are the values needed to
1443
* initialize the directory word properly: the key is the first two
1444
* bits, which must be "10" for a directly encoded stripe and "01" for
1445
* a RLE encoded one. In the lexmark directory, each bit represents a
1446
* group of 8 nozzles: in a directly encoded stripe if the bit is "1"
1447
* it means none of the nozzles in the group are used, if it is a "0"
1448
* it means at least one is used and we need to append a data byte to
1449
* define the exact usage pattern. So, for direct encoded stripes we
1450
* start with the first two bits set to "10" and all the directory
1451
* bitfield set to "1" (we will unset to "0" only the needed bits in
1452
* the encoding loop). If we are using RLE encoding, each "0" bits
1453
* means that there is a data byte that defines a pattern for the
1454
* group of 8 nozzles associated to that bit, and an "1" means that
1455
* the pattern for the associated group of nozzles is the same as the
1456
* previous group. This means that for RLE encoded stripes we start the
1457
* directory word with two bits set to "01" and then initialize to "1"
1458
* all the directory bitfield, except the first one which must be 0
1459
* because we must have at least one data byte to define the initial
1460
* pattern that will be eventually repeated.
1462
if(gendata.numlines == 208)
1479
/* The variable "bytes" will contain the total
1480
* number of output bytes in the data stripe.
1484
/* For all the columns in the stripe */
1485
for(x = 0; x < numcols; x++)
1487
/* Calculate which representation is smaller by counting
1488
* the number of non zero data bytes for the direct encoding
1489
* and the number of changes between data bytes for the RLE.
1490
* At the end we have in "std" the length of the output data
1491
* if encoded with standard encoding, and in "rle" the length
1492
* of the output data if encoded with RLE.
1497
for(i=1; i<nby; i++)
1499
if((p = read[i]))std++;
1507
/* Now initialize the last two bytes in the directory
1508
* word. These always belong to the directory bitfield
1509
* and must be set to all ones.
1514
/* And now encode the column, using the shortest encoding.
1515
* If the two encodings are of equal length we prefer the
1516
* standard encoding to the RLE one. No real reason for
1517
* this: it could have been done the other way, but it
1518
* seems the Windows driver does this way as well...
1522
/* Run-length encoding */
1532
for(i=1; i<nby; i++)
1538
write[q>>3] &= ibits[q & 7];
1546
/* Standard encoding */
1554
for(i=0; i<nby; i++)
1560
write[q>>3] &= ibits[q & 7];
1567
/* Update the counters and pointers. Note that when
1568
* we are here "cnt" is the number of bytes that we
1569
* have actually output, including the directory word.
1576
fillheader(head, numcols, firstcol, bytes);
1415
int x, i, c, p, q, cnt, rle, std;
1416
int nby, ofs, dts0, dtr0, dtr1;
1419
/* Initialize the pointers. We use the same buffer
1420
* for both input and output (we can do it because
1421
* the output data is at most as long as the input).
1422
* Note that the encode routines skipped 4 bytes at
1423
* each column to make room for the directory word.
1425
read = gendata.outdata + 4;
1426
write = gendata.outdata;
1428
/* Set the parameters that will be used to create the directory and
1429
* to access the data. These parameters define the structure of the
1430
* directory word (32 bit) and depend on the number of nozzles that
1431
* are used. Note that the directory bitfield is initialized to all
1432
* ones (but read below for further info) because it works in negative
1433
* logic (i.e. a change is marked by a zero bit).
1434
* Below, nby is the number of bytes needed in the input data to map
1435
* a column (each nozzle is 1 bit, so 208 nozzles are 26 bytes and
1436
* 192 nozzles are 24 bytes). Ofs is the number of the first bit of
1437
* the directory bitfield in the directory word (with 208 nozzles we
1438
* need 26 bits, from 6 to 31, with 192 nozzles we need 24 bits, from
1439
* 8 to 31). The other three parameters are the values needed to
1440
* initialize the directory word properly: the key is the first two
1441
* bits, which must be "10" for a directly encoded stripe and "01" for
1442
* a RLE encoded one. In the lexmark directory, each bit represents a
1443
* group of 8 nozzles: in a directly encoded stripe if the bit is "1"
1444
* it means none of the nozzles in the group are used, if it is a "0"
1445
* it means at least one is used and we need to append a data byte to
1446
* define the exact usage pattern. So, for direct encoded stripes we
1447
* start with the first two bits set to "10" and all the directory
1448
* bitfield set to "1" (we will unset to "0" only the needed bits in
1449
* the encoding loop). If we are using RLE encoding, each "0" bits
1450
* means that there is a data byte that defines a pattern for the
1451
* group of 8 nozzles associated to that bit, and an "1" means that
1452
* the pattern for the associated group of nozzles is the same as the
1453
* previous group. This means that for RLE encoded stripes we start the
1454
* directory word with two bits set to "01" and then initialize to "1"
1455
* all the directory bitfield, except the first one which must be 0
1456
* because we must have at least one data byte to define the initial
1457
* pattern that will be eventually repeated.
1459
if(gendata.numlines == 208)
1476
/* The variable "bytes" will contain the total
1477
* number of output bytes in the data stripe.
1481
/* For all the columns in the stripe */
1482
for(x = 0; x < numcols; x++)
1484
/* Calculate which representation is smaller by counting
1485
* the number of non zero data bytes for the direct encoding
1486
* and the number of changes between data bytes for the RLE.
1487
* At the end we have in "std" the length of the output data
1488
* if encoded with standard encoding, and in "rle" the length
1489
* of the output data if encoded with RLE.
1494
for(i=1; i<nby; i++)
1496
if((p = read[i]))std++;
1504
/* Now initialize the last two bytes in the directory
1505
* word. These always belong to the directory bitfield
1506
* and must be set to all ones.
1511
/* And now encode the column, using the shortest encoding.
1512
* If the two encodings are of equal length we prefer the
1513
* standard encoding to the RLE one. No real reason for
1514
* this: it could have been done the other way, but it
1515
* seems the Windows driver does this way as well...
1519
/* Run-length encoding */
1529
for(i=1; i<nby; i++)
1535
write[q>>3] &= ibits[q & 7];
1543
/* Standard encoding */
1551
for(i=0; i<nby; i++)
1557
write[q>>3] &= ibits[q & 7];
1564
/* Update the counters and pointers. Note that when
1565
* we are here "cnt" is the number of bytes that we
1566
* have actually output, including the directory word.
1573
fillheader(head, numcols, firstcol, bytes);
1579
1576
/* This routine takes one full buffer of data and
1584
1581
encode_bw_buf(void)
1586
int left, right, x, y, nn, mod;
1587
int nxp, yy, numcols, incr;
1588
int dy, dy2, csep, pass, f1;
1589
int f2, start, s1, s2, yincr;
1593
/* Set some parameters that depend on resolution and are
1594
* used in the inner loop to select lines to print.
1595
* We basically encode all the even nozzles in a loop and
1596
* all the odd nozzles in another loop. The values of s1
1597
* and s2 are the starting offset in the line buffer for
1598
* the first and second loop, and yincr is the number of lines
1599
* in the buffer we move on at each cycle.
1601
switch(gendata.yres)
1603
/* At 300 dpi we use only one nozzle column, and
1604
* each line in the buffer is printed. So both offsets
1605
* are zero (only one is used, actually) and yincr is 1.
1606
* The mask is set to 127 because the buffer is 128 lines.
1615
/* At 600 dpi we use both nozzle columns: each row goes
1616
* alternatively to the left or right nozzle column. So
1617
* the even offset is zero, the odd offset is 1 and the
1618
* increment is 2: in this way the even loop scans lines
1619
* 0, 2, 4, ... and the odd loop lines 1, 3, 5, ...
1620
* Here the buffer is 256 lines so mask is set to 255.
1630
/* At 1200 dpi we are printing two interleaved passes. Each
1631
* nozzle column sees every fourth line in the buffer (so
1632
* yincr is 4) and the starting offset varies depending on
1633
* which interleaved pass we are doing.
1634
* During the first pass, even nozzles are used to print
1635
* lines 0, 4, 8, ... and odd nozzles are used to print
1636
* lines 2, 6, 10, ... while in the second pass the even
1637
* nozzles print lines 1, 5, 9, ... and the odd nozzles
1638
* print lines 3, 7, 11, ...
1639
* The buffer is 512 lines, so mask is set to 511 */
1642
s1 = (gendata.ileave ? 1 : 0);
1643
s2 = (gendata.ileave ? 3 : 2);
1648
/* Now we must calculate the offset q from the beginning of
1649
* the buffer of the first line to print in this pass, and
1650
* the total number of lines to be printed. We print as many
1651
* lines as we can in a single pass, i.e. the value of "lines"
1652
* is simply the number of lines that at the current vertical
1653
* resolution fully cover the printing pen.
1654
* Note that in case of monochrome printing we print all
1655
* buffer lines, from first to last, so we also need to set
1656
* the mask to a neutral value because we don't use wrapping.
1658
if(gendata.rendermode == LXM3200_M)
1662
lines = gendata.numblines;
1666
q = gendata.firstline + valign[BLACKVALIGN];
1667
lines = (BWCOLPEN * 2) / gendata.yrmul;
1670
/* Adjust the value of the nozzle column separation to the
1671
* horizontal resolution we are using now.
1673
csep = (gendata.bwsep * 2) / gendata.xrmul;
1675
/* Here we calculate how many "real" passes we are doing.
1676
* A "real" pass is a pass where a full column is printed
1677
* and then some columns (maybe zero) are skipped before
1678
* printing another one. If we are at 1200 dpi horizontal
1679
* then we must use only one nozzle column at a time, so each
1680
* real pass comprises two subpasses, one where we print with
1681
* even nozzles only and another where we print with odd
1682
* nozzles only. So at 1200 dpi the "real" passes are half the
1683
* total number of passes. Another way of looking at it: the
1684
* "nxp" variable holds the separation, in columns, between two
1685
* dot columns printed in the same head sweep.
1687
nxp = gendata.numpasses;
1688
if(gendata.xres == 1200)nxp /= 2;
1690
/* Now calculate the byte increments for the *output* data
1691
* buffer (i.e. the encoded buffer). The first variable,
1692
* dy, is the number of bytes taken by a single data burst
1693
* (both even and odd nozzle columns). The second variable,
1694
* dy2, tells how many bytes we must skip from one column
1695
* to the other (if we are printing multipass we skip some
1696
* columns that will be printed in subsequent passes).
1698
dy = (gendata.numlines / 8) + 4;
1701
/* Calculate the starting and ending horizontal positions for
1702
* this head pass. There are the margins corrected to take
1703
* into account the displacement between the odd and even
1704
* nozzle columns (csep). Moreover we start "csep" pixels
1705
* before the margin to give the head a little more room to
1706
* accelerate properly (not sure if this really works, but it
1707
* doesn't cost much, so I've left it in).
1709
if(gendata.direction == LEFT)
1711
left = gendata.left - 2*csep;
1712
right = gendata.right + csep;
1716
left = gendata.left - csep;
1717
right = gendata.right + 2*csep;
1720
/* Number of columns in a full row */
1721
numcols = right - left;
1723
/* Calculate the last pixel of the first pass of the
1724
* stripe. If we are printing bidirectionally, this
1725
* will be the base to calculate the start of the
1726
* passes printed right-to-left.
1728
mod = numcols - (numcols % nxp);
1730
/* f1 and f2 are two flags that define which nozzle columns
1731
* we are using in this stripe, f1 for the even nozzle column
1732
* and f2 for the odd nozzle column: if they are zero that
1733
* nozzle column is not used in this pass.
1737
if(gendata.yres == 300)
1739
/* At 300 dpi we use only one nozzle column. As of now this
1740
* is always the even one, but maybe it could be tried to
1741
* alternate between columns at each pass, to improve the
1748
/* Now start the passes to fill all the stripe */
1749
for(pass = 0; pass < gendata.numpasses; pass++)
1751
/* If there is data in the buffer which has not been
1752
* sent to the printer yet, send it now.
1754
if(gendata.fullflag)
1756
fwrite(gendata.header, 3, 8, gendata.stream);
1757
fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
1758
gendata.fullflag = FALSE;
1761
/* Clear the output buffer to avoid problems with the bitwise
1762
* operations we will do later on.
1764
memset(gendata.outdata, 0, gendata.numbytes * 30);
1766
/* Calculate standard increments, starting column
1767
* and start of output data. They will be corrected
1768
* later for 1200dpi or right-to-left printing direction.
1771
start = left + pass;
1772
data = gendata.outdata + (pass*dy) + 4;
1774
/* It appears that at 1200dpi, in addition of not being able
1775
* to use 208 nozzles mode for the black cartridge, the Lexmark
1776
* 3200 cannot print at full rate with all the 192 useable nozzles.
1777
* Maybe the reason is that the data rate of 1200dpi horizontal
1778
* resolution exceeds the mechanical/thermal limits of the heads.
1779
* So if we are printing at 1200dpi we need to use alternatively
1780
* only odd or even numbered nozzles, for each printed column, to
1781
* half the data rate towards the head.
1782
* This obviously means that, at 1200dpi horizontal, a minimum of
1783
* two passes are required to print each stripe. Since if we are
1784
* printing at 1200dpi vertical we need two interlaced passes, a
1785
* minimum grand total of 4 passes are needed to print one full
1786
* 1200x1200 dpi stripe with the Lexmark 3200.
1788
if(gendata.xres == 1200)
1793
start = left + (pass/2);
1794
data = gendata.outdata + ((pass/2)*dy) + 4;
1797
/* If printing right-to-left we need to present data
1798
* to the printer in that direction, inverting the
1799
* normal flow of data.
1801
if(gendata.direction == RIGHT)
1807
/* Start column scanning */
1810
/* Now we split the behaviour depending on the printing
1811
* direction. To be honest, the inner loops are almost
1812
* identical between left-to-right and right-to-left
1813
* directions. The only difference is where is computed
1814
* the contribute of the nozzle columns separation ("csep"),
1815
* but having the "if" outside the loop it's somehow better.
1817
if(gendata.direction == LEFT)
1819
/* For all the columns in this pass */
1820
for(nn = 0; nn < numcols; nn += nxp)
1822
/* Encode the even numbered nozzles */
1825
scan = gendata.scanbuf + x;
1827
for(y = s1; y < lines; y += yincr)
1829
if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1830
data[yy/8] |= bits[yy&7];
1835
/* Encode the odd numbered nozzles */
1836
if(((x+csep) < gendata.numbytes) && f2)
1838
scan = gendata.scanbuf + x + csep;
1840
for(y = s2; y < lines; y += yincr)
1842
if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1843
data[yy/8] |= bits[yy&7];
1848
/* If we are in 1200dpi horizontal resolution,
1849
* alternate between nozzle columns to avoid
1850
* overstressing the printing head.
1852
if(gendata.xres == 1200)
1858
/* Adjust data pointers */
1863
else /* direction == RIGHT */
1865
/* For all the columns in this pass */
1866
for(nn = 0; nn < numcols; nn += nxp)
1868
/* Encode the odd numbered nozzles */
1869
if((x < gendata.numbytes) && f1)
1871
scan = gendata.scanbuf + x;
1873
for(y = s1; y < lines; y += yincr)
1875
if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1876
data[yy/8] |= bits[yy&7];
1881
/* Encode the even numbered nozzles */
1882
if(((x-csep) >= 0) && f2)
1884
scan = gendata.scanbuf + x - csep;
1886
for(y = s2; y < lines; y += yincr)
1888
if(scan[((y+q) & mask)*gendata.numbytes] & BLACK)
1889
data[yy/8] |= bits[yy&7];
1894
/* If we are in 1200dpi horizontal resolution,
1895
* alternate between nozzle columns to avoid
1896
* overstressing the printing head.
1898
if(gendata.xres == 1200)
1904
/* Adjust data pointers */
1910
/* Convert the buffer to the shortest output format.
1911
* Which is the first column of the output depends
1912
* on the printing direction: it will be the left
1913
* margin if we are printing left to right or the
1914
* right margin if we are printing right to left.
1916
if(gendata.direction == LEFT)
1917
convbuf(LEFT, numcols, left);
1919
convbuf(LEFT, numcols, right);
1583
int left, right, x, y, nn, mod;
1584
int nxp, yy, numcols, incr;
1585
int dy, dy2, csep, pass, f1;
1586
int f2, start, s1, s2, yincr;
1590
/* Set some parameters that depend on resolution and are
1591
* used in the inner loop to select lines to print.
1592
* We basically encode all the even nozzles in a loop and
1593
* all the odd nozzles in another loop. The values of s1
1594
* and s2 are the starting offset in the line buffer for
1595
* the first and second loop, and yincr is the number of lines
1596
* in the buffer we move on at each cycle.
1598
switch(gendata.yres)
1600
/* At 300 dpi we use only one nozzle column, and
1601
* each line in the buffer is printed. So both offsets
1602
* are zero (only one is used, actually) and yincr is 1.
1603
* The mask is set to 127 because the buffer is 128 lines.
1612
/* At 600 dpi we use both nozzle columns: each row goes
1613
* alternatively to the left or right nozzle column. So
1614
* the even offset is zero, the odd offset is 1 and the
1615
* increment is 2: in this way the even loop scans lines
1616
* 0, 2, 4, ... and the odd loop lines 1, 3, 5, ...
1617
* Here the buffer is 256 lines so mask is set to 255.
1627
/* At 1200 dpi we are printing two interleaved passes. Each
1628
* nozzle column sees every fourth line in the buffer (so
1629
* yincr is 4) and the starting offset varies depending on
1630
* which interleaved pass we are doing.
1631
* During the first pass, even nozzles are used to print
1632
* lines 0, 4, 8, ... and odd nozzles are used to print
1633
* lines 2, 6, 10, ... while in the second pass the even
1634
* nozzles print lines 1, 5, 9, ... and the odd nozzles
1635
* print lines 3, 7, 11, ...
1636
* The buffer is 512 lines, so mask is set to 511 */
1639
s1 = (gendata.ileave ? 1 : 0);
1640
s2 = (gendata.ileave ? 3 : 2);
1645
/* Now we must calculate the offset q from the beginning of
1646
* the buffer of the first line to print in this pass, and
1647
* the total number of lines to be printed. We print as many
1648
* lines as we can in a single pass, i.e. the value of "lines"
1649
* is simply the number of lines that at the current vertical
1650
* resolution fully cover the printing pen.
1651
* Note that in case of monochrome printing we print all
1652
* buffer lines, from first to last, so we also need to set
1653
* the mask to a neutral value because we don't use wrapping.
1655
if(gendata.rendermode == LXM3200_M)
1659
lines = gendata.numblines;
1663
q = gendata.firstline + valign[BLACKVALIGN];
1664
lines = (BWCOLPEN * 2) / gendata.yrmul;
1667
/* Adjust the value of the nozzle column separation to the
1668
* horizontal resolution we are using now.
1670
csep = (gendata.bwsep * 2) / gendata.xrmul;
1672
/* Here we calculate how many "real" passes we are doing.
1673
* A "real" pass is a pass where a full column is printed
1674
* and then some columns (maybe zero) are skipped before
1675
* printing another one. If we are at 1200 dpi horizontal
1676
* then we must use only one nozzle column at a time, so each
1677
* real pass comprises two subpasses, one where we print with
1678
* even nozzles only and another where we print with odd
1679
* nozzles only. So at 1200 dpi the "real" passes are half the
1680
* total number of passes. Another way of looking at it: the
1681
* "nxp" variable holds the separation, in columns, between two
1682
* dot columns printed in the same head sweep.
1684
nxp = gendata.numpasses;
1685
if(gendata.xres == 1200)nxp /= 2;
1687
/* Now calculate the byte increments for the *output* data
1688
* buffer (i.e. the encoded buffer). The first variable,
1689
* dy, is the number of bytes taken by a single data burst
1690
* (both even and odd nozzle columns). The second variable,
1691
* dy2, tells how many bytes we must skip from one column
1692
* to the other (if we are printing multipass we skip some
1693
* columns that will be printed in subsequent passes).
1695
dy = (gendata.numlines / 8) + 4;
1698
/* Calculate the starting and ending horizontal positions for
1699
* this head pass. There are the margins corrected to take
1700
* into account the displacement between the odd and even
1701
* nozzle columns (csep). Moreover we start "csep" pixels
1702
* before the margin to give the head a little more room to
1703
* accelerate properly (not sure if this really works, but it
1704
* doesn't cost much, so I've left it in).
1706
if(gendata.direction == LEFT)
1708
left = gendata.left - 2*csep;
1709
right = gendata.right + csep;
1713
left = gendata.left - csep;
1714
right = gendata.right + 2*csep;
1717
/* Number of columns in a full row */
1718
numcols = right - left;
1720
/* Calculate the last pixel of the first pass of the
1721
* stripe. If we are printing bidirectionally, this
1722
* will be the base to calculate the start of the
1723
* passes printed right-to-left.
1725
mod = numcols - (numcols % nxp);
1727
/* f1 and f2 are two flags that define which nozzle columns
1728
* we are using in this stripe, f1 for the even nozzle column
1729
* and f2 for the odd nozzle column: if they are zero that
1730
* nozzle column is not used in this pass.
1734
if(gendata.yres == 300)
1736
/* At 300 dpi we use only one nozzle column. As of now this
1737
* is always the even one, but maybe it could be tried to
1738
* alternate between columns at each pass, to improve the
1745
/* Now start the passes to fill all the stripe */
1746
for(pass = 0; pass < gendata.numpasses; pass++)
1748
/* If there is data in the buffer which has not been
1749
* sent to the printer yet, send it now.
1751
if(gendata.fullflag)
1753
fwrite(gendata.header, 3, 8, gendata.stream);
1754
fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
1755
gendata.fullflag = FALSE;
1758
/* Clear the output buffer to avoid problems with the bitwise
1759
* operations we will do later on.
1761
memset(gendata.outdata, 0, gendata.numbytes * 30);
1763
/* Calculate standard increments, starting column
1764
* and start of output data. They will be corrected
1765
* later for 1200dpi or right-to-left printing direction.
1768
start = left + pass;
1769
data = gendata.outdata + (pass*dy) + 4;
1771
/* It appears that at 1200dpi, in addition of not being able
1772
* to use 208 nozzles mode for the black cartridge, the Lexmark
1773
* 3200 cannot print at full rate with all the 192 useable nozzles.
1774
* Maybe the reason is that the data rate of 1200dpi horizontal
1775
* resolution exceeds the mechanical/thermal limits of the heads.
1776
* So if we are printing at 1200dpi we need to use alternatively
1777
* only odd or even numbered nozzles, for each printed column, to
1778
* half the data rate towards the head.
1779
* This obviously means that, at 1200dpi horizontal, a minimum of
1780
* two passes are required to print each stripe. Since if we are
1781
* printing at 1200dpi vertical we need two interlaced passes, a
1782
* minimum grand total of 4 passes are needed to print one full
1783
* 1200x1200 dpi stripe with the Lexmark 3200.
1785
if(gendata.xres == 1200)
1790
start = left + (pass/2);
1791
data = gendata.outdata + ((pass/2)*dy) + 4;
1794
/* If printing right-to-left we need to present data
1795
* to the printer in that direction, inverting the
1796
* normal flow of data.
1798
if(gendata.direction == RIGHT)
1804
/* Start column scanning */
1807
/* Now we split the behaviour depending on the printing
1808
* direction. To be honest, the inner loops are almost
1809
* identical between left-to-right and right-to-left
1810
* directions. The only difference is where is computed
1811
* the contribute of the nozzle columns separation ("csep"),
1812
* but having the "if" outside the loop it's somehow better.
1814
if(gendata.direction == LEFT)
1816
/* For all the columns in this pass */
1817
for(nn = 0; nn < numcols; nn += nxp)
1819
/* Encode the even numbered nozzles */
1822
scan = gendata.scanbuf + x;
1824
for(y = s1; y < lines; y += yincr)
1826
if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1827
data[yy/8] |= bits[yy&7];
1832
/* Encode the odd numbered nozzles */
1833
if(((x+csep) < gendata.numbytes) && f2)
1835
scan = gendata.scanbuf + x + csep;
1837
for(y = s2; y < lines; y += yincr)
1839
if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1840
data[yy/8] |= bits[yy&7];
1845
/* If we are in 1200dpi horizontal resolution,
1846
* alternate between nozzle columns to avoid
1847
* overstressing the printing head.
1849
if(gendata.xres == 1200)
1855
/* Adjust data pointers */
1860
else /* direction == RIGHT */
1862
/* For all the columns in this pass */
1863
for(nn = 0; nn < numcols; nn += nxp)
1865
/* Encode the odd numbered nozzles */
1866
if((x < gendata.numbytes) && f1)
1868
scan = gendata.scanbuf + x;
1870
for(y = s1; y < lines; y += yincr)
1872
if(scan[((y+q) & mask) * gendata.numbytes] & BLACK)
1873
data[yy/8] |= bits[yy&7];
1878
/* Encode the even numbered nozzles */
1879
if(((x-csep) >= 0) && f2)
1881
scan = gendata.scanbuf + x - csep;
1883
for(y = s2; y < lines; y += yincr)
1885
if(scan[((y+q) & mask)*gendata.numbytes] & BLACK)
1886
data[yy/8] |= bits[yy&7];
1891
/* If we are in 1200dpi horizontal resolution,
1892
* alternate between nozzle columns to avoid
1893
* overstressing the printing head.
1895
if(gendata.xres == 1200)
1901
/* Adjust data pointers */
1907
/* Convert the buffer to the shortest output format.
1908
* Which is the first column of the output depends
1909
* on the printing direction: it will be the left
1910
* margin if we are printing left to right or the
1911
* right margin if we are printing right to left.
1913
if(gendata.direction == LEFT)
1914
convbuf(LEFT, numcols, left);
1916
convbuf(LEFT, numcols, right);
1923
1920
/* This routine is the equivalent of encode_bw_buf() but
1924
1921
* for color or photo cartridge. Since this routine is
1925
1922
* heavily based on the B/W one, the comments here will
1926
* be somewhat less esaurient. Please have a look at
1923
* be somewhat less esaurient. Please have a look at
1927
1924
* encode_bw_buf() to understand better how this routine
1928
1925
* works: I will only pinpoint the differences between this
1929
1926
* routine and encode_bw_buf().
1931
1928
* head: the head we are calculating the buffer for. It will
1932
1929
* be LEFT for a photo cartridge or RIGHT for a color one.
1935
1932
encode_col_buf(int head)
1937
int left, right, x, y, nn, mod;
1938
int nxp, yy, numcols, incr;
1939
int dy, dy2, csep, pass, f1;
1940
int f2, start, s1, s2, yincr;
1941
int q, mask, k, align, lines;
1944
/* Here there are two more parameters: mask and lines, that
1945
* for color cartridges are both dependent on vertical
1946
* resolution. Since the buffer is "rolling", i.e. it is
1947
* implemented as a circular array, all the coordinates of
1948
* the buffer lines must be taken modulo the buffer length.
1949
* We choose a buffer length that is a power of two to be
1950
* able to turn the modulo operation into a bitwise AND, so
1951
* we need to set "mask" to the correct value for the AND.
1952
* Another difference is that "lines", i.e. the number of
1953
* lines to print in each pass, is based on the height of a
1954
* color pen. Since there are three color pens in each cartridge,
1955
* each color pen is treated separately to fully cover the
1958
switch(gendata.yres)
1979
s1 = (gendata.ileave ? 1 : 0);
1980
s2 = (gendata.ileave ? 3 : 2);
1986
/* Choose the vertical alignment depending on the head.
1987
* This is needed to vertically align the color cartridge
1988
* with the photo or black cartridge.
1991
align = valign[PHOTOVALIGN];
1993
align = valign[COLORVALIGN];
1995
/* All the stuff below is exactly the same as in
1996
* encode_bw_buf(), and is therefore commented there.
1999
csep = (gendata.bwsep * 2) / gendata.xrmul;
2000
nxp = gendata.numpasses;
2001
if(gendata.xres == 1200)nxp /= 2;
2003
dy = (gendata.numlines / 8) + 4;
2006
if(gendata.direction == LEFT)
2008
left = gendata.left - 2*csep;
2009
right = gendata.right + csep;
2013
left = gendata.left - csep;
2014
right = gendata.right + 2*csep;
2017
numcols = right - left;
2018
mod = numcols - (numcols % nxp);
2022
if(gendata.yres == 300)
2028
/* For all passes */
2029
for(pass = 0; pass < gendata.numpasses; pass++)
2031
/* If there is data in the buffer which has not been
2032
* sent to the printer yet, do it now.
2034
if(gendata.fullflag)
2036
fwrite(gendata.header, 3, 8, gendata.stream);
2037
fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
2038
gendata.fullflag = FALSE;
2041
/* All the stuff below is exactly the same as in
2042
* encode_bw_buf(), and is therefore commented there.
2045
memset(gendata.outdata, 0, gendata.numbytes * 30);
2048
start = left + pass;
2049
data = gendata.outdata + (pass*dy) + 4;
2051
if(gendata.xres == 1200)
2056
start = left + (pass/2);
2057
data = gendata.outdata + ((pass/2)*dy) + 4;
2060
if(gendata.direction == RIGHT)
2066
/* Start column scanning */
2069
if(gendata.direction == LEFT)
2071
/* For all the columns */
2072
for(nn = 0; nn < numcols; nn += nxp)
2074
/* Encode the even numbered nozzles */
2077
scan = gendata.scanbuf + x;
2080
/* In color printing there is one more loop to scan
2081
* all three color pens. We have to do exactly the
2082
* same things for all pens: the only differences are
2083
* the color encoding bit we are testing and the offset
2084
* from the beginning of the buffer and the offset of the
2085
* output data. All of this is stored into arrays. The
2086
* "penofs" array stores the offset of the first line of
2087
* each pen in the raster buffer. The array "colmask" stores
2088
* the encoding bits for the color of each pen, and it
2089
* is bidimensional because pen masks are different between
2090
* a color cartridge (where pens are Cyan, Magenta, Yellow)
2091
* and a photo cartridge (where pens are LightCyan,
2092
* LightMagenta and Black).
2096
q = gendata.firstline + align + penofs[k];
2097
for(y = s1; y < lines; y += yincr)
2099
if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2100
data[yy/8] |= bits[yy&7];
2106
/* Encode the odd numbered nozzles */
2107
if(((x+csep) < gendata.numbytes) && f2)
2109
scan = gendata.scanbuf + x + csep;
2113
q = gendata.firstline + align + penofs[k];
2114
for(y = s2; y < lines; y += yincr)
2116
if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2117
data[yy/8] |= bits[yy&7];
2123
/* If we are in 1200dpi horizontal resolution,
2124
* alternate between nozzle columns to avoid
2125
* overstressing the printing head.
2127
if(gendata.xres == 1200)
2133
/* Adjust data pointers */
2140
/* For all the columns */
2141
for(nn = 0; nn < numcols; nn += nxp)
2143
/* Encode the odd numbered nozzles */
2144
if((x < gendata.numbytes) && f1)
2146
scan = gendata.scanbuf + x;
2150
q = gendata.firstline + align + penofs[k];
2151
for(y = s1; y < lines; y += yincr)
2153
if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2154
data[yy/8] |= bits[yy&7];
2160
/* Encode the even numbered nozzles */
2161
if(((x-csep) >= 0) && f2)
2163
scan = gendata.scanbuf + x - csep;
2167
q = gendata.firstline + align + penofs[k];
2168
for(y = s2; y < lines; y += yincr)
2170
if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2171
data[yy/8] |= bits[yy&7];
2177
/* If we are in 1200dpi horizontal resolution,
2178
* alternate between nozzle columns to avoid
2179
* overstressing the printing head.
2181
if(gendata.xres == 1200)
2187
/* Adjust data pointers */
2193
if(gendata.direction == LEFT)
2194
convbuf(head, numcols, left);
2196
convbuf(head, numcols, right);
1934
int left, right, x, y, nn, mod;
1935
int nxp, yy, numcols, incr;
1936
int dy, dy2, csep, pass, f1;
1937
int f2, start, s1, s2, yincr;
1938
int q, mask, k, align, lines;
1941
/* Here there are two more parameters: mask and lines, that
1942
* for color cartridges are both dependent on vertical
1943
* resolution. Since the buffer is "rolling", i.e. it is
1944
* implemented as a circular array, all the coordinates of
1945
* the buffer lines must be taken modulo the buffer length.
1946
* We choose a buffer length that is a power of two to be
1947
* able to turn the modulo operation into a bitwise AND, so
1948
* we need to set "mask" to the correct value for the AND.
1949
* Another difference is that "lines", i.e. the number of
1950
* lines to print in each pass, is based on the height of a
1951
* color pen. Since there are three color pens in each cartridge,
1952
* each color pen is treated separately to fully cover the
1955
switch(gendata.yres)
1976
s1 = (gendata.ileave ? 1 : 0);
1977
s2 = (gendata.ileave ? 3 : 2);
1983
/* Choose the vertical alignment depending on the head.
1984
* This is needed to vertically align the color cartridge
1985
* with the photo or black cartridge.
1988
align = valign[PHOTOVALIGN];
1990
align = valign[COLORVALIGN];
1992
/* All the stuff below is exactly the same as in
1993
* encode_bw_buf(), and is therefore commented there.
1996
csep = (gendata.bwsep * 2) / gendata.xrmul;
1997
nxp = gendata.numpasses;
1998
if(gendata.xres == 1200)nxp /= 2;
2000
dy = (gendata.numlines / 8) + 4;
2003
if(gendata.direction == LEFT)
2005
left = gendata.left - 2*csep;
2006
right = gendata.right + csep;
2010
left = gendata.left - csep;
2011
right = gendata.right + 2*csep;
2014
numcols = right - left;
2015
mod = numcols - (numcols % nxp);
2019
if(gendata.yres == 300)
2025
/* For all passes */
2026
for(pass = 0; pass < gendata.numpasses; pass++)
2028
/* If there is data in the buffer which has not been
2029
* sent to the printer yet, do it now.
2031
if(gendata.fullflag)
2033
fwrite(gendata.header, 3, 8, gendata.stream);
2034
fwrite(gendata.outdata, gendata.stripebytes, 1, gendata.stream);
2035
gendata.fullflag = FALSE;
2038
/* All the stuff below is exactly the same as in
2039
* encode_bw_buf(), and is therefore commented there.
2042
memset(gendata.outdata, 0, gendata.numbytes * 30);
2045
start = left + pass;
2046
data = gendata.outdata + (pass*dy) + 4;
2048
if(gendata.xres == 1200)
2053
start = left + (pass/2);
2054
data = gendata.outdata + ((pass/2)*dy) + 4;
2057
if(gendata.direction == RIGHT)
2063
/* Start column scanning */
2066
if(gendata.direction == LEFT)
2068
/* For all the columns */
2069
for(nn = 0; nn < numcols; nn += nxp)
2071
/* Encode the even numbered nozzles */
2074
scan = gendata.scanbuf + x;
2077
/* In color printing there is one more loop to scan
2078
* all three color pens. We have to do exactly the
2079
* same things for all pens: the only differences are
2080
* the color encoding bit we are testing and the offset
2081
* from the beginning of the buffer and the offset of the
2082
* output data. All of this is stored into arrays. The
2083
* "penofs" array stores the offset of the first line of
2084
* each pen in the raster buffer. The array "colmask" stores
2085
* the encoding bits for the color of each pen, and it
2086
* is bidimensional because pen masks are different between
2087
* a color cartridge (where pens are Cyan, Magenta, Yellow)
2088
* and a photo cartridge (where pens are LightCyan,
2089
* LightMagenta and Black).
2093
q = gendata.firstline + align + penofs[k];
2094
for(y = s1; y < lines; y += yincr)
2096
if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2097
data[yy/8] |= bits[yy&7];
2103
/* Encode the odd numbered nozzles */
2104
if(((x+csep) < gendata.numbytes) && f2)
2106
scan = gendata.scanbuf + x + csep;
2110
q = gendata.firstline + align + penofs[k];
2111
for(y = s2; y < lines; y += yincr)
2113
if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2114
data[yy/8] |= bits[yy&7];
2120
/* If we are in 1200dpi horizontal resolution,
2121
* alternate between nozzle columns to avoid
2122
* overstressing the printing head.
2124
if(gendata.xres == 1200)
2130
/* Adjust data pointers */
2137
/* For all the columns */
2138
for(nn = 0; nn < numcols; nn += nxp)
2140
/* Encode the odd numbered nozzles */
2141
if((x < gendata.numbytes) && f1)
2143
scan = gendata.scanbuf + x;
2147
q = gendata.firstline + align + penofs[k];
2148
for(y = s1; y < lines; y += yincr)
2150
if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2151
data[yy/8] |= bits[yy&7];
2157
/* Encode the even numbered nozzles */
2158
if(((x-csep) >= 0) && f2)
2160
scan = gendata.scanbuf + x - csep;
2164
q = gendata.firstline + align + penofs[k];
2165
for(y = s2; y < lines; y += yincr)
2167
if(scan[((y+q) & mask) * gendata.numbytes] & colmask[head][k])
2168
data[yy/8] |= bits[yy&7];
2174
/* If we are in 1200dpi horizontal resolution,
2175
* alternate between nozzle columns to avoid
2176
* overstressing the printing head.
2178
if(gendata.xres == 1200)
2184
/* Adjust data pointers */
2190
if(gendata.direction == LEFT)
2191
convbuf(head, numcols, left);
2193
convbuf(head, numcols, right);
2200
/* Fill monochrome buffer: this routine fills the buffer
2201
* with rasterized lines, skipping over vertical spacing
2202
* (i.e. completely blank lines). The routine is only
2203
* used in monochrome mode, where we print a full buffer
2204
* at each stripe. The color printing needs a different
2197
/* Fill monochrome buffer: this routine fills the buffer
2198
* with rasterized lines, skipping over vertical spacing
2199
* (i.e. completely blank lines). The routine is only
2200
* used in monochrome mode, where we print a full buffer
2201
* at each stripe. The color printing needs a different
2205
2202
* routine which makes use of a circular buffer.
2207
2204
* vline: the line from which to start searching for data.
2210
2207
fill_mono_buffer(int vline)
2212
byte *in_data, *data;
2215
/* Initialize the "data" pointer, that will be used to
2216
* scan all the lines in the buffer, and the "ofs" pointer
2217
* that will be used to mark the start of the "real" rasterized
2218
* data into the buffer (see below). To compensate for the offsets
2219
* caused by the horizontal spacing between nozzle columns on a
2220
* cartridge, the head must start before the horizontal margin, so
2221
* the buffer width is slightly bigger than the width of the
2222
* rasterized lines. The difference is the "guard offset", and the
2223
* variables gendata.numbytes and gendata.numrbytes hold respectively
2224
* the number of bytes in a buffer line and the number of bytes in a
2225
* rasterized scanline, while gendata.goffset contains the number of
2226
* bytes reserved to the guard offset on each side of the scanline.
2228
data = gendata.scanbuf;
2229
ofs = gendata.goffset;
2231
/* Cycle until we have no more lines on the page */
2232
while(vline < gendata.numvlines)
2234
/* Ask Ghostscript for one rasterized line */
2235
gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2236
vline, data+ofs, &in_data);
2238
/* And check if it's all zero: if not, break out of
2239
* the loop. This nice trick with memcpy it's by Stephen
2240
* Taylor (if I'm not wrong...)
2243
if(in_data[0] != 0 ||
2244
memcmp(in_data, in_data+1,gendata.numrbytes-1))break;
2248
/* If we are here because no non-empty lines were found before
2249
* the end of the page, our work is over. Return to the caller
2250
* saying that this is the last buffer (LAST bit set) and it's
2251
* empty (no LHDATA or RHDATA bit set).
2253
if(vline >= gendata.numvlines)return(LAST);
2255
/* This buffer contains at least one non-empty line.
2256
* Adjust the current vertical position and load the first
2257
* line into the buffer.
2259
gendata.curvline = vline;
2260
memset(data, 0, gendata.numbytes);
2261
if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2264
data += gendata.numbytes;
2266
/* Now initialize the return value to LHDATA (since at least
2267
* one non-blank line was found, this buffer contains data, and
2268
* it is obviously left-head data because we are in monochromatic
2269
* mode and so we are printing with left head only).
2270
* After that, get as many rasterized lines as needed to fill the
2271
* buffer, checking if in the process we have reached the end of
2275
for(i=1; i<gendata.numblines; i++)
2277
memset(data, 0, gendata.numbytes);
2278
if(vline > gendata.numvlines)
2280
/* Ok, we are at the end of the page, so set the LAST bit
2281
* in the return value but don't exit the loop because we
2282
* need to make sure all remaining lines in the buffer will
2283
* be blanked (exiting now would leave them untouched from
2284
* the previous stripe). This is needed to avoid printing
2285
* random data under the bottom margin.
2287
ret = LHDATA | LAST;
2291
/* If we are not at the end of the page, copy one more
2292
* scanline into the buffer.
2294
gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2295
vline, data+ofs, &in_data);
2296
if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2300
data += gendata.numbytes;
2209
byte *in_data, *data;
2212
/* Initialize the "data" pointer, that will be used to
2213
* scan all the lines in the buffer, and the "ofs" pointer
2214
* that will be used to mark the start of the "real" rasterized
2215
* data into the buffer (see below). To compensate for the offsets
2216
* caused by the horizontal spacing between nozzle columns on a
2217
* cartridge, the head must start before the horizontal margin, so
2218
* the buffer width is slightly bigger than the width of the
2219
* rasterized lines. The difference is the "guard offset", and the
2220
* variables gendata.numbytes and gendata.numrbytes hold respectively
2221
* the number of bytes in a buffer line and the number of bytes in a
2222
* rasterized scanline, while gendata.goffset contains the number of
2223
* bytes reserved to the guard offset on each side of the scanline.
2225
data = gendata.scanbuf;
2226
ofs = gendata.goffset;
2228
/* Cycle until we have no more lines on the page */
2229
while(vline < gendata.numvlines)
2231
/* Ask Ghostscript for one rasterized line */
2232
gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2233
vline, data+ofs, &in_data);
2235
/* And check if it's all zero: if not, break out of
2236
* the loop. This nice trick with memcpy it's by Stephen
2237
* Taylor (if I'm not wrong...)
2240
if(in_data[0] != 0 ||
2241
memcmp(in_data, in_data+1,gendata.numrbytes-1))break;
2245
/* If we are here because no non-empty lines were found before
2246
* the end of the page, our work is over. Return to the caller
2247
* saying that this is the last buffer (LAST bit set) and it's
2248
* empty (no LHDATA or RHDATA bit set).
2250
if(vline >= gendata.numvlines)return(LAST);
2252
/* This buffer contains at least one non-empty line.
2253
* Adjust the current vertical position and load the first
2254
* line into the buffer.
2256
gendata.curvline = vline;
2257
memset(data, 0, gendata.numbytes);
2258
if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2261
data += gendata.numbytes;
2263
/* Now initialize the return value to LHDATA (since at least
2264
* one non-blank line was found, this buffer contains data, and
2265
* it is obviously left-head data because we are in monochromatic
2266
* mode and so we are printing with left head only).
2267
* After that, get as many rasterized lines as needed to fill the
2268
* buffer, checking if in the process we have reached the end of
2272
for(i=1; i<gendata.numblines; i++)
2274
memset(data, 0, gendata.numbytes);
2275
if(vline > gendata.numvlines)
2277
/* Ok, we are at the end of the page, so set the LAST bit
2278
* in the return value but don't exit the loop because we
2279
* need to make sure all remaining lines in the buffer will
2280
* be blanked (exiting now would leave them untouched from
2281
* the previous stripe). This is needed to avoid printing
2282
* random data under the bottom margin.
2284
ret = LHDATA | LAST;
2288
/* If we are not at the end of the page, copy one more
2289
* scanline into the buffer.
2291
gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2292
vline, data+ofs, &in_data);
2293
if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2297
data += gendata.numbytes;
2307
2304
/* Fill the buffer with initial data.
2310
2307
* mode, we just call fill_mono_buffer for the first line.
2311
2308
* If we are printing in color mode, we have a problem to
2312
2309
* solve: since the color pen are stacked vertically, we
2313
* need multiple head passes to print all colors on the
2310
* need multiple head passes to print all colors on the
2314
2311
* same line. So, to simplify all, we start with the paper
2315
2312
* at a fixed vertical position, even if it's blank, and
2316
2313
* then we go down in fixed increments, equal to the height
2317
2314
* of a color pen. This means we check all buffers without
2318
2315
* skipping over blank ones, but since we actually send the
2319
2316
* printing commands to the printer only when there is something
2320
* to print, there is no speed impact.
2317
* to print, there is no speed impact.
2323
2320
init_buffer(void)
2325
byte *in_data, *data;
2326
int i, ret, p1, p2, ofs;
2328
data = gendata.scanbuf;
2329
ofs = gendata.goffset;
2331
if(gendata.rendermode == LXM3200_M)return(fill_mono_buffer(0));
2333
/* We position the heads with the bottom color pen (the
2334
* yellow one in the color cartridge and the black one
2335
* in the photo cartridge) just covering the first lines
2336
* of the paper sheet. So the first buffer is divided in
2337
* two parts: "p1" is the number of lines above the top
2338
* border and "p2" the number of lines below.
2340
p1 = 368 / gendata.yrmul;
2341
p2 = 144 / gendata.yrmul;
2343
/* Initialize the counters */
2344
gendata.curvline = -p1;
2345
gendata.lastblack = gendata.curvline - 1;
2346
data = gendata.scanbuf;
2348
/* Clear the lines of the buffer that correspond to
2349
* lines above the top margin: of course we don't
2350
* want to print anything on the air...
2354
memset(data, 0, gendata.numbytes);
2355
data += gendata.numbytes;
2358
/* And now load the last part of the buffer.
2359
* Note that here we don't check for blank lines,
2360
* this will be cared for later.
2364
memset(data, 0, gendata.numbytes);
2366
if(i < gendata.numvlines)
2368
gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2369
i, data+ofs, &in_data);
2370
if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2373
data += gendata.numbytes;
2376
gendata.firstline = 0;
2378
/* Now check the return value. If by chance we are under
2379
* the bottom margin, add the LAST bit to the return value.
2380
* Of course, since this is the first buffer of the page,
2381
* it's not likely we will reach the bottom margin in
2382
* this pass. Anyway this is code that will be executed
2383
* only once per page, so better safe than sorry.
2385
ret = (gendata.numvlines < p2 ? LAST : 0) | qualify_buffer();
2322
byte *in_data, *data;
2323
int i, ret, p1, p2, ofs;
2325
data = gendata.scanbuf;
2326
ofs = gendata.goffset;
2328
if(gendata.rendermode == LXM3200_M)return(fill_mono_buffer(0));
2330
/* We position the heads with the bottom color pen (the
2331
* yellow one in the color cartridge and the black one
2332
* in the photo cartridge) just covering the first lines
2333
* of the paper sheet. So the first buffer is divided in
2334
* two parts: "p1" is the number of lines above the top
2335
* border and "p2" the number of lines below.
2337
p1 = 368 / gendata.yrmul;
2338
p2 = 144 / gendata.yrmul;
2340
/* Initialize the counters */
2341
gendata.curvline = -p1;
2342
gendata.lastblack = gendata.curvline - 1;
2343
data = gendata.scanbuf;
2345
/* Clear the lines of the buffer that correspond to
2346
* lines above the top margin: of course we don't
2347
* want to print anything on the air...
2351
memset(data, 0, gendata.numbytes);
2352
data += gendata.numbytes;
2355
/* And now load the last part of the buffer.
2356
* Note that here we don't check for blank lines,
2357
* this will be cared for later.
2361
memset(data, 0, gendata.numbytes);
2363
if(i < gendata.numvlines)
2365
gdev_prn_get_bits((gx_device_printer *)gendata.dev,
2366
i, data+ofs, &in_data);
2367
if(in_data != data+ofs)memcpy(data+ofs, in_data, gendata.numrbytes);
2370
data += gendata.numbytes;
2373
gendata.firstline = 0;
2375
/* Now check the return value. If by chance we are under
2376
* the bottom margin, add the LAST bit to the return value.
2377
* Of course, since this is the first buffer of the page,
2378
* it's not likely we will reach the bottom margin in
2379
* this pass. Anyway this is code that will be executed
2380
* only once per page, so better safe than sorry.
2382
ret = (gendata.numvlines < p2 ? LAST : 0) | qualify_buffer();
2390
2387
/* This function checks if the current buffer contains
2391
2388
* data to be printed with the left or right head.
2392
2389
* It assumes that we are printing in color mode, and it
2393
2390
* is useful to minimize the number of needed passes.
2394
* When we are printing in monochrome mode we directly skip
2391
* When we are printing in monochrome mode we directly skip
2395
2392
* over blank lines, so this routine is not needed.
2398
2395
qualify_buffer(void)
2407
/* Set variables which contains the size, in rows, of
2408
* each color pen and of the black pen in color mode,
2409
* adjusting for different resolution settings.
2410
* Also set the mask used to rollover the buffer.
2412
cpsz = (COLORPEN * 2) / gendata.yrmul;
2413
bpsz = (BWCOLPEN * 2) / gendata.yrmul;
2414
rmsk = gendata.numblines - 1;
2416
/* Check the right head data, it is always a color cartridge */
2417
for(k=0; k<3 && ret==0; k++)
2419
/* For each pen, scan all the bytes on each row of
2420
* the buffer that is covered by the current pen,
2421
* ORing together all the bits.
2424
q = gendata.firstline + valign[COLORVALIGN] + penofs[k];
2425
for(i=0; i<cpsz; i++)
2427
data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2428
for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2430
/* If the result of the OR has the proper color bit
2431
* set, it means that this buffer contains at least
2432
* one pixel of this pen, so we need a color pass.
2433
* Note that we exit as soon as we find a color bit
2434
* set, because if at least one color pen is used
2435
* in this buffer we need to do a color pass anyway,
2436
* so there's no need to check the other two pens.
2438
if(v1 & colmask[RIGHT][k])ret |= RHDATA;
2441
/* Check the left head data: it could be a black or
2442
* a photo cartridge, depending on the printing mode.
2444
if(gendata.rendermode == LXM3200_C)
2446
/* We are in standard color mode: the left cartridge
2447
* is a black cartridge used in 192 nozzles mode.
2448
* This is done exactly in the same way as above, but
2449
* without the outer loop because we have only one
2450
* color pen on this cartridge.
2453
q = gendata.firstline + valign[BLACKVALIGN];
2454
for(i=0; i<bpsz; i++)
2456
data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2457
for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2459
if(v1 & BLACK)ret |= LHDATA;
2463
/* If we are here we need to check for a photo cartridge
2464
* (this routine is never called in monochrome mode, so
2465
* if we are not in color mode we must be in photo mode).
2466
* This routine is identical to the color routine above.
2468
for(k=0; k<3 && !(ret & LHDATA); k++)
2471
q = gendata.firstline + valign[PHOTOVALIGN] + penofs[k];
2472
for(i=0; i<cpsz; i++)
2474
data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2475
for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2477
if(v1 & colmask[LEFT][k])ret |= LHDATA;
2404
/* Set variables which contains the size, in rows, of
2405
* each color pen and of the black pen in color mode,
2406
* adjusting for different resolution settings.
2407
* Also set the mask used to rollover the buffer.
2409
cpsz = (COLORPEN * 2) / gendata.yrmul;
2410
bpsz = (BWCOLPEN * 2) / gendata.yrmul;
2411
rmsk = gendata.numblines - 1;
2413
/* Check the right head data, it is always a color cartridge */
2414
for(k=0; k<3 && ret==0; k++)
2416
/* For each pen, scan all the bytes on each row of
2417
* the buffer that is covered by the current pen,
2418
* ORing together all the bits.
2421
q = gendata.firstline + valign[COLORVALIGN] + penofs[k];
2422
for(i=0; i<cpsz; i++)
2424
data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2425
for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2427
/* If the result of the OR has the proper color bit
2428
* set, it means that this buffer contains at least
2429
* one pixel of this pen, so we need a color pass.
2430
* Note that we exit as soon as we find a color bit
2431
* set, because if at least one color pen is used
2432
* in this buffer we need to do a color pass anyway,
2433
* so there's no need to check the other two pens.
2435
if(v1 & colmask[RIGHT][k])ret |= RHDATA;
2438
/* Check the left head data: it could be a black or
2439
* a photo cartridge, depending on the printing mode.
2441
if(gendata.rendermode == LXM3200_C)
2443
/* We are in standard color mode: the left cartridge
2444
* is a black cartridge used in 192 nozzles mode.
2445
* This is done exactly in the same way as above, but
2446
* without the outer loop because we have only one
2447
* color pen on this cartridge.
2450
q = gendata.firstline + valign[BLACKVALIGN];
2451
for(i=0; i<bpsz; i++)
2453
data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2454
for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2456
if(v1 & BLACK)ret |= LHDATA;
2460
/* If we are here we need to check for a photo cartridge
2461
* (this routine is never called in monochrome mode, so
2462
* if we are not in color mode we must be in photo mode).
2463
* This routine is identical to the color routine above.
2465
for(k=0; k<3 && !(ret & LHDATA); k++)
2468
q = gendata.firstline + valign[PHOTOVALIGN] + penofs[k];
2469
for(i=0; i<cpsz; i++)
2471
data = gendata.scanbuf + ((q+i) & rmsk)*gendata.numbytes;
2472
for(j=0; j<gendata.numbytes; j++)v1 |= *data++;
2474
if(v1 & colmask[LEFT][k])ret |= LHDATA;
2484
2481
/* This functions rolls the circular buffer by the
2485
2482
* number of lines of one color pen, reading new
2486
2483
* lines to refill the buffer.
2487
* In color mode we use a circular buffer because
2484
* In color mode we use a circular buffer because
2488
2485
* we need to read the same lines more than once.
2489
2486
* So when we are forwarding to the next pass we
2490
2487
* simply read in the new lines and then update the
2575
2572
* left: calculated left margin (output variable)
2576
2573
* right: calculated right margin (output variable)
2579
2576
calclinemargins(byte *data, int mask, int *left, int *right)
2583
num = gendata.numbytes - 1;
2586
while((l <= num) && ((data[l] & mask) == 0))l++;
2589
while((r >= 0) && ((data[r] & mask) == 0))r--;
2580
num = gendata.numbytes - 1;
2583
while((l <= num) && ((data[l] & mask) == 0))l++;
2586
while((r >= 0) && ((data[r] & mask) == 0))r--;
2595
2592
/* Calculate the margins of the whole buffer. The
2596
2593
* calculation accounts separately for the data to
2597
2594
* be printed with the left or with the right head,
2598
* so we can try to minimize the head movement even
2595
* so we can try to minimize the head movement even
2599
2596
* on multiple passes.
2601
2598
* head: the code of the head we are calculating
2602
2599
* margins for (LEFT or RIGHT)
2605
2602
calcbufmargins(int head)
2607
int i, l1, r1, q, k;
2608
int mleft, mright, nl;
2609
int cpen, cmask, al;
2612
/* Adjust mask and pen height according to vertical resolution */
2613
cpen = (COLORPEN * 2) / gendata.yrmul;
2614
cmask = (gendata.numblines) - 1;
2616
/* Calculate margins for a color or photo cartridge */
2617
if(head == RIGHT || (gendata.rendermode == LXM3200_P))
2619
/* Get correct vertical aligment */
2620
al = (head == LEFT ? PHOTOVALIGN : COLORVALIGN);
2622
q = gendata.firstline + valign[al];
2624
/* Calculate margins for first line, using those values
2625
* to initialize the max and min values.
2627
scan = gendata.scanbuf + ((q+penofs[0]) & cmask)*gendata.numbytes;
2628
calclinemargins(scan, colmask[head][0], &mleft, &mright);
2630
/* And now scan all the remaining buffer. We scan according
2631
* to color pens, i.e. we calculate the margin on the rows
2632
* where magenta will be laid down taking into account magenta
2633
* pixels only, and this will be the magenta submargin. After
2634
* having done that for cyan and yellow as well, we take as the
2635
* global margin the smaller space that contains all the three
2640
for(i=0; i<cpen; i++)
2642
scan = gendata.scanbuf + ((q+i+penofs[k]) & cmask)*gendata.numbytes;
2643
calclinemargins(scan, colmask[head][k], &l1, &r1);
2644
mleft = min(mleft, l1);
2645
mright = max(mright, r1);
2649
gendata.left = mleft;
2650
gendata.right = mright;
2655
/* Calculate buffer margins for a black head. This is
2656
* almost exactly the same as before, but now we do
2657
* a single pass because we have only one black pen.
2659
if(gendata.rendermode == LXM3200_M)
2661
/* Monochromatic mode: we use 208 nozzles and
2662
* all the buffer, so the initial offset is zero.
2665
scan = gendata.scanbuf;
2666
calclinemargins(scan, BLACK, &mleft, &mright);
2668
for(i=1; i<gendata.numblines; i++)
2670
scan += gendata.numbytes;
2671
calclinemargins(scan, BLACK, &l1, &r1);
2672
mleft = min(mleft, l1);
2673
mright = max(mright, r1);
2676
gendata.left = mleft;
2677
gendata.right = mright;
2682
/* Standard color mode: we use 192 nozzles and must
2683
* take into account the vertical alignment.
2686
nl = (gendata.numlines * 2) / gendata.yrmul;
2687
q = gendata.firstline + valign[BLACKVALIGN];
2689
scan = gendata.scanbuf + (q & cmask)*gendata.numbytes;
2690
calclinemargins(scan, BLACK, &mleft, &mright);
2694
scan = gendata.scanbuf + ((q+i) & cmask)*gendata.numbytes;
2695
calclinemargins(scan, BLACK, &l1, &r1);
2696
mleft = min(mleft, l1);
2697
mright = max(mright, r1);
2699
gendata.left = mleft;
2700
gendata.right = mright;
2604
int i, l1, r1, q, k;
2605
int mleft, mright, nl;
2606
int cpen, cmask, al;
2609
/* Adjust mask and pen height according to vertical resolution */
2610
cpen = (COLORPEN * 2) / gendata.yrmul;
2611
cmask = (gendata.numblines) - 1;
2613
/* Calculate margins for a color or photo cartridge */
2614
if(head == RIGHT || (gendata.rendermode == LXM3200_P))
2616
/* Get correct vertical aligment */
2617
al = (head == LEFT ? PHOTOVALIGN : COLORVALIGN);
2619
q = gendata.firstline + valign[al];
2621
/* Calculate margins for first line, using those values
2622
* to initialize the max and min values.
2624
scan = gendata.scanbuf + ((q+penofs[0]) & cmask)*gendata.numbytes;
2625
calclinemargins(scan, colmask[head][0], &mleft, &mright);
2627
/* And now scan all the remaining buffer. We scan according
2628
* to color pens, i.e. we calculate the margin on the rows
2629
* where magenta will be laid down taking into account magenta
2630
* pixels only, and this will be the magenta submargin. After
2631
* having done that for cyan and yellow as well, we take as the
2632
* global margin the smaller space that contains all the three
2637
for(i=0; i<cpen; i++)
2639
scan = gendata.scanbuf + ((q+i+penofs[k]) & cmask)*gendata.numbytes;
2640
calclinemargins(scan, colmask[head][k], &l1, &r1);
2641
mleft = min(mleft, l1);
2642
mright = max(mright, r1);
2646
gendata.left = mleft;
2647
gendata.right = mright;
2652
/* Calculate buffer margins for a black head. This is
2653
* almost exactly the same as before, but now we do
2654
* a single pass because we have only one black pen.
2656
if(gendata.rendermode == LXM3200_M)
2658
/* Monochromatic mode: we use 208 nozzles and
2659
* all the buffer, so the initial offset is zero.
2662
scan = gendata.scanbuf;
2663
calclinemargins(scan, BLACK, &mleft, &mright);
2665
for(i=1; i<gendata.numblines; i++)
2667
scan += gendata.numbytes;
2668
calclinemargins(scan, BLACK, &l1, &r1);
2669
mleft = min(mleft, l1);
2670
mright = max(mright, r1);
2673
gendata.left = mleft;
2674
gendata.right = mright;
2679
/* Standard color mode: we use 192 nozzles and must
2680
* take into account the vertical alignment.
2683
nl = (gendata.numlines * 2) / gendata.yrmul;
2684
q = gendata.firstline + valign[BLACKVALIGN];
2686
scan = gendata.scanbuf + (q & cmask)*gendata.numbytes;
2687
calclinemargins(scan, BLACK, &mleft, &mright);
2691
scan = gendata.scanbuf + ((q+i) & cmask)*gendata.numbytes;
2692
calclinemargins(scan, BLACK, &l1, &r1);
2693
mleft = min(mleft, l1);
2694
mright = max(mright, r1);
2696
gendata.left = mleft;
2697
gendata.right = mright;
2708
2705
print_color_page(void)
2710
int res, lline, cmask;
2711
int i, j, nl, q, sk;
2714
/* Set the blackskip value depending on vertical resolution.
2715
* Since we have a black pen which is 3 times as high as
2716
* each color pen, we must print black only once every three
2717
* passes. So we take into account on which line we printed
2718
* the last black stripe and then we print another only if
2719
* the current line is at least "sk" lines after that.
2721
sk = (BWCOLPEN * 2) / gendata.yrmul;
2723
/* Get the first buffer, and if it's empty continue
2724
* to skip forward without doing anything.
2726
res = init_buffer();
2727
while(res == 0)res = roll_buffer();
2729
/* If this buffer happens to be the last one,
2730
* and empty as well, we had a blank page.
2731
* Just exit without ado.
2733
if(res == LAST)return;
2735
/* This is the first non-blank line of the
2736
* page: issue a vertical skip command to
2737
* advance the paper to proper position.
2739
skiplines(gendata.curvline, COLTOPSTART);
2741
/* "lline" holds the number of the first line of
2742
* the last buffer printed, either with left or
2743
* right head. This is needed to keep track of
2744
* how many lines we must skip from one stripe to
2745
* the next (if we encounter blank buffers we just
2746
* ignore them without moving the head, so we need
2747
* to do the proper vertical motion in one single
2748
* pass as soon as we encounter a non-blank buffer).
2750
lline = gendata.curvline;
2752
/* Now depending on the data we have into the
2753
* buffer, print with the left head, right
2755
* NOTE: this is the first buffer, and it needs
2756
* to be treated specially from the others.
2757
* The main difference is that we usually finalize
2758
* the buffer (issuing the print commands) at the
2759
* start of the next buffer, and not at the end of
2760
* the current one. This is because the Lexmark 3200
2761
* wants to know where to leave the printing head
2762
* at the end of each printing command, but we can't
2763
* know that until we start the next buffer so discovering
2764
* its margins and position. The solution is that we keep
2765
* "suspended" each buffer until we find another valid one.
2766
* The first buffer is special since there is no previous
2767
* buffer to finalize.
2768
* NOTE: I will comment the general case below, because
2769
* this code is simply a subset of the main loop.
2774
calcbufmargins(LEFT);
2777
gendata.lastblack = gendata.curvline + sk;
2778
lline = gendata.curvline;
2779
if(gendata.yres == 1200)
2781
finalizeheader(1, LEFT);
2789
calcbufmargins(RIGHT);
2791
encode_col_buf(RIGHT);
2792
lline = gendata.curvline;
2793
if(gendata.yres == 1200)
2795
finalizeheader(1, RIGHT);
2797
encode_col_buf(RIGHT);
2803
calcbufmargins(LEFT);
2806
gendata.lastblack = gendata.curvline + sk;
2807
calcbufmargins(RIGHT);
2808
finalizeheader(0, RIGHT);
2809
encode_col_buf(RIGHT);
2810
lline = gendata.curvline;
2811
if(gendata.yres == 1200)
2813
calcbufmargins(LEFT);
2814
finalizeheader(1, LEFT);
2817
calcbufmargins(RIGHT);
2818
finalizeheader(0, RIGHT);
2819
encode_col_buf(RIGHT);
2825
/* Skip to next buffer */
2826
res = roll_buffer();
2828
/* Start the main loop. Here we do all the stuff required
2829
* to print buffers properly.
2831
while(!(res & LAST))
2833
/* If we haven't forwarded until "lastblack", do not
2834
* print black data because it has been printed on
2835
* previous passes. So, if we are below gendata.lastblack
2836
* clear the LHDATA flag to ignore left-head data.
2838
if(gendata.curvline < gendata.lastblack)res &= ~LHDATA;
2840
/* And now start examining the buffer for data */
2843
/* We have left head data */
2846
/* Calculate the margins of this buffer */
2847
calcbufmargins(LEFT);
2849
/* And then finalize the previous buffer. We can't
2850
* do this until now, because only now we know the
2851
* margins and vertical position of the next buffer,
2852
* which are required data to calculate the final
2853
* head position at the end of the previous buffer.
2855
finalizeheader(gendata.curvline - lline, LEFT);
2857
/* Set interleave to zero (only meaningful in 1200dpi
2862
/* Encode this buffer making it the current buffer */
2865
/* Since we are printing a black buffer, update
2866
* gendata.lastblack to point to the first line
2867
* not covered by this black pass.
2869
gendata.lastblack = gendata.curvline + sk;
2871
/* And update "lline" as well */
2872
lline = gendata.curvline;
2874
/* If we are printing at 1200 dpi vertical, we must
2875
* do one more pass, interleaved with the one before.
2877
if(gendata.yres == 1200)
2879
/* Finalize previous buffer, moving down 1/1200th
2880
* of an inch to properly interleave the two passes.
2881
* This is naive: we should do something here, because
2882
* this way two adjacent lines are printed by the same
2883
* nozzle, and there is the danger of having a slight
2884
* banding on output (no more than 1/600th of an inch,
2885
* but maybe noticeable).
2887
finalizeheader(1, LEFT);
2889
/* Set interleave to 1 to start an interleaved pass */
2892
/* Encode the buffer, and not finalize it: we leave
2893
* the buffer suspended until we find another buffer
2898
/* And adjust "lline" because to print the interleaved
2899
* pass we have moved down one line, so we need to
2900
* skip one line less to print the next buffer.
2906
/* Right head data. This is absolutely identical to the
2907
* code above for left head data, with two exceptions: all
2908
* the "LEFT" codes are changed to "RIGHT" and we don't
2909
* update gendata.lastblack because we are printing a
2910
* color stripe and not a black one.
2913
calcbufmargins(RIGHT);
2914
finalizeheader(gendata.curvline - lline, RIGHT);
2916
encode_col_buf(RIGHT);
2917
lline = gendata.curvline;
2918
if(gendata.yres == 1200)
2920
finalizeheader(1, RIGHT);
2922
encode_col_buf(RIGHT);
2927
/* We have both left and right head data (i.e. black and
2928
* color on the same stripe).
2929
* The code here is identical to the code for the left data
2930
* only and right data only cases above. But they are
2931
* interleaved, because since we can't take back the paper
2932
* once it's advanced, in case we are printing at 1200 dpi
2933
* vertical (and so we need two interlaced passes) we need
2934
* to do both the first black and the first color pass,
2935
* advance the paper and then do the second black and the
2936
* second color pass. Simply appendig the two code pieces
2937
* above would not work.
2940
calcbufmargins(LEFT);
2941
finalizeheader(gendata.curvline - lline, LEFT);
2944
gendata.lastblack = gendata.curvline + sk;
2945
calcbufmargins(RIGHT);
2946
finalizeheader(0, RIGHT);
2947
encode_col_buf(RIGHT);
2948
lline = gendata.curvline;
2949
if(gendata.yres == 1200)
2951
calcbufmargins(LEFT);
2952
finalizeheader(1, LEFT);
2955
calcbufmargins(RIGHT);
2956
finalizeheader(0, RIGHT);
2957
encode_col_buf(RIGHT);
2963
/* Get another buffer */
2964
res = roll_buffer();
2967
/* Last buffer. We treat this one specially as well,
2968
* because we don't have a subsequent buffer to print,
2969
* and so we need to finalize this buffers as soon as
2972
res = qualify_buffer();
2974
/* Void the printed blacks. Since we are printing the
2975
* last buffer, it could happen that we have advanced
2976
* from the last time we printed a black stripe but
2977
* we are not yet at the point where another black
2978
* stripe would have been triggered. This would cause
2979
* an eventual black component in the last lines of
2980
* the page to be ignored.
2981
* To avoid the problem we do an unconditional black
2982
* pass, but we also must clear the black bits from the
2983
* lines we have already printed otherwise we would
2986
if((res & LHDATA) && (gendata.curvline <= gendata.lastblack))
2988
/* Find how many black lines we have yet printed
2989
* are still in the buffer
2991
nl = gendata.lastblack - gendata.curvline;
2993
/* And now remove the BLACK bit from them */
2995
q = gendata.firstline + valign[BLACKVALIGN];
2996
cmask = (gendata.numblines) - 1;
2999
scan = gendata.scanbuf + ((i+q) & cmask)*gendata.numbytes;
3000
for(j=0; j<gendata.numbytes; j++)
3008
/* Now we can print the last buffer as usual.
3009
* This is perfectly identical to the code
3010
* into the loop above: we are replicating it
3011
* only because we need the blanking code above
3012
* to be executed before this code.
3013
* Maybe there is a better way to do it...
3018
calcbufmargins(LEFT);
3019
finalizeheader(gendata.curvline - lline, LEFT);
3022
if(gendata.yres == 1200)
3024
finalizeheader(1, LEFT);
3032
calcbufmargins(RIGHT);
3033
finalizeheader(gendata.curvline - lline, RIGHT);
3035
encode_col_buf(RIGHT);
3036
if(gendata.yres == 1200)
3038
finalizeheader(1, RIGHT);
3040
encode_col_buf(RIGHT);
3046
calcbufmargins(LEFT);
3047
finalizeheader(gendata.curvline - lline, LEFT);
3050
calcbufmargins(RIGHT);
3051
finalizeheader(0, RIGHT);
3052
encode_col_buf(RIGHT);
3053
if(gendata.yres == 1200)
3055
calcbufmargins(LEFT);
3056
finalizeheader(1, LEFT);
3059
calcbufmargins(RIGHT);
3060
finalizeheader(0, RIGHT);
3061
encode_col_buf(RIGHT);
3067
/* Now finalize the header using a value of "0" for
3068
* the vertical skip (no need to move down: the
3069
* paper is about to be ejected) and -1 for the
3070
* head (meaning: last buffer, don't care for the
3071
* final head position, it will be reset unconditionally
3072
* by the trailing sequence).
3074
finalizeheader(0, -1);
2707
int res, lline, cmask;
2708
int i, j, nl, q, sk;
2711
/* Set the blackskip value depending on vertical resolution.
2712
* Since we have a black pen which is 3 times as high as
2713
* each color pen, we must print black only once every three
2714
* passes. So we take into account on which line we printed
2715
* the last black stripe and then we print another only if
2716
* the current line is at least "sk" lines after that.
2718
sk = (BWCOLPEN * 2) / gendata.yrmul;
2720
/* Get the first buffer, and if it's empty continue
2721
* to skip forward without doing anything.
2723
res = init_buffer();
2724
while(res == 0)res = roll_buffer();
2726
/* If this buffer happens to be the last one,
2727
* and empty as well, we had a blank page.
2728
* Just exit without ado.
2730
if(res == LAST)return;
2732
/* This is the first non-blank line of the
2733
* page: issue a vertical skip command to
2734
* advance the paper to proper position.
2736
skiplines(gendata.curvline, COLTOPSTART);
2738
/* "lline" holds the number of the first line of
2739
* the last buffer printed, either with left or
2740
* right head. This is needed to keep track of
2741
* how many lines we must skip from one stripe to
2742
* the next (if we encounter blank buffers we just
2743
* ignore them without moving the head, so we need
2744
* to do the proper vertical motion in one single
2745
* pass as soon as we encounter a non-blank buffer).
2747
lline = gendata.curvline;
2749
/* Now depending on the data we have into the
2750
* buffer, print with the left head, right
2752
* NOTE: this is the first buffer, and it needs
2753
* to be treated specially from the others.
2754
* The main difference is that we usually finalize
2755
* the buffer (issuing the print commands) at the
2756
* start of the next buffer, and not at the end of
2757
* the current one. This is because the Lexmark 3200
2758
* wants to know where to leave the printing head
2759
* at the end of each printing command, but we can't
2760
* know that until we start the next buffer so discovering
2761
* its margins and position. The solution is that we keep
2762
* "suspended" each buffer until we find another valid one.
2763
* The first buffer is special since there is no previous
2764
* buffer to finalize.
2765
* NOTE: I will comment the general case below, because
2766
* this code is simply a subset of the main loop.
2771
calcbufmargins(LEFT);
2774
gendata.lastblack = gendata.curvline + sk;
2775
lline = gendata.curvline;
2776
if(gendata.yres == 1200)
2778
finalizeheader(1, LEFT);
2786
calcbufmargins(RIGHT);
2788
encode_col_buf(RIGHT);
2789
lline = gendata.curvline;
2790
if(gendata.yres == 1200)
2792
finalizeheader(1, RIGHT);
2794
encode_col_buf(RIGHT);
2800
calcbufmargins(LEFT);
2803
gendata.lastblack = gendata.curvline + sk;
2804
calcbufmargins(RIGHT);
2805
finalizeheader(0, RIGHT);
2806
encode_col_buf(RIGHT);
2807
lline = gendata.curvline;
2808
if(gendata.yres == 1200)
2810
calcbufmargins(LEFT);
2811
finalizeheader(1, LEFT);
2814
calcbufmargins(RIGHT);
2815
finalizeheader(0, RIGHT);
2816
encode_col_buf(RIGHT);
2822
/* Skip to next buffer */
2823
res = roll_buffer();
2825
/* Start the main loop. Here we do all the stuff required
2826
* to print buffers properly.
2828
while(!(res & LAST))
2830
/* If we haven't forwarded until "lastblack", do not
2831
* print black data because it has been printed on
2832
* previous passes. So, if we are below gendata.lastblack
2833
* clear the LHDATA flag to ignore left-head data.
2835
if(gendata.curvline < gendata.lastblack)res &= ~LHDATA;
2837
/* And now start examining the buffer for data */
2840
/* We have left head data */
2843
/* Calculate the margins of this buffer */
2844
calcbufmargins(LEFT);
2846
/* And then finalize the previous buffer. We can't
2847
* do this until now, because only now we know the
2848
* margins and vertical position of the next buffer,
2849
* which are required data to calculate the final
2850
* head position at the end of the previous buffer.
2852
finalizeheader(gendata.curvline - lline, LEFT);
2854
/* Set interleave to zero (only meaningful in 1200dpi
2859
/* Encode this buffer making it the current buffer */
2862
/* Since we are printing a black buffer, update
2863
* gendata.lastblack to point to the first line
2864
* not covered by this black pass.
2866
gendata.lastblack = gendata.curvline + sk;
2868
/* And update "lline" as well */
2869
lline = gendata.curvline;
2871
/* If we are printing at 1200 dpi vertical, we must
2872
* do one more pass, interleaved with the one before.
2874
if(gendata.yres == 1200)
2876
/* Finalize previous buffer, moving down 1/1200th
2877
* of an inch to properly interleave the two passes.
2878
* This is naive: we should do something here, because
2879
* this way two adjacent lines are printed by the same
2880
* nozzle, and there is the danger of having a slight
2881
* banding on output (no more than 1/600th of an inch,
2882
* but maybe noticeable).
2884
finalizeheader(1, LEFT);
2886
/* Set interleave to 1 to start an interleaved pass */
2889
/* Encode the buffer, and not finalize it: we leave
2890
* the buffer suspended until we find another buffer
2895
/* And adjust "lline" because to print the interleaved
2896
* pass we have moved down one line, so we need to
2897
* skip one line less to print the next buffer.
2903
/* Right head data. This is absolutely identical to the
2904
* code above for left head data, with two exceptions: all
2905
* the "LEFT" codes are changed to "RIGHT" and we don't
2906
* update gendata.lastblack because we are printing a
2907
* color stripe and not a black one.
2910
calcbufmargins(RIGHT);
2911
finalizeheader(gendata.curvline - lline, RIGHT);
2913
encode_col_buf(RIGHT);
2914
lline = gendata.curvline;
2915
if(gendata.yres == 1200)
2917
finalizeheader(1, RIGHT);
2919
encode_col_buf(RIGHT);
2924
/* We have both left and right head data (i.e. black and
2925
* color on the same stripe).
2926
* The code here is identical to the code for the left data
2927
* only and right data only cases above. But they are
2928
* interleaved, because since we can't take back the paper
2929
* once it's advanced, in case we are printing at 1200 dpi
2930
* vertical (and so we need two interlaced passes) we need
2931
* to do both the first black and the first color pass,
2932
* advance the paper and then do the second black and the
2933
* second color pass. Simply appendig the two code pieces
2934
* above would not work.
2937
calcbufmargins(LEFT);
2938
finalizeheader(gendata.curvline - lline, LEFT);
2941
gendata.lastblack = gendata.curvline + sk;
2942
calcbufmargins(RIGHT);
2943
finalizeheader(0, RIGHT);
2944
encode_col_buf(RIGHT);
2945
lline = gendata.curvline;
2946
if(gendata.yres == 1200)
2948
calcbufmargins(LEFT);
2949
finalizeheader(1, LEFT);
2952
calcbufmargins(RIGHT);
2953
finalizeheader(0, RIGHT);
2954
encode_col_buf(RIGHT);
2960
/* Get another buffer */
2961
res = roll_buffer();
2964
/* Last buffer. We treat this one specially as well,
2965
* because we don't have a subsequent buffer to print,
2966
* and so we need to finalize this buffers as soon as
2969
res = qualify_buffer();
2971
/* Void the printed blacks. Since we are printing the
2972
* last buffer, it could happen that we have advanced
2973
* from the last time we printed a black stripe but
2974
* we are not yet at the point where another black
2975
* stripe would have been triggered. This would cause
2976
* an eventual black component in the last lines of
2977
* the page to be ignored.
2978
* To avoid the problem we do an unconditional black
2979
* pass, but we also must clear the black bits from the
2980
* lines we have already printed otherwise we would
2983
if((res & LHDATA) && (gendata.curvline <= gendata.lastblack))
2985
/* Find how many black lines we have yet printed
2986
* are still in the buffer
2988
nl = gendata.lastblack - gendata.curvline;
2990
/* And now remove the BLACK bit from them */
2992
q = gendata.firstline + valign[BLACKVALIGN];
2993
cmask = (gendata.numblines) - 1;
2996
scan = gendata.scanbuf + ((i+q) & cmask)*gendata.numbytes;
2997
for(j=0; j<gendata.numbytes; j++)
3005
/* Now we can print the last buffer as usual.
3006
* This is perfectly identical to the code
3007
* into the loop above: we are replicating it
3008
* only because we need the blanking code above
3009
* to be executed before this code.
3010
* Maybe there is a better way to do it...
3015
calcbufmargins(LEFT);
3016
finalizeheader(gendata.curvline - lline, LEFT);
3019
if(gendata.yres == 1200)
3021
finalizeheader(1, LEFT);
3029
calcbufmargins(RIGHT);
3030
finalizeheader(gendata.curvline - lline, RIGHT);
3032
encode_col_buf(RIGHT);
3033
if(gendata.yres == 1200)
3035
finalizeheader(1, RIGHT);
3037
encode_col_buf(RIGHT);
3043
calcbufmargins(LEFT);
3044
finalizeheader(gendata.curvline - lline, LEFT);
3047
calcbufmargins(RIGHT);
3048
finalizeheader(0, RIGHT);
3049
encode_col_buf(RIGHT);
3050
if(gendata.yres == 1200)
3052
calcbufmargins(LEFT);
3053
finalizeheader(1, LEFT);
3056
calcbufmargins(RIGHT);
3057
finalizeheader(0, RIGHT);
3058
encode_col_buf(RIGHT);
3064
/* Now finalize the header using a value of "0" for
3065
* the vertical skip (no need to move down: the
3066
* paper is about to be ejected) and -1 for the
3067
* head (meaning: last buffer, don't care for the
3068
* final head position, it will be reset unconditionally
3069
* by the trailing sequence).
3071
finalizeheader(0, -1);
3077
/* This is the equivalent of print_color_page()
3074
/* This is the equivalent of print_color_page()
3078
3075
* for monochrome output. It is almost identical,
3079
3076
* only much simpler because now we are printing
3080
3077
* with only one head.
3083
3080
print_mono_page(void)
3087
/* Load the first buffer, skipping over
3088
* blank lines (if any).
3090
res = init_buffer();
3092
/* If we happen to have a buffer which is LAST
3093
* and empty, we have a blank page to print:
3096
if(res == LAST)return;
3098
/* Skip enough lines to reach the start of
3099
* the first stripe to print.
3101
skiplines(gendata.curvline, BWTOPSTART);
3102
lline = gendata.curvline;
3104
/* And now print the first buffer. This part of
3105
* the code is identical to the LHDATA part in
3106
* print_color_page()
3108
calcbufmargins(LEFT);
3111
lline = gendata.curvline;
3112
if(gendata.yres == 1200)
3114
finalizeheader(1, LEFT);
3120
/* And now load another buffer, starting to
3121
* look for it from the first line after the
3122
* pass we have just done.
3124
res = fill_mono_buffer(gendata.curvline + gendata.numblines);
3126
/* Now loop. Even this code is identical
3127
* to the code above: the only difference
3128
* is that here we also finalize the previous
3129
* buffer before encoding this one. No need
3130
* to check if the buffer is empty because
3131
* a buffer is reported only if it's full
3132
* or if it is the last one, so if it's not
3133
* the last it must be full.
3135
while(!(res & LAST))
3137
calcbufmargins(LEFT);
3138
finalizeheader(gendata.curvline - lline, LEFT);
3141
lline = gendata.curvline;
3142
if(gendata.yres == 1200)
3144
finalizeheader(1, LEFT);
3150
/* Get another buffer, and so on */
3151
res = fill_mono_buffer(gendata.curvline + gendata.numblines);
3154
/* Last buffer. This can be either empty or full.
3155
* If it's not empty (LHDATA bit set), print it.
3159
calcbufmargins(LEFT);
3160
finalizeheader(gendata.curvline - lline, LEFT);
3162
if(gendata.yres == 1200)
3164
finalizeheader(1, LEFT);
3171
/* Finalize the last buffer */
3172
finalizeheader(0, -1);
3084
/* Load the first buffer, skipping over
3085
* blank lines (if any).
3087
res = init_buffer();
3089
/* If we happen to have a buffer which is LAST
3090
* and empty, we have a blank page to print:
3093
if(res == LAST)return;
3095
/* Skip enough lines to reach the start of
3096
* the first stripe to print.
3098
skiplines(gendata.curvline, BWTOPSTART);
3099
lline = gendata.curvline;
3101
/* And now print the first buffer. This part of
3102
* the code is identical to the LHDATA part in
3103
* print_color_page()
3105
calcbufmargins(LEFT);
3108
lline = gendata.curvline;
3109
if(gendata.yres == 1200)
3111
finalizeheader(1, LEFT);
3117
/* And now load another buffer, starting to
3118
* look for it from the first line after the
3119
* pass we have just done.
3121
res = fill_mono_buffer(gendata.curvline + gendata.numblines);
3123
/* Now loop. Even this code is identical
3124
* to the code above: the only difference
3125
* is that here we also finalize the previous
3126
* buffer before encoding this one. No need
3127
* to check if the buffer is empty because
3128
* a buffer is reported only if it's full
3129
* or if it is the last one, so if it's not
3130
* the last it must be full.
3132
while(!(res & LAST))
3134
calcbufmargins(LEFT);
3135
finalizeheader(gendata.curvline - lline, LEFT);
3138
lline = gendata.curvline;
3139
if(gendata.yres == 1200)
3141
finalizeheader(1, LEFT);
3147
/* Get another buffer, and so on */
3148
res = fill_mono_buffer(gendata.curvline + gendata.numblines);
3151
/* Last buffer. This can be either empty or full.
3152
* If it's not empty (LHDATA bit set), print it.
3156
calcbufmargins(LEFT);
3157
finalizeheader(gendata.curvline - lline, LEFT);
3159
if(gendata.yres == 1200)
3161
finalizeheader(1, LEFT);
3168
/* Finalize the last buffer */
3169
finalizeheader(0, -1);
3175
/* This is the equivalent of print_color_page()
3172
/* This is the equivalent of print_color_page()
3176
3173
* for photoquality output. They are almost identical,
3177
3174
* the only real difference is that we now are
3178
3175
* printing with two identical heads, so there is
3179
3176
* no need to care for different heights of the
3180
3177
* printing pens (i.e.: no "lastblack" tricks).
3183
3180
print_photo_page(void)
3187
res = init_buffer();
3188
while(res == 0)res = roll_buffer();
3190
if(res == LAST)return;
3192
skiplines(gendata.curvline, COLTOPSTART);
3193
lline = gendata.curvline;
3198
calcbufmargins(LEFT);
3200
encode_col_buf(LEFT);
3201
lline = gendata.curvline;
3202
if(gendata.yres == 1200)
3204
finalizeheader(1, LEFT);
3206
encode_col_buf(LEFT);
3212
calcbufmargins(RIGHT);
3214
encode_col_buf(RIGHT);
3215
lline = gendata.curvline;
3216
if(gendata.yres == 1200)
3218
finalizeheader(1, RIGHT);
3220
encode_col_buf(RIGHT);
3226
calcbufmargins(LEFT);
3228
encode_col_buf(LEFT);
3229
calcbufmargins(RIGHT);
3230
finalizeheader(0, RIGHT);
3231
encode_col_buf(RIGHT);
3232
lline = gendata.curvline;
3233
if(gendata.yres == 1200)
3235
calcbufmargins(LEFT);
3236
finalizeheader(1, LEFT);
3238
encode_col_buf(LEFT);
3239
calcbufmargins(RIGHT);
3240
finalizeheader(0, RIGHT);
3241
encode_col_buf(RIGHT);
3248
res = roll_buffer();
3250
while(!(res & LAST))
3255
calcbufmargins(LEFT);
3256
finalizeheader(gendata.curvline - lline, LEFT);
3258
encode_col_buf(LEFT);
3259
lline = gendata.curvline;
3260
if(gendata.yres == 1200)
3262
finalizeheader(1, LEFT);
3264
encode_col_buf(LEFT);
3270
calcbufmargins(RIGHT);
3271
finalizeheader(gendata.curvline - lline, RIGHT);
3273
encode_col_buf(RIGHT);
3274
lline = gendata.curvline;
3275
if(gendata.yres == 1200)
3277
finalizeheader(1, RIGHT);
3279
encode_col_buf(RIGHT);
3285
calcbufmargins(LEFT);
3286
finalizeheader(gendata.curvline - lline, LEFT);
3288
encode_col_buf(LEFT);
3289
calcbufmargins(RIGHT);
3290
finalizeheader(0, RIGHT);
3291
encode_col_buf(RIGHT);
3292
lline = gendata.curvline;
3293
if(gendata.yres == 1200)
3295
calcbufmargins(LEFT);
3296
finalizeheader(1, LEFT);
3298
encode_col_buf(LEFT);
3299
calcbufmargins(RIGHT);
3300
finalizeheader(0, RIGHT);
3301
encode_col_buf(RIGHT);
3307
res = roll_buffer();
3313
calcbufmargins(LEFT);
3314
finalizeheader(gendata.curvline - lline, LEFT);
3316
encode_col_buf(LEFT);
3317
if(gendata.yres == 1200)
3319
finalizeheader(1, LEFT);
3321
encode_col_buf(LEFT);
3326
calcbufmargins(RIGHT);
3327
finalizeheader(gendata.curvline - lline, RIGHT);
3329
encode_col_buf(RIGHT);
3330
if(gendata.yres == 1200)
3332
finalizeheader(1, RIGHT);
3334
encode_col_buf(RIGHT);
3340
calcbufmargins(LEFT);
3341
finalizeheader(gendata.curvline - lline, LEFT);
3343
encode_col_buf(LEFT);
3344
calcbufmargins(RIGHT);
3345
finalizeheader(0, RIGHT);
3346
encode_col_buf(RIGHT);
3347
if(gendata.yres == 1200)
3349
calcbufmargins(LEFT);
3350
finalizeheader(1, LEFT);
3352
encode_col_buf(LEFT);
3353
calcbufmargins(RIGHT);
3354
finalizeheader(0, RIGHT);
3355
encode_col_buf(RIGHT);
3361
finalizeheader(0, -1);
3184
res = init_buffer();
3185
while(res == 0)res = roll_buffer();
3187
if(res == LAST)return;
3189
skiplines(gendata.curvline, COLTOPSTART);
3190
lline = gendata.curvline;
3195
calcbufmargins(LEFT);
3197
encode_col_buf(LEFT);
3198
lline = gendata.curvline;
3199
if(gendata.yres == 1200)
3201
finalizeheader(1, LEFT);
3203
encode_col_buf(LEFT);
3209
calcbufmargins(RIGHT);
3211
encode_col_buf(RIGHT);
3212
lline = gendata.curvline;
3213
if(gendata.yres == 1200)
3215
finalizeheader(1, RIGHT);
3217
encode_col_buf(RIGHT);
3223
calcbufmargins(LEFT);
3225
encode_col_buf(LEFT);
3226
calcbufmargins(RIGHT);
3227
finalizeheader(0, RIGHT);
3228
encode_col_buf(RIGHT);
3229
lline = gendata.curvline;
3230
if(gendata.yres == 1200)
3232
calcbufmargins(LEFT);
3233
finalizeheader(1, LEFT);
3235
encode_col_buf(LEFT);
3236
calcbufmargins(RIGHT);
3237
finalizeheader(0, RIGHT);
3238
encode_col_buf(RIGHT);
3245
res = roll_buffer();
3247
while(!(res & LAST))
3252
calcbufmargins(LEFT);
3253
finalizeheader(gendata.curvline - lline, LEFT);
3255
encode_col_buf(LEFT);
3256
lline = gendata.curvline;
3257
if(gendata.yres == 1200)
3259
finalizeheader(1, LEFT);
3261
encode_col_buf(LEFT);
3267
calcbufmargins(RIGHT);
3268
finalizeheader(gendata.curvline - lline, RIGHT);
3270
encode_col_buf(RIGHT);
3271
lline = gendata.curvline;
3272
if(gendata.yres == 1200)
3274
finalizeheader(1, RIGHT);
3276
encode_col_buf(RIGHT);
3282
calcbufmargins(LEFT);
3283
finalizeheader(gendata.curvline - lline, LEFT);
3285
encode_col_buf(LEFT);
3286
calcbufmargins(RIGHT);
3287
finalizeheader(0, RIGHT);
3288
encode_col_buf(RIGHT);
3289
lline = gendata.curvline;
3290
if(gendata.yres == 1200)
3292
calcbufmargins(LEFT);
3293
finalizeheader(1, LEFT);
3295
encode_col_buf(LEFT);
3296
calcbufmargins(RIGHT);
3297
finalizeheader(0, RIGHT);
3298
encode_col_buf(RIGHT);
3304
res = roll_buffer();
3310
calcbufmargins(LEFT);
3311
finalizeheader(gendata.curvline - lline, LEFT);
3313
encode_col_buf(LEFT);
3314
if(gendata.yres == 1200)
3316
finalizeheader(1, LEFT);
3318
encode_col_buf(LEFT);
3323
calcbufmargins(RIGHT);
3324
finalizeheader(gendata.curvline - lline, RIGHT);
3326
encode_col_buf(RIGHT);
3327
if(gendata.yres == 1200)
3329
finalizeheader(1, RIGHT);
3331
encode_col_buf(RIGHT);
3337
calcbufmargins(LEFT);
3338
finalizeheader(gendata.curvline - lline, LEFT);
3340
encode_col_buf(LEFT);
3341
calcbufmargins(RIGHT);
3342
finalizeheader(0, RIGHT);
3343
encode_col_buf(RIGHT);
3344
if(gendata.yres == 1200)
3346
calcbufmargins(LEFT);
3347
finalizeheader(1, LEFT);
3349
encode_col_buf(LEFT);
3350
calcbufmargins(RIGHT);
3351
finalizeheader(0, RIGHT);
3352
encode_col_buf(RIGHT);
3358
finalizeheader(0, -1);