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); } } ----------------------------------------------------------------
Created attachment 16716 [details] Java code Esc Pos renderer
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?
uups.. 283 instead of 284 for TM-L90...
Off course Jeremias, i'll doit as soon as i can.
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..
(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
(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. :-)
Created attachment 16808 [details] coding style touced-up
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. :-)
I'd like additional opinions from the FOP committers on this one.
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 :)
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.
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
lack of consensus to patch
batch transition resolved+wontfix to closed+wontfix
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