Posts tagged "printer"

Support for unicode characters on Zebra Labels

In ES2, Livecycle introduced support for arbitrary unicode characters in Zebra Labels. Prior to this only latin-I charset was supported. Though there was support for Asian encoding like GBK(Simplified Chinese), Shift-JIS (Japanese), BIG-5 (Traditional Chinese) and KSC-5601 (Korean) but generic unicode support was missing.

Another pain was LC didn’t allow any font that is not present on the printer, to be specified in the label. This combined with above became a real problem with the middle east customers. The problem with Zebra is one cannot embed fonts inside the document like Postscript as downloading fonts on the printer is awfully slow. So the only option we left with is to rasterize the text and represent it as an image in the generated label. This way, the form author can get what he sees on the screen in pdf or in designer. Even with this approach, we felt that there is considerable file size bloating even after compressing the images of the document. Since XTG was rasterizing all the text present in the font other than the printer, which was not necessary sometime. For example, if the text is specified in english in Arial font, the end user might want to substitute it with the font present on the printer. In fact this is what we used to do before this change.

An option in XDC file is used to map to a font which is to be rasterized. The general font mapping sequence that is allowed in XTG needs both from and to font and along with it one can specify which unicodeRange to target. But here, the form author might not know before hand what data is going to be merged with the form. For example, there can be multiple textfields in the form with different fonts specified. The data to be merged in the form may contain non-english characters for some of the textfield. If the end user wants to map the form font into printer font, she has to specify that many mapping in the config file. So to ease the effort on the end user side, we exposed this option in xdc file where one needs to specify only to font and unicodeRange. This is a shortcut to the existing font mapping sequence.

<xdp>
    <xdc>
       <deviceInfo>
          <option>

            ...

            <!-- ========================================== -->
            <!-- Raster Substitution Font                     -->
            <!-- ========================================== -->

            <rasterSubstitutionFont typeface="CG Triumvirate_Normal_Normal" unicodeRange="U+20-U+FF"/>
         </option>
     </deviceInfo>
   </xdc>
</xdp>

The above entry is shortcut to the following config option:

<fontInfo>
   <map from="FONT_TO_BE_RASTERED" to="CG Triumvirate_Normal_Normal" unicodeRange="U+20-U+FF"/>
</fontInfo>

Here the printer driver for Zebra printer in XTG determines which font is going to be rasterized and based on that map that font to the specified rasterSubstitutionFont present in the xdc file.

There can be multiple rasterSubstitutionFont in the XDC file for different unicodeRange just like the font substitution entry.

Document Printing Using Adobe LiveCycle Output

Adobe LiveCycle Output generates printer ready document in various formats like ps, pcl etc from a form design (xdp) or pdf. The form design here refers to the combination of a template and the data associated with it. These printer ready documents can be directly streamed to the printer for printing. I will start start with the types of printers first and then examine the Output API to access them.

Printers can be broadly classified into two categories based on the way to access them.

Directly accessible printer

If a printer is installed on the same machine from where it is being accessed (means on the same machine where LiveCycle is installed), it is called directly accessible printer and the machine is called printer host (or print server) machine. These type of printers can be a local printer connected to the machine directly or a remote network printer installed on that machine.

Indirectly Accessible Printer

Now-a-days, there are technologies like LPR/LPD, CUPS etc. available to obviate the need of the printer being installed on the same machine, to use that.
In this model, the printer installed on a machine (print server) is accessed from another machine. This is called indirect access. In this type of access we need to know the print server IP or hostname and the printer’s name.

One Solution to all problem

LC Output has following single API to access all kinds of printers. The user needs to pass the access mechanism, described later in this blog in the API.

void sendToPrinter(Document document, Enum accessMechanism, String printServerUri, String printerName)

where document being the document to be printed, printerName being the printer on which the document to be printed, printServerUri being the print server on which the printerName is installed and accessMechanism being the method to use to direct the document on the printerName.

The LPD service might be listening to the ports different than the standard ports. In that case the caller needs to pass the ip address and port number in x.x.x.x:portNo format.

Enumeration Description
SharedPrinter
This is used for direct access of the printer. In this case, the user needs to specify only the printerName, The printServerUri argument will be ignored in this case.
LPD If specified, LC will use indirect method to access the printerName via the printServerUri using LPR/LPD technology.
CUPS If specified, LC will use indirect method to access the printServerUri using IPP 1.1 technology.
DirectIP
If specified, LC will use the direct ip mechanism to access the printServerUri. The printerName argument, in this case, will be ignored by the API.

Examples

The following table describes the expected results in case of each accessMechanism that the user can expect:

accessMechanism value of sPrintServerUri value of sPrinterName Expected result
SharedPrinter
Any null Exception : Required Argument sPrinterName cannot be null
SharedPrinter
Any Invalid Exception : Printer not found
SharedPrinter
Any Valid Printed Output
LPD null Any Exception : Required Argument sPrintServerUri cannot be null
LPD Invalid null Exception : Required Argument sPrinterName cannot be null
LPD Invalid non-null Exception : sPrintServerUri not found
LPD Valid Invalid Exception : Printer Not Found
LPD Valid Valid Printed Output
CUPS null Any Exception : Required Argument sPrintServerUri cannot be null
CUPS Invalid Any Exception : Printer Not Found
CUPS Valid Any Printed Output
DirectIP
null Any Exception : Required Argument sPrintServerUri cannot be null
DirectIP
Invalid Any Exception : Printer Not Found
DirectIP
Valid Any Printed Output

The sPrintServerUri parameter, in case of CUPS will be something like http://<server>:<port>/<path>/<printerName>. If the user wants to use a port other than the default port in case of LPD and DirectIP, he can pass <server>:<port> in the sPrintServerUri argument. Here <port> is strictly a positive integer and <server> is either a valid IP address or a valid hostname. If one passes anything other than the integer in place of <port>, one will get Malformed URI exception.