Bug 37116 - ESC POS Renderer
Summary: ESC POS Renderer
Status: CLOSED WONTFIX
Alias: None
Product: Fop - Now in Jira
Classification: Unclassified
Component: awt renderer (show other bugs)
Version: all
Hardware: Other other
: P2 enhancement
Target Milestone: ---
Assignee: fop-dev
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-17 14:41 UTC by Andrea Amerigo Aristodemo Gariboldi
Modified: 2012-04-30 00:17 UTC (History)
0 users



Attachments
Java code Esc Pos renderer (5.90 KB, text/java)
2005-10-17 14:42 UTC, Andrea Amerigo Aristodemo Gariboldi
Details
escposrenderer with apache header and package (9.55 KB, text/java)
2005-10-24 16:25 UTC, Andrea Amerigo Aristodemo Gariboldi
Details
coding style touced-up (7.51 KB, text/java)
2005-10-25 16:05 UTC, Andrea Amerigo Aristodemo Gariboldi
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrea Amerigo Aristodemo Gariboldi 2005-10-17 14:41:05 UTC
Hi all,
   i would like to submit this ugly but functional implementation of a renderer
for ESCPOS printers. With correct scale factor it can render against any ESCPOS 
printer directly (output stream to the device):

        ...
        
        Driver driver = new Driver();
        OutputStream out= new FileOutputStream("/dev/usb/usbtm0"); // the 
printer device
        OutputStream debug= new FileOutputStream("/tmp/escpos.txt");
        driver.setRenderer(new EscPosRenderer(284,new PrintWriter(debug)));
        driver.setOutputStream(out);
        driver.render(...);
        out.close();

        ...

Please let me know if you need more docs or info.

Andrea.



---------------Renderer Code----------------------
package eforce.fop.renderer;
/**
 * @Author Andrea A. A. Gariboldi
 * */
import java.awt.image.Raster;

import java.io.OutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import org.apache.fop.render.awt.AWTRenderer;

/**
 * EscPosRenderer converts AWTRenderer output
 * to an escpos raster bit image command.
 */
public class EscPosRenderer extends AWTRenderer
{
  /**
   * Very usefull debug of 0 1 bit maps for 
   * human beings. Expecially if you put in in
   * a file and look at without wrap.
   */
  private PrintWriter debug;

  public EscPosRenderer()
  {
    super(null);
    this.debug= null;
  }
  
  /**
   * You will need scale factor to meet your printer
   * resolution, example:
   * 
   * EPSON TM-L90 (scaleFactor 284):
   *  max printable horizontal line = 71mm = 568 dots
   *  so make a FO document to print a table with solid
   *  borthers 71mm wide, and find that your scale factor
   *  is 284. Is not so simple to explain why, you better test
   *  it, playing with scaleFactor and trying to have your
   *  table printed as 71mm wide, or better looking at
   *  debug file, have your table printed as 568 dots wide.
   *  
   */
  public EscPosRenderer(double scaleFactor)
  {
    super(null);
    this.setScaleFactor(scaleFactor);
    this.debug= null;
  }

  public EscPosRenderer(double scaleFactor, PrintWriter debug)
  {
    super(null);
    this.setScaleFactor(scaleFactor);
    this.debug= debug;
  }

  public void stopRenderer(OutputStream out)
  throws IOException
  {
    super.stopRenderer(out);
    
    Raster r= getLastRenderedPage().getData();
    double maxY= r.getBounds().getMaxY();
    double maxX= r.getBounds().getMaxX();
    int h= new Double(r.getBounds().getHeight()).intValue();
    int w= new Double(r.getBounds().getWidth()).intValue();
    
    /* convert to black & white image (very ugly) */  
    char[][] imagePixels= new char[h][w];
     
    for (int y=(int)Math.round(r.getBounds().getMinY());y<maxY;y++)
    {
      for (int x=(int)Math.round(r.getBounds().getMinX());x<maxX;x++)
      {
         /* rgb values to 0 1 */
         if (r.getSample(x,y,0)==255&&r.getSample(x,y,1)==255&&r.getSample
(x,y,2)==255)
           imagePixels[y][x]= '0';
         else
           imagePixels[y][x]= '1';
         
         d(imagePixels[y][x]);
      }
      dln();
    }
     
    dln("----------------------");

    /* Escpos raster bit image is formed like this x=n*byte(8 bit) y=n*dots 
     * so we need to convert w from dots to bytes, each byte represents 8 
horizontal
     * dots, next we fill the end of the line whit nulls (xcorrection).
     * The result is an array on bytes to send to the printer.
     * */
    int paperw= new Double(Math.ceil(new Double(w).doubleValue()/8.0)).intValue
();
    int xcorrection= (paperw*8)-w;
    byte[] image= new byte[paperw*h];
    int cnt= 0,idx=0;
    StringBuffer sb= new StringBuffer(8);

    // so ugly     
    for (int y=0;y<h;y++)
    {
       for (int x=0;x<w;x++)
       {
         if (++cnt==8)
         {
           sb.append(imagePixels[y][x]);
           String strb= sb.toString();
           d(strb);
           int intb= Integer.parseInt(strb,2);
           image[idx++]= (byte)chr(intb); //binary string to byte
           sb.delete(0,8);
           cnt=0;
         }
         else  
           sb.append(imagePixels[y][x]);      
       }
       d("|");
       for (int c=0;c<xcorrection;c++) 
         if (++cnt==8)
         {
           sb.append('0');
           String strb= sb.toString();
           d(strb);
           int intb= Integer.parseInt(strb,2);
           image[idx++]= (byte)chr(intb); //binary string to byte
           sb.delete(0,8);
           cnt=0;
         }
         else  
           sb.append('0'); //fill end of line with nulls

       dln();
    }
     
    printImage(0, paperw, h, image, out);
     
    if (debug!=null) {  debug.flush(); } 
  }
  
