HPGL/2 Converter Add-on

Added in version 1.1.

The hpgl2 add-on provides tools to process and convert HPGL/2 plot files.

What are HPGL/2 Plot Files?

The Hewlett-Packard Graphics Language (HPGL) is a vector graphics language originally developed by Hewlett-Packard in the 1970s. HPGL is widely used for controlling pen plotters and other output devices, and it has become a de facto standard for communicating between computers and output devices in the field of computer-aided design (CAD) and drafting.

HPGL is a command-driven language that consists of a series of commands that control the movement of the plotter pen, the selection of pens and other output parameters, and the drawing of geometric shapes such as lines, arcs, circles, and text. The language is interpreted by the plotter or other output device and translated into physical pen movements on the drawing surface.

HPGL has evolved over the years, and various extensions have been added to support more complex graphics operations and to improve compatibility with other graphics languages. Despite the development of newer graphics languages and file formats, HPGL remains a widely used format for vector-based graphics, particularly in the engineering and architectural fields.

The Goal of This Add-on

An HPGL/2 plot file contains all of the data generated by a CAD application that has been sent to a plotter to print an engineering drawing. In the past, the only way to access this data was to view it on a plotter or an specialized application, which could be expensive and impractical for many people. However, this module provides functions and classes to convert HPGL/2 plot files into modern vector graphic formats such as PDF and SVG and of course DXF, allowing the data to be viewed and processed using a wide range of software tools.

Important

The Python module PyMuPDF is required for the PDF export: https://pypi.org/project/PyMuPDF/

The Plotter class in the hpgl2 add-on supports only the most commonly used commands of HPGL/2. This is because many CAD applications use only a small subset of HPGL/2 to create their output, typically consisting of polylines and filled polygons. For more information on the supported commands, please refer to the documentation for the Plotter class.

To use the HPGL2 add-on, the entry point is the ezdxf.addons.hpgl2.api module. This module contains the public interface of the add-on and should be imported in the following way:

from ezdxf.addons.hpgl2 import api as hpgl2

with open("hpgl2.plt", "rb") as fp:
    data = fp.read()
doc = hpgl2.to_dxf(data, color_mode=hpgl2.ColorMode.ACI)
doc.saveas("hpgl2_as.dxf")

High Level Functions

to_dxf

Exports the HPGL/2 commands of the byte stream b as a DXF document.

to_svg

Exports the HPGL/2 commands of the byte stream b as SVG string.

to_pdf

Exports the HPGL/2 commands of the byte stream b as PDF data.

to_pixmap

Exports the HPGL/2 commands of the byte stream b as pixel image.

ezdxf.addons.hpgl2.api.to_dxf(b: bytes, *, rotation: int = 0, mirror_x: bool = False, mirror_y: bool = False, color_mode=ColorMode.RGB, merge_control: MergeControl = MergeControl.AUTO) Drawing

Exports the HPGL/2 commands of the byte stream b as a DXF document.

The page content is created at the origin of the modelspace and 1 drawing unit is 1 plot unit (1 plu = 0.025mm) unless scaling values are provided.

The content of HPGL files is intended to be plotted on white paper, therefore a white filling will be added as background in color mode RGB.

All entities are assigned to a layer according to the pen number with the name scheme PEN_<###>. In order to be able to process the file better, it is also possible to assign the ACI color by layer by setting the argument color_mode to ColorMode.ACI, but then the RGB color is lost because the RGB color has always the higher priority over the ACI.

The first paperspace layout “Layout1” of the DXF document is set up to print the entire modelspace on one sheet, the size of the page is the size of the original plot file in millimeters.

HPGL/2’s merge control works at the pixel level and cannot be replicated by DXF, but to prevent fillings from obscuring text, the filled polygons are sorted by luminance - this can be forced or disabled by the argument merge_control, see also MergeControl enum.

Parameters:
  • b – plot file content as bytes

  • rotation – rotation angle of 0, 90, 180 or 270 degrees

  • mirror_x – mirror in x-axis direction

  • mirror_y – mirror in y-axis direction

  • color_mode – the color mode controls how color values are assigned to DXF entities, see ColorMode

  • merge_control – how to order filled polygons, see MergeControl

Returns: DXF document as instance of class Drawing

ezdxf.addons.hpgl2.api.to_svg(b: bytes, *, rotation: int = 0, mirror_x: bool = False, mirror_y: bool = False, merge_control=MergeControl.AUTO) str

Exports the HPGL/2 commands of the byte stream b as SVG string.

The plot units are mapped 1:1 to viewBox units and the size of image is the size of the original plot file in millimeters.

HPGL/2’s merge control works at the pixel level and cannot be replicated by the backend, but to prevent fillings from obscuring text, the filled polygons are sorted by luminance - this can be forced or disabled by the argument merge_control, see also MergeControl enum.

