--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hpgl_parser.py Fri Dec 21 23:51:36 2007 +0100 @@ -0,0 +1,408 @@ +# -*- coding: utf-8 -*- + +import re +import numpy + +vsplitter = re.compile('[ ,]') +vextractor = re.compile('(?P<value>[^;\n\r\aA-DF-Za-df-z]*?)(?P<terminator>[;\n\r\a]+)', re.S+re.M) + +class HPGLParser(object): + def __init__(self, data): + self.data = data + self.idx = 0 + self.str_terminator = chr(0x03) + + self.IN() + + while self.idx<len(data): + while data[self.idx] in [';','\n','\r', '\a', ' ']: + self.idx += 1 + if data[self.idx] == chr(0x03): + self.ESC() + else: + cmd = data[self.idx: self.idx+2] + self.idx += 2 + getattr(self, cmd)() + while self.idx<len(data) and data[self.idx] in [';','\n','\r', '\a', ' ']: + self.idx += 1 + + def user_to_abs(self, pos): + """ + converts a position (x, y) given in user units to absolute + units + """ + return pos #TODO + + def extract_value(self, raw=False): + m = vextractor.match(self.data[self.idx:]) + if m: + val = m.group("value") + self.idx = self.idx + len(val) + len(m.group("terminator")) + val = vsplitter.split(val) + if not raw: + val = [eval(x) for x in val if x.strip()] + return val + return [] + + def extract_string(self): + idx2 = self.data.find(self.str_terminator, self.idx) + val = self.data[self.idx: idx2] + self.idx = idx2+1 + return val + + def polyline(self, values): + if (len(values)%2) == 1: + # this is a syntax error in the HPGL data + values = values[:-1] + values = numpy.array(values).reshape(-1, 2) + # TODO use scaling + # do plots + values = numpy.r_[[self.pos], values] #add self.pos as 1st value + if self.plot_mode == 'relative': + values = values.cumsum(axis=0) + if self.symbol_mode: + self.plot_symbols(values[1:]) + if self.pen_state == "down": + self.plot_lines(values) + self.pos = values[-1] + + def get_window_for_paper(self): + return 0,100,0,100 + def get_scaling_points_for_paper(self): + return 0,100,0,100 + + # effective plot methods; to be defined in subclasses (backends) + def plot_symbols(self, points): + pass + def plot_lines(self, points): + pass + + # HPGL-related methods + def ESC(self): + print "ESC" + self.idx += 1 + + def OE(self): + """ Output Error """ + pass + + def EC(self): + """? what's this """ + values = self.extract_value() + + def OO(self): + """idem""" + pass + + def OP(self): + """idem""" + pass + + def VS(self): + """idem""" + pass + + + def DF(self): + """ Default """ + self.pen = 0 + self.pos = 0,0 + self.char_set = "std" + self.plot_mode = 'absolute' + self.char_direction = 1,0 + self.line_type = 0 # 'solid' + self.pattern_len = 4 #percentage + self.window = self.get_window_for_paper() + self.char_size = 0.75, 1.5 #percentages + self.symbol_mode = False + self.tick_len = 0.5, 0.5 # % + self.std_char_set = 0 + self.alt_char_set = 0 + self.selected_char_set = 0 + self.char_slant = 0 # degrees + self.scale = None + self.str_terminator = chr(0x03) + self.chord_ang = 5 #degrees + self.fill_type = 'bidirectionnal', 1 + self.fill_distance = 1 # % + self.fill_slant = 0 # degrees + self.pen_thickness = 0.3 # mm + + def IN(self): + """ Initialize """ + self.DF() + self.pen_state = "up" + self.rotation = 0 #degrees + self.scaling_points = self.get_scaling_points_for_paper() + + def IP(self): + """ Input Scale Point""" + values = self.extract_value() + if len(values) == 0: + self.scaling_points = self.get_scaling_points_for_paper() + elif len(values) == 2: + p1x, p1y, p2x, p2y = self.scaling_points + dx, dy = p2x-p1x, p2y-p1y + x, y = values + self.scaling = (x, y, x+dx, y+dy) + elif len(values) == 4: + self.values = tuple(values) + + def SC(self): + """ Scale """ + values = self.extract_value() + if len(values) == 4: + self.scale = tuple(values) + else: + self.scale = None + + def IW(self): + values = self.extract_value() + if len(values) == 0: + self.window = self.get_window_for_paper() + elif len(value) == 4: + self.window = tuple(values) + + def RO(self): + values = self.extract_value() + if len(values) == 0: + self.rotation = 0 + elif len(values) == 1: + self.rotation = values[0] + + def PG(self): + pass + + def PU(self): + """ Pen Up""" + self.pen_state = "up" + values = self.extract_value() + self.polyline(values) + + def PD(self): + """ Pen Down """ + self.pen_state = "down" + values = self.extract_value() + self.polyline(values) + + def PA(self): + """ Plot Absolute """ + self.plot_mode = "absolute" + values = self.extract_value() + self.polyline(values) + + def PR(self): + """ Plot Relative """ + self.plot_mode = "relative" + values = self.extract_value() + self.polyline(values) + + def AA(self): + """ Arc Absolute """ + values = self.extract_value() + if len(values) in [3, 4]: + x, y, qc = values[:3] + if len(values)==4: + qd = values[-1] + else: + qd = self.chord_ang + # TODO : plot arc + print "plotting an arc" + def AR(self): + """ Arc Relative """ + values = self.extract_value() + # TODO + + def CI(self): + """ Circle Plot""" + values = self.extract_value() + # TODO + + def EA(self): + """Edge Rectangle Absolute""" + values = self.extract_value() + # TODO + + def ER(self): + """Edge Rectangle Relative""" + values = self.extract_value() + # TODO + + def EW(self): + """ Edge Wedge """ + values = self.extract_value() + # TODO + + def RA(self): + """ Fill Rectangle Absolute """ + values = self.extract_value() + # TODO + + def RR(self): + """ Fill Rectangle Relative """ + values = self.extract_value() + # TODO + + def WG(self): + """ Fill Wedge """ + values = self.extract_value() + # TODO + + def FT(self): + """ Fill Type """ + values = self.extract_value() + # TODO + + def LT(self): + """ Line Type """ + values = self.extract_value() + + if len(values)==0: + self.line_type = 0 #'solid' + else: + self.line_type = values[0] + if len(values)>1: + self.pattern_len = values[1] + + def PW(self): + """ Pen Width """ + values = self.extract_value() + if len(values) == 1: + self.pen_thickness = values[0] + + def SM(self): + """ Symbol Mode """ + values = self.extract_value() + if len(values) == 0: + self.symbol_mode = False + elif len(values) == 1: + self.symbol_mode = values[0] + + def SP(self): + """ Select Pen """ + values = self.extract_value() + if len(values) == 1: + self.pen = values[0] + + def TL(self): + """ Tick Len """ + values = self.extract_value() + # TODO + + def XT(self): + """ X-axis Tick """ + # TODO + print "X ticks" + + def YT(self): + """ X-axis Tick """ + # TODO + print "Y ticks" + + def PT(self): + """ Pen Thickness Select """ + values = self.extract_value() + if len(values) == 0: + self.pen_thickness = 0.3 + elif len(values) == 1: + self.pen_thickness = values[0] + + def CS(self): + """ Standard Character Set """ + values = self.extract_value() + if len(values) == 0: + self.std_char_set = 0 + elif len(values) == 1: + self.std_char_set = values[0] + + def CA(self): + """ Alternate Character Set """ + values = self.extract_value() + if len(values) == 0: + self.alt_char_set = 0 + elif len(values) == 1: + self.alt_char_set = values[0] + + def SS(self): + """ Select Standard Character Set """ + self.char_set = "std" + + def SA(self): + """ Select Alternate Character Set """ + self.char_set = "alt" + + def DT(self): + """ Define Label Terminator """ + values = self.extract_value(raw=True) + if len(values) == 0: + self.str_terminator = chr(0x03) + elif len(values) == 1: + self.str_terminator = values[0] + + def LB(self): + """ Character Plot """ + values = self.extract_string() + # TODO + + def DI(self): + """ Absolute Direction """ + values = self.extract_value() + if len(values) == 0: + self.char_direction = 1.0, 0.0 + elif len(values) == 2: + self.char_direction = values + + def DR(self): + """ Relative Direction """ + values = self.extract_value() + if len(values) == 0: + self.char_direction = 1.0, 0.0 + elif len(values) == 2: + # TODO : compute as percentages + self.char_direction = values + + def CP(self): + """ Character Plot """ + values = self.extract_value() + # TODO + if len(values) == 0: + values = 0, -1 + #if len(values) == 2: + # self.pos = + + def SI(self): + """ Set Absolute Character Size """ + values = self.extract_value() + self.char_size = "absolute" + if len(values) == 0: + self.char_width = 0.1879 + self.char_height = 0.2690 + elif len(values) == 2: + self.char_width, self.char_height = values + + def SR(self): + """ Set Relative Character Size """ + values = self.extract_value() + self.char_size = "relative" + if len(values) == 0: + self.char_width = 0.75 + self.char_height = 1.5 + elif len(values) == 2: + self.char_width, self.char_height = values + + def SL(self): + """ Character Slant """ + values = self.extract_value() + # TODO + + def UC(self): + """ User Defined Character """ + values = self.extract_value() + # TODO + +if __name__ == '__main__': + import sys + data = open(sys.argv[1]).read() + + p = HPGLParser(data) +