  /**
   * Adpter for escpos raster bit image printing
   */
  private static void printImage(int m, int w, int h, byte[] data, OutputStream 
out)
  throws IOException
  {
    int s=w*h,xH=1,xL=0,yH=1,yL=0,fix=255;
    
    if (data.length!=s) // if something strange stream!!
      throw new RuntimeException("wrong data count: data.length-
> "+data.length+" w*h: "+s);
     
    if (w > fix)
    {
      xH= new Double(Math.floor((double)w/(double)fix)).intValue();
      if (xH==0) xH=1;
      xL= w-(xH*fix);
    }
    else
    if (w < fix)
    {
      xH= 0;
      xL= w;
    }

    if (h > fix)
    {
      yH= new Double(Math.floor((double)h/(double)fix)).intValue();
      if (yH==0) yH=1;
      yL= h-yH*fix;
    }
    else
    if (h < fix)
    {
      yH= 0;
      yL= new Double(Math.ceil(h)).intValue();
    }
     
    int H= yL + yH * (fix+1),W= xL + xH * (fix+1),S= W*H;
    
    out.write(new byte[]{'\35','v','0',(byte)chr(m)}); //cmd1
    out.flush();
    out.write(new byte[]{(byte)chr(xL),(byte)chr(xH),(byte)chr(yL),(byte)chr
(yH)}); //cmd2
    out.flush();
    out.write(data); //data
    out.flush();

    byte[] surplus= new byte[S-data.length]; // data from strange escpos 
conversion functions
                                             // actually useless
    for (int i=0;i<surplus.length;i++) surplus[i]= (byte)chr(0);
    
    out.write(surplus); // actually useless data, that printer want!
    out.flush();
  }
  
  /**
   * Stupid function to meet escpos samples,
   * and to try make code more readable
   */
  private static char chr(int i) 
  {
    return (char)i;
  }
  
  private void d(char c)
  {
    if (debug!=null) debug.print(c);
  }

  private void d(String s)
  {
    if (debug!=null) debug.print(s);
  }

  private void dln()
  {
    if (debug!=null) debug.println();
  }

  private void dln(String s)
  {
    if (debug!=null) debug.println(s);
  }

}
----------------------------------------------------------------
Comment 1 Andrea Amerigo Aristodemo Gariboldi 2005-10-17 14:42:43 UTC
Created attachment 16716 [details]
Java code Esc Pos renderer
Comment 2 Jeremias Maerki 2005-10-19 10:19:53 UTC
Andrea, thank you for this. I think support for these POS printers is
interesting, though I'm not sure this is the best approach to implement this. I
think you could create a much more universally usable thing if you took the
bitmap conversion out of the renderer and into a separate package where you
simply take bitmap images that you convert for the POS printers. That way it
could easily be used for FOP Trunk, too. After all, we won't be able to include
your renderer in FOP as is, (1) because it's apparently written for FOP 0.20.5
whose development line has been frozen and (2) your code would need some
touch-up before we would include it (code style, package name must be
org.apache.fop.*, no apache license header etc.).

If I were you, separate this code out into a universally usable component that
can convert bitmaps to output for POS printers and post that somewhere on the
net, for example as SourceForge project. We could then link to it from the FOP
website. WDYT?
Comment 3 Andrea Amerigo Aristodemo Gariboldi 2005-10-24 15:01:41 UTC
uups.. 283 instead of 284 for TM-L90...
Comment 4 Andrea Amerigo Aristodemo Gariboldi 2005-10-24 15:06:54 UTC
Off course Jeremias, i'll doit as soon as i can. 
Comment 5 Andrea Amerigo Aristodemo Gariboldi 2005-10-24 16:25:58 UTC
Created attachment 16788 [details]
escposrenderer with apache header and package

1) modified package
2) added apache header

