[barcode] barcode on PCL printer

Andrea Scopece a.scopece@vizzavi.it
Fri, 18 Oct 2002 23:09:14 -0000


This is a multi-part message in MIME format.

------=_NextPart_000_0068_01C276FB.6083E280
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

From: <r.krebs@netlab.ch>

> Here's an example:
>   Barcode_Encode_and_Print(data, stdout, width, height, xoffs, yoffs,
> flags) ;
>        data = "123456789827"
>        width = 73 (25.8mm)
>        height = 34 (12mm)
>        xoffs = 22 (8mm)
>        yoffs = 136 (48mm)
>  -> This results in a scaling factor of 0.722772
>
> Since the printout is done by the line
>       fprintf(f,"%c*c%.0fH", 27, ((j*scalef) - SHRINK_AMOUNT) * 10.0);
> the result for the different bars will therefore be (SHRINK_AMOUNT =
0.15):
>       j = 1 -> 5.72     -> 5 decipoints
>       j = 2 -> 12.95    -> 12 decipoints
>       j = 3 -> 20.18    -> 20 decipoints
>       j = 4 -> 27.41    -> 27 decipoints

this MUST be corrected as:

       j = 1 -> 57.2     -> 57 decipoints
       j = 2 -> 129.5    -> 129 decipoints
       j = 3 -> 201.8    -> 201 decipoints
       j = 4 -> 274.1    -> 274 decipoints

Can we consider a default laser printer resolution oequal to 300 dpi? I
think yes.
At this resolution the thinnest line the printer can draw is about
0.084666... mm.

PCL can use as units the above resolution,
or decipoints, (the last is independent from resolution of printer).

One decipoints is defined as 1/720 of Inch, about 0,0352777... mm.

This mean that a normal printer (300 dpi) don't allow a resolution of 1
decipoints, but at best about 2.4 decipoints.

A (real) 600 dpi printer has a resolution of 1.2 decipoints.

HP printers manage (internally) all units of measure  (resolution,
decipoints, columns, row,..)as 1/7200 of inch, so internal conversions
doesn't impact on output quality.
.....

Aarghhhhhhhhhhhhh!!!!!!!!!!!!!
I have not converted the SHRINK_AMOUNT, this were originally expressed in
points
in ps.c and I have used it as is, instead of convert it to decipoints.

The correct espression in pcl.c should be:
----------snip------------------------------------------------------

fprintf(f, "%c*c%.0fH", 27, (j*scalef *10.0) - SHRINK_AMOUNT);

----------snip------------------------------------------------------

attached here, a corrected version of pcl.c (barcode-0.98), with PCL
comments added.

Andrea Scopece



------=_NextPart_000_0068_01C276FB.6083E280
Content-Type: application/octet-stream;
	name="pcl.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="pcl.c"

/*=0A=
 * pcl.c -- printing the "partial" bar encoding in PCL format=0A=
 *=0A=
 * Copyright (c) 1999 Alessandro Rubini (rubini@gnu.org)=0A=
 * Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)=0A=
 * Copyright (c) 2001 Andrea Scopece (a.scopece@tin.it)=0A=
 *=0A=
 *   This program is free software; you can redistribute it and/or modify=0A=
 *   it under the terms of the GNU General Public License as published by=0A=
 *   the Free Software Foundation; either version 2 of the License, or=0A=
 *   (at your option) any later version.=0A=
 *=0A=
 *   This program is distributed in the hope that it will be useful,=0A=
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of=0A=
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the=0A=
 *   GNU General Public License for more details.=0A=
 *=0A=
 *   You should have received a copy of the GNU General Public License=0A=
 *   along with this program; if not, write to the Free Software=0A=
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA =
02111-1307, USA.=0A=
 */=0A=
=0A=
#include <stdio.h>=0A=
#include <stdlib.h>=0A=
#include <string.h>=0A=
#include <ctype.h>=0A=
#include <errno.h>=0A=
=0A=
#include "barcode.h"=0A=
=0A=
#define SHRINK_AMOUNT 0.15  /* shrink the bars to account for ink =
spreading */=0A=
=0A=
=0A=
/*=0A=
 * How do the "partial" and "textinfo" strings work? See file "ps.c"=0A=
 */=0A=
=0A=
=0A=
int Barcode_pcl_print(struct Barcode_Item *bc, FILE *f)=0A=
{=0A=
    int i, j, k, barlen;=0A=
    double f1, f2, fsav=3D0;=0A=
    int mode =3D '-'; /* text below bars */=0A=
    double scalef=3D1, xpos, x0, y0, yr;=0A=
    unsigned char *ptr;=0A=
    unsigned char c;=0A=
=0A=
    char font_id[6];           /* default font, should be "scalable" */=0A=
    /* 0     Line printer,    use on older LJet II, isn't scalable   */=0A=
    /* 4148  Univers,         use on LJet III series, and Lj 4L, 5L  */=0A=
    /* 16602 Arial,           default LJ family 4, 5, 6, Color, Djet */=0A=
=0A=
    if (!bc->partial || !bc->textinfo) {=0A=
	bc->error =3D EINVAL;=0A=
	return -1;=0A=
    }=0A=
=0A=
    /*=0A=
     * Maybe this first part can be made common to several printing =
back-ends,=0A=
     * we'll see how that works when other ouput engines are added=0A=
     */=0A=
=0A=
    /* First, calculate barlen */=0A=
    barlen =3D bc->partial[0] - '0';=0A=
    for (ptr =3D bc->partial+1; *ptr; ptr++)=0A=
	if (isdigit(*ptr)) =0A=
	    barlen +=3D (*ptr - '0');=0A=
	else if (islower(*ptr))=0A=
	    barlen +=3D (*ptr - 'a'+1);=0A=
=0A=
    /* The scale factor depends on bar length */=0A=
    if (!bc->scalef) {=0A=
        if (!bc->width) bc->width =3D barlen; /* default */=0A=
        scalef =3D bc->scalef =3D (double)bc->width / (double)barlen;=0A=
    }=0A=
=0A=
    /* The width defaults to "just enough" */=0A=
    if (!bc->width) bc->width =3D barlen * scalef +1;=0A=
=0A=
    /* But it can be too small, in this case enlarge and center the area =
*/=0A=
    if (bc->width < barlen * scalef) {=0A=
        int wid =3D barlen * scalef + 1;=0A=
        bc->xoff -=3D (wid - bc->width)/2 ;=0A=
        bc->width =3D wid;=0A=
        /* Can't extend too far on the left */=0A=
        if (bc->xoff < 0) {=0A=
            bc->width +=3D -bc->xoff;=0A=
            bc->xoff =3D 0;=0A=
        }=0A=
    }=0A=
=0A=
    /* The height defaults to 80 points (rescaled) */=0A=
    if (!bc->height) bc->height =3D 80 * scalef;=0A=
=0A=
#if 0=0A=
    /* If too small (5 + text), enlarge and center */=0A=
    i =3D 5 + 10 * ((bc->flags & BARCODE_NO_ASCII)=3D=3D0);=0A=
    if (bc->height < i * scalef ) {=0A=
        int hei =3D i * scalef;=0A=
        bc->yoff -=3D (hei-bc->height)/2;=0A=
        bc->height =3D hei;=0A=
        if (bc->yoff < 0) {=0A=
            bc->height +=3D -bc->yoff;=0A=
            bc->yoff =3D 0;=0A=
        }=0A=
    }=0A=
#else=0A=
    /* If too small (5 + text), reduce the scale factor and center */=0A=
    i =3D 5 + 10 * ((bc->flags & BARCODE_NO_ASCII)=3D=3D0);=0A=
    if (bc->height < i * scalef ) {=0A=
        double scaleg =3D ((double)bc->height) / i;=0A=
        int wid =3D bc->width * scaleg / scalef;=0A=
        bc->xoff +=3D (bc->width - wid)/2;=0A=
        bc->width =3D wid;=0A=
        scalef =3D scaleg;=0A=
    }=0A=
#endif=0A=
=0A=
    /*=0A=
     * deal with PCL output=0A=
     */=0A=
=0A=
    xpos =3D bc->margin + (bc->partial[0]-'0') * scalef;=0A=
    for (ptr =3D bc->partial+1, i=3D1; *ptr; ptr++, i++) {=0A=
	/* special cases: '+' and '-' */=0A=
	if (*ptr =3D=3D '+' || *ptr =3D=3D '-') {=0A=
	    mode =3D *ptr; /* don't count it */ i++; continue;=0A=
	}=0A=
=0A=
	/* j is the width of this bar/space */=0A=
	if (isdigit (*ptr))   j =3D *ptr-'0';=0A=
	else                  j =3D *ptr-'a'+1;=0A=
	if (i%2) { /* bar */=0A=
	    x0 =3D bc->xoff + xpos;=0A=
            y0 =3D bc->yoff + bc->margin;=0A=
            yr =3D bc->height;=0A=
            if (!(bc->flags & BARCODE_NO_ASCII)) { /* leave space for =
text */=0A=
		if (mode =3D=3D '-') {=0A=
		    /* text below bars: 10 points or five points */=0A=
		    yr -=3D (isdigit(*ptr) ? 10 : 5) * scalef;=0A=
		} else { /* '+' */=0A=
		    /* text above bars: 10 or 0 from bottom, and 10 from top */=0A=
		    y0 +=3D (isdigit(*ptr) ? 10 : 0) * scalef;=0A=
		    yr -=3D (isdigit(*ptr) ? 20 : 10) * scalef; =0A=
		}=0A=
	    }=0A=
=0A=
	    /* set left-upper corner coordinates */=0A=
=0A=
	    fprintf(f,"%c&a%.0fH", 27, x0 * 10.0);=0A=
	    fprintf(f,"%c&a%.0fV", 27, y0 * 10.0);=0A=
=0A=
	    /* set x coordinate of righ-bottom corner */=0A=
=0A=
	    fprintf(f,"%c*c%.0fH", 27, (j * scalef * 10.0)-SHRINK_AMOUNT);=0A=
=0A=
	    /* set y coorinate of right-bottom corner */=0A=
=0A=
	    fprintf(f,"%c*c%.0fV", 27, yr * 10.0);=0A=
=0A=
	    /* draw a black rectangle:=0A=
               see PCL "Rectangular Area Fill Graphics" */=0A=
=0A=
	    fprintf(f,"%c*c0P\n", 27);=0A=
	}=0A=
	xpos +=3D j * scalef;=0A=
    }=0A=
=0A=
    /* the text */=0A=
=0A=
    mode =3D '-'; /* reinstantiate default */=0A=
    if (!(bc->flags & BARCODE_NO_ASCII)) {=0A=
        k=3D0; /* k is the "previous font size" */=0A=
        for (ptr =3D bc->textinfo; ptr; ptr =3D strchr(ptr, ' ')) {=0A=
            while (*ptr =3D=3D ' ') ptr++;=0A=
            if (!*ptr) break;=0A=
	    if (*ptr =3D=3D '+' || *ptr =3D=3D '-') {=0A=
		mode =3D *ptr; continue;=0A=
	    }=0A=
            if (sscanf(ptr, "%lf:%lf:%c", &f1, &f2, &c) !=3D 3) {=0A=
		fprintf(stderr, "barcode: impossible data: %s\n", ptr);=0A=
                continue;=0A=
            }=0A=
=0A=
    /* select a Scalable Font */=0A=
=0A=
	    if (fsav !=3D f2)=0A=
	    {   =0A=
    	        if ((bc->flags & BARCODE_OUT_PCL_III) =3D=3D =
BARCODE_OUT_PCL_III)=0A=
		{	strcpy(font_id, "4148");	/* font Univers */=0A=
		}=0A=
		else=0A=
		{	strcpy(font_id, "16602");	/* font Arial */=0A=
		}=0A=
=0A=
		fprintf(f,"%c(8U%c(s1p%5.2fv0s0b%sT", 27, 27, f2 * scalef, font_id);=0A=
	    }=0A=
	    fsav =3D f2;=0A=
	=0A=
	    fprintf(f,"%c&a%.0fH", 27, (bc->xoff + f1 * scalef + bc->margin) * =
10.0);=0A=
	    fprintf(f,"%c&a%.0fV", 27,=0A=
		    mode !=3D '-'=0A=
                       ? ((double)bc->yoff + bc->margin              + =
8*scalef) * 10.0=0A=
		       : ((double)bc->yoff + bc->margin + bc->height           ) * =
10.0);=0A=
=0A=
		fprintf(f, "%c", c);=0A=
	}=0A=
=0A=
    }=0A=
=0A=
    return 0;=0A=
}=0A=

------=_NextPart_000_0068_01C276FB.6083E280--