Parameters:
  • b – plot file content as bytes

  • rotation – rotation angle of 0, 90, 180 or 270 degrees

  • mirror_x – mirror in x-axis direction

  • mirror_y – mirror in y-axis direction

  • merge_control – how to order filled polygons, see MergeControl

Returns: SVG content as str

ezdxf.addons.hpgl2.api.to_pdf(b: bytes, *, rotation: int = 0, mirror_x: bool = False, mirror_y: bool = False, merge_control=MergeControl.AUTO) bytes

Exports the HPGL/2 commands of the byte stream b as PDF data.

The plot units (1 plu = 0.025mm) are converted to PDF units (1/72 inch) so the image has the size of the original plot file.

HPGL/2’s merge control works at the pixel level and cannot be replicated by the backend, but to prevent fillings from obscuring text, the filled polygons are sorted by luminance - this can be forced or disabled by the argument merge_control, see also MergeControl enum.

Python module PyMuPDF is required: https://pypi.org/project/PyMuPDF/

Parameters:
  • b – plot file content as bytes

  • rotation – rotation angle of 0, 90, 180 or 270 degrees

  • mirror_x – mirror in x-axis direction

  • mirror_y – mirror in y-axis direction

  • merge_control – how to order filled polygons, see MergeControl

Returns: PDF content as bytes

ezdxf.addons.hpgl2.api.to_pixmap(b: bytes, *, rotation: int = 0, mirror_x: bool = False, mirror_y: bool = False, merge_control=MergeControl.AUTO, fmt: str = 'png', dpi: int = 96) bytes

Exports the HPGL/2 commands of the byte stream b as pixel image.

Supported image formats:

png

Portable Network Graphics

ppm

Portable Pixmap

pbm

Portable Bitmap

The plot units (1 plu = 0.025mm) are converted to dot per inch (dpi) so the image has the size of the original plot file.

HPGL/2’s merge control works at the pixel level and cannot be replicated by the backend, but to prevent fillings from obscuring text, the filled polygons are sorted by luminance - this can be forced or disabled by the argument merge_control, see also MergeControl enum.

Python module PyMuPDF is required: https://pypi.org/project/PyMuPDF/

Parameters:
  • b – plot file content as bytes

  • rotation – rotation angle of 0, 90, 180 or 270 degrees

  • mirror_x – mirror in x-axis direction

  • mirror_y – mirror in y-axis direction

  • merge_control – how to order filled polygons, see MergeControl

  • fmt – image format

  • dpi – output resolution in dots per inch

Returns: image content as bytes

class ezdxf.addons.hpgl2.api.ColorMode

The color mode controls how color values are assigned to DXF entities

ACI

Use the pen number as AutoCAD Color Index (ACI) for DXF entities, ignores the RGB color values

RGB

Use the pen number as AutoCAD Color Index (ACI) but also set the RGB color for DXF entities, RGB color values have always higher priority than the ACI when displaying DXF content.

class ezdxf.addons.hpgl2.api.MergeControl

Merge control enumeration.

NONE

export filled polygons in print order

LUMINANCE

sort filled polygons by luminance

AUTO

guess best order of filled polygons

The Low Level Functions and Classes

ezdxf.addons.hpgl2.api.hpgl2_commands(s: bytes) list[Command]

Low level plot file parser, extracts the HPGL/2 from the byte stream b.

Important

This parser expects the “Enter HPGL/2 mode” escape sequence to recognize HPGL/2 commands. The sequence looks like this: [ESC]%1B, multiple variants of this sequence are supported.

The HPGL/2 commands are often mixed with the Printer Command Language (PCL) and/or the Raster Transfer Language (RTL) commands in a single plot file.

Some plot files that contain pure HPGL/2 code do not contain the escape sequence “Enter HPGL/2 mode”, without this sequence the HPGL/2 parser cannot recognize the beginning of the HPGL/2 code. Add the ENTER_HPGL2_MODE sequence in front of the bytes stream to switch on the HPGL/2 manually, regardless of whether the file is an HPGL/2 plot file or not, so be careful:

commands = hpgl2_commands(hpgl2.ENTER_HPGL2_MODE + data)
class ezdxf.addons.hpgl2.api.Interpreter(plotter: Plotter)

The Interpreter is the frontend for the Plotter class. The run() methods interprets the low level HPGL commands from the hpgl2_commands() parser and sends the commands to the virtual plotter device, which sends his output to a low level Backend class.

Most CAD application send a very restricted subset of commands to plotters, mostly just polylines and filled polygons. Implementing the whole HPGL/2 command set is not worth the effort - unless reality proofs otherwise.

Not implemented commands:

  • the whole character group - text is send as filled polygons or polylines

  • configuration group: IN, DF, RO, IW - the plotter is initialized by creating a new plotter and page rotation is handled by the add-on itself

  • polygon group: EA, ER, EW, FA, RR, WG, the rectangle and wedge commands

  • line and fill attributes group: LA, RF, SM, SV, TR, UL, WU, linetypes and hatch patterns are decomposed into simple lines by CAD applications

