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¶
Exports the HPGL/2 commands of the byte stream b as a DXF document. |
|
Exports the HPGL/2 commands of the byte stream b as SVG string. |
|
Exports the HPGL/2 commands of the byte stream b as PDF data. |
|
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 toColorMode.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.
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 thePlotter
class. Therun()
methods interprets the low level HPGL commands from thehpgl2_commands()
parser and sends the commands to the virtual plotter device, which sends his output to a low levelBackend
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 levelBackend
.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 thePlotter
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 polylinepoints – 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 polygonpaths – sequence of single
ezdxf.path.Path
instancesfilled – 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.- 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 aNumpyPoints2d
instanceRecordType.FILLED_POLYGON
returns a tuple ofNumpyPath2d
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_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.
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.