Skip to content

Developing a Frontend to BWIPP

Terry Burton edited this page Feb 19, 2015 · 29 revisions

Developing a Frontend to BWIPP

There are a number of frontends to BWIPP that vary in terms of the functionality that they expose and the way that they express this through their API or GUI, etc.

It would be nice to unify some of these projects but in the meantime this document attempts to provide some guidelines to apply when developing something that places BWIPP in the hands of developers and users.

The author would ideally like any language binding, library or graphical frontend to be representative of the complete functionality of the BWIPP resource and to be maintainable with minimal effort and these guideline help to achieve this goal.

Author's commitment: I will make a best efforts commitment to provide end user support and developer support for any library or application that makes an effort to adopt the principles given here. Such projects should also feel free to adopt the BWIPP mailing list if they are so inclined and to request access to extend this wiki.

Make Early Contact with the BWIPP Author

Contact the author of BWIPP whilst you're still experimenting.

I'm Terry Burton. I will try not to insist on my own way as it's you that will end up supporting your creation so I want you to be happy with it, but it will help everyone if there is some consistency between your code and the next person's.

Refer users to the BWIPP documentation

Point your users at the online BWIPP symbologies and options references.

The reference is written these in a way that is fairly environment agnostic but if you have any idea or want to improve them then please contribute.

Safe argument passing

Safely pass your arguments to BWIPP in an PostScript code injection-proof way.

Hexify the data, options and encoder string input to BWIPP to prevent PostScript injection by means of un-escaped ) or otherwise.

Not like this:

0 0 moveto
(02345673)
(includetext)
/ean8
/uk.co.terryburton.bwipp findresource exec

But like this (obviously don't include the comments, at least not in production):

0 0 moveto
<3032333435363733>                          % (02345673)
<696e636c75646574657874>                    % (includetext)
<65616e38> cvn                              % /ean8
/uk.co.terryburton.bwipp findresource exec

Example Python:

import binascii, textwrap
def hexify(input):
  return textwrap.TextWrapper(subsequent_indent=' ', width=72). \
    fill('<' + binascii.hexlify(string) + '>')

Example Perl:

sub hexify {
  return '<'.(join "\n ", unpack '(A72)*', unpack 'H*', shift).'>';
}

Use the BWIPP metadata

Use the inline metadata rather than embedding a load of static data in your code.

Support barcode formats automatically by scanning the barcode.ps metadata for BEGIN/END ENCODER blocks. From these extract descriptions, example data and example options using the DESC, EXAM and EXOP stanzas within the BEGIN/ENCODER ENCODER blocks.

Example BWIPP metadata for an encoder:

% --BEGIN ENCODER ean8--
% --REQUIRES preamble raiseerror renlinear ean5 ean2--
% --DESC: EAN-8
% --EXAM: 02345673
% --EXOP: includetext guardwhitespace
% --RNDR: renlinear
... PostScript resource definition here ...
% --END ENCODER ean8--

The aim is that libraries and graphical frontends can be light on compiled-in data and can therefore be enhanced by simply replacing the barcode.ps file.

To fully meet this objective may require extending the barcode.ps metadata to describe the individual options that are available for each encoder. The BWIPP author is certainly interested in having such a discussion so please make contact regarding your requirements.

Let users drive BWIPP directly if they choose

Allow advanced users to specify the data, options and encoder directly. This will allow them to access BWIPP functionality that you haven't anticipated or exposed via your API or GUI.

Use BWIPP's error reporting

Use the BWIPP error reporting mechanism to provide specific error messages to users so that they can understand why a given input is invalid. For example, the following PS procedure can be used to invoke barcode.ps and on error will halt with the descriptive text of the error (e.g. BWIPP ERROR: EAN-13 must be 12 or 13 digits) written to STDERR which can be intercepted and thrown or displayed in whatever manner is most appropriate.

%!PS
errordict begin
/handleerror {
  $error begin
  errorname dup length string cvs 0 6 getinterval (bwipp.) eq {
    (%stderr) (w) file
    dup (\nBWIPP ERROR: ) writestring
    dup errorname dup length string cvs writestring
    dup ( ) writestring
    dup errorinfo dup length string cvs writestring
    dup (\n) writestring
    dup flushfile end quit
  } if
  end //handleerror exec
} bind def
end
%
% If necessary, set up anything else specific to the environment just here.
%
% Include the BWIPP resource, either directly or from PS
(barcode.ps) run
%
% Now make the calls to BWIPP
% 0 0 moveto (ABC) () /code39 /uk.co.terryburton.bwipp findresource exec

Locating the resource

Allow the location of the barcode.ps file to be configured by the user so that non-admins users can provide a local version and distributions that deprecate bundled libraries can provide a separately packaged version.

In any case, use the following search order to locate the barcode.ps resource:

  1. [%USER_SPECIFIED_LOCATION%]
  2. ~/.[%APP_RC_DIRECTORY%] (a user's own replacement)
  3. [%APP_INSTALL_DIR%] (a version you have bundled)
  4. /usr/share/postscriptbarcode (Fedora's postscriptbarcode package)
  5. /usr/share/libpostscriptbarcode (Debian's libpostscriptbarcode package)

Displaying the list of supported barcodes

To make the presentation of the list of barcode formats manageable any such list of barcodes should be rendered in the same/similar way as the web-based generator.

Would it be helpful to extend the metadata to help group the supported barcodes into categories?

Clone this wiki locally