Parameters:

plotter – virtual Plotter device

errors

List of error messages occurred during the interpretation of the HPGL/2 commands.

not_implemented_commands

List of all unsupported/ignored commands from the input stream.

run(commands: list[Command]) None

Interprets the low level HPGL commands from the hpgl2_commands() parser and sends the commands to the virtual plotter device.

disable_commands(commands: Iterable[str]) None

Disable commands manually, like the scaling command [“SC”, “IP”, “IR”]. This is a feature for experts, because disabling commands which changes the pen location may distort or destroy the plotter output.

class ezdxf.addons.hpgl2.api.Plotter(backend: Backend)

The Plotter class represents a virtual plotter device.

The HPGL/2 commands send by the Interpreter are processed into simple polylines and filled polygons and send to low level Backend.

HPGL/2 uses a units system called “Plot Units”:

  • 1 plot unit (plu) = 0.025mm

  • 40 plu = 1 mm

  • 1016 plu = 1 inch

The Plotter device does not support font rendering and page rotation (RO). The scaling commands IP, RP, SC are supported.

Recorder

class ezdxf.addons.hpgl2.api.Recorder

The Recorder class records the output of the Plotter class.

All input coordinates are page coordinates:

  • 1 plot unit (plu) = 0.025mm

  • 40 plu = 1 mm

  • 1016 plu = 1 inch

player() Player

Returns a Player instance with the original recordings. Make a copy of this player to protect the original recordings from being modified:

safe_player = recorder.player().copy()
draw_polyline(properties: Properties, points: Sequence[Vec2]) None

Draws a polyline from a sequence points. The input coordinates are page coordinates in plot units. The points sequence can contain 0 or more points!

Parameters:
  • properties – display Properties for the polyline

  • points – sequence of ezdxf.math.Vec2 instances

draw_paths(properties: Properties, paths: Sequence[Path], filled: bool) None

Draws filled or outline paths from the sequence of paths. The input coordinates are page coordinates in plot units. The paths sequence can contain 0 or more single Path instances. Draws outline paths if Properties.FillType is NONE and filled paths otherwise.

Parameters:
  • properties – display Properties for the filled polygon

  • paths – sequence of single ezdxf.path.Path instances

  • filled – draw filled paths if True otherwise outline paths

Player

class ezdxf.addons.hpgl2.api.Player(records: list[DataRecord], properties: dict[int, Properties])

This class replays the recordings of the Recorder class on another backend. The class can modify the recorded output.

copy() Self

Returns a new Player instance with a copy of recordings.

recordings() Iterator[tuple[RecordType, Properties, Any]]

Yields all recordings as (RecordType, Properties, Data) tuples.

The content of the Data field is determined by the enum RecordType:

  • RecordType.POLYLINE returns a NumpyPoints2d instance

  • RecordType.FILLED_POLYGON returns a tuple of NumpyPath2d instances

replay(backend: Backend) None

Replay the recording on another backend.

bbox() BoundingBox2d

Returns the bounding box of all recorded polylines and polygons as BoundingBox2d.

transform(m: Matrix44) None

Transforms the recordings by a transformation matrix m of type Matrix44.

sort_filled_paths() None

Sort filled paths by descending luminance (from light to dark).

This also changes the plot order in the way that all filled paths are plotted before polylines and outline paths.

Properties

class ezdxf.addons.hpgl2.properties.Properties

Consolidated display properties.

pen_index

pen index as int

pen_color

pen color as RGB tuple

pen_width

pen width in millimeters (float)

fill_type

FillType of filled polygons

fill_method

FillMethod of filled polygons

fill_hatch_line_angle

fill hatch line angle in degrees

fill_hatch_line_spacing

fill hatch line distance in plotter units

fill_shading_density

fill shading density in percent from 0 to 100.

resolve_pen_color() RGB

Returns the final RGB pen color.

resolve_fill_color() RGB

Returns the final RGB fill color.

class ezdxf.addons.hpgl2.properties.FillType(value, names=_not_given, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Fill type enumeration.

NONE
SOLID
HATCHING
CROSS_HATCHING
SHADING
class ezdxf.addons.hpgl2.properties.FillMethod(value, names=_not_given, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Fill method enumeration.

EVEN_ODD
NONE_ZERO_WINDING

Exceptions

class ezdxf.addons.hpgl2.api.Hpgl2Error

Base exception for the hpgl2 add-on.

class ezdxf.addons.hpgl2.api.Hpgl2DataNotFound

No HPGL/2 data was found, maybe the “Enter HPGL/2 mode” escape sequence is missing.

class ezdxf.addons.hpgl2.api.EmptyDrawing

The HPGL/2 commands do not produce any content.