i'll clean it for newer fop versions..
Comment 6 Andrea Amerigo Aristodemo Gariboldi 2005-10-24 16:53:52 UTC
(In reply to comment #2)
> Andrea, thank you for this. I think support for these POS printers is
> interesting, though I'm not sure this is the best approach to implement this. I
> think you could create a much more universally usable thing if you took the
> bitmap conversion out of the renderer and into a separate package where you
> simply take bitmap images that you convert for the POS printers. That way it
> could easily be used for FOP Trunk, too. 

Yes, but is really useless without FOP. Those printers are almost used to print
receipts and invoices, with near to 0 support for advanced imaging, so this will
be used almost to line up text on preprinted forms, and i think it is a very
easy way to do it. 

> After all, we won't be able to include
> your renderer in FOP as is, (1) because it's apparently written for FOP 0.20.5
> whose development line has been frozen and (2) your code would need some
> touch-up before we would include it (code style, package name must be
> org.apache.fop.*, no apache license header etc.).

I posted it with package and header, but is there a doc with coding style infos
that i can use to touch-up the code? Which branch i should use?

> 
> If I were you, separate this code out into a universally usable component that
> can convert bitmaps to output for POS printers and post that somewhere on the
> net, for example as SourceForge project. We could then link to it from the FOP
> website. WDYT?

As i say i think it is really useless alone.

Thanks
Andrea
Comment 7 Jeremias Maerki 2005-10-24 22:01:11 UTC
(In reply to comment #6)
> (In reply to comment #2)
> > Andrea, thank you for this. I think support for these POS printers is
> > interesting, though I'm not sure this is the best approach to implement this. I
> > think you could create a much more universally usable thing if you took the
> > bitmap conversion out of the renderer and into a separate package where you
> > simply take bitmap images that you convert for the POS printers. That way it
> > could easily be used for FOP Trunk, too. 
> 
> Yes, but is really useless without FOP. Those printers are almost used to print
> receipts and invoices, with near to 0 support for advanced imaging, so this will
> be used almost to line up text on preprinted forms, and i think it is a very
> easy way to do it. 

It may be useless without FOP in your case, but some people might actually want
to create the receipts with SVG/Batik instead of XSL-FO/FOP. I simply think you
restrict your code too quickly to a certain use case while it could actually be
used in a much wider area.

> > After all, we won't be able to include
> > your renderer in FOP as is, (1) because it's apparently written for FOP 0.20.5
> > whose development line has been frozen and (2) your code would need some
> > touch-up before we would include it (code style, package name must be
> > org.apache.fop.*, no apache license header etc.).
> 
> I posted it with package and header, but is there a doc with coding style infos
> that i can use to touch-up the code? 

Our code conventions: http://xmlgraphics.apache.org/fop/dev/conventions.html
And you can take the existing code as an example.

> Which branch i should use?

No branch. Use the trunk: http://svn.apache.org/repos/asf/xmlgraphics/fop/trunk/

BTW, the license header needs to be the one from the Apache License v2.0, not 1.1.

> > 
> > If I were you, separate this code out into a universally usable component that
> > can convert bitmaps to output for POS printers and post that somewhere on the
> > net, for example as SourceForge project. We could then link to it from the FOP
> > website. WDYT?
> 
> As i say i think it is really useless alone.

And I disagree. :-)
Comment 8 Andrea Amerigo Aristodemo Gariboldi 2005-10-25 16:05:16 UTC
Created attachment 16808 [details]
coding style touced-up
Comment 9 Andrea Amerigo Aristodemo Gariboldi 2005-10-25 16:35:38 UTC
Probably you are right, there may be someone somewhere that wants to print
invoices with Vectorial Graphics or whatever, but writing a good java library to
support escpos printers needs time, writing a FOP Renderer to easly print a page
is a starting point...

I've tyde up the code, and recoded for the trunk you posted me out.

Andrea

(In reply to comment #7)
> (In reply to comment #6)
> > (In reply to comment #2)
> > > Andrea, thank you for this. I think support for these POS printers is
> > > interesting, though I'm not sure this is the best approach to implement
this. I
> > > think you could create a much more universally usable thing if you took the
> > > bitmap conversion out of the renderer and into a separate package where you
> > > simply take bitmap images that you convert for the POS printers. That way it
> > > could easily be used for FOP Trunk, too. 
> > 
> > Yes, but is really useless without FOP. Those printers are almost used to print
> > receipts and invoices, with near to 0 support for advanced imaging, so this will
> > be used almost to line up text on preprinted forms, and i think it is a very
> > easy way to do it. 
> 
> It may be useless without FOP in your case, but some people might actually want
> to create the receipts with SVG/Batik instead of XSL-FO/FOP. I simply think you
> restrict your code too quickly to a certain use case while it could actually be
> used in a much wider area.
> 
> > > After all, we won't be able to include
> > > your renderer in FOP as is, (1) because it's apparently written for FOP 0.20.5
> > > whose development line has been frozen and (2) your code would need some
> > > touch-up before we would include it (code style, package name must be
> > > org.apache.fop.*, no apache license header etc.).
> > 
> > I posted it with package and header, but is there a doc with coding style infos
> > that i can use to touch-up the code? 
> 
> Our code conventions: http://xmlgraphics.apache.org/fop/dev/conventions.html
> And you can take the existing code as an example.
> 
> > Which branch i should use?
> 
> No branch. Use the trunk: http://svn.apache.org/repos/asf/xmlgraphics/fop/trunk/
> 
> BTW, the license header needs to be the one from the Apache License v2.0, not 1.1.
> 
> > > 
> > > If I were you, separate this code out into a universally usable component that
> > > can convert bitmaps to output for POS printers and post that somewhere on the
> > > net, for example as SourceForge project. We could then link to it from the FOP
> > > website. WDYT?
> > 
> > As i say i think it is really useless alone.
> 
> And I disagree. :-)

Comment 10 Jeremias Maerki 2005-11-09 10:36:44 UTC
I'd like additional opinions from the FOP committers on this one.
Comment 11 Chris Bowditch 2005-11-09 12:45:34 UTC
Well if the code follows the Project style conventions has the Apache header, 
and works for Trunk then the only Pro/cons I see to commiting this to the code 
base are:

+ An additional renderer which may be useful for some users - although I think 
its a very tiny set of users. XSL-FO is not the best tecnology for working 
with ESCPOS Printers, but then XSL-FO is not the best technology for 
generating Text output either.
- Support problems; users on the mailing list asking what it does, or 
reporting that it doesn't do X or Y.

Given the above it's a hard decision to make :)
Comment 12 Manuel Mall 2005-11-09 13:44:48 UTC
I have similar concerns as Chris.

Maybe once we have the pluggable renderers this can be more easily solved by

a) People who develop non "mainstream" renderers can provide them as separate 
jars and house them on SourceForge or similar environments

b) The FOP project itself could have an area called "unsupported" for this type 
of additions to FOP

c) XMLGraphics could provide an "incubator" type environment for it

It seems what I am saying is that we should encourage and support expansion / 
extension of FOP by possibly providing some infrastructure for it but not 
necessarily by adding everything into the core code base.
Comment 13 Andrea Amerigo Aristodemo Gariboldi 2005-11-09 15:07:46 UTC
May i suggest (In reply to comment #11)
> Well if the code follows the Project style conventions has the Apache header, 
> and works for Trunk then the only Pro/cons I see to commiting this to the code 
> base are:
> 
> + An additional renderer which may be useful for some users - although I think 
> its a very tiny set of users. XSL-FO is not the best tecnology for working 
> with ESCPOS Printers, but then XSL-FO is not the best technology for 
> generating Text output either.

Its true. But what if your printer supports only two fonts? This renderer 
render "eye visible text" but it is really an image with gliphs for characters
from any fop supported font, and XSL-FO lets you align things on a preprinted
form simply with a ruler, millimeter by millimeter an not with \n \r \something.

> - Support problems; users on the mailing list asking what it does, or 
> reporting that it doesn't do X or Y.
> 
> Given the above it's a hard decision to make :)

Just trying to explain.

Andrea
Comment 14 Glenn Adams 2012-04-03 21:02:28 UTC
lack of consensus to patch
Comment 15 Glenn Adams 2012-04-30 00:14:39 UTC
batch transition resolved+wontfix to closed+wontfix
Comment 16 Glenn Adams 2012-04-30 00:17:08 UTC
batch transition resolved+wontfix to closed+wontfix; if you believe this remains a bug and can demonstrate it with appropriate input FO file and output PDF file (as applicable), then you may reopen