class DXFLoader(GenericLoader): functions={ "POP_TRAFO": 'pop_trafo', "TABLE": 'load_TABLE', "BLOCK": 'load_BLOCK', "LINE": 'load_line', "LWPOLYLINE": 'load_lwpolyline', "POLYLINE": 'load_polyline', "SEQEND": 'load_seqend', "VERTEX": 'load_vertex', "CIRCLE": 'load_circle', "ARC": 'load_arc', "ELLIPSE": 'load_ellips', "POINT": 'load_point', "SOLID": 'load_solid', "INSERT": 'load_insert', "TEXT": 'load_text', #"MTEXT": 'load_text', "3DFACE": 'load_3dface', "SPLINE": 'load_spline', "VIEWPORT": 'load_bypass', } def __init__(self, file, filename, match): GenericLoader.__init__(self, file, filename, match) self.file = file self.DWGCODEPAGE = 'latin1' self.unit_to_pt = 2.83464566929 self.dynamic_style_dict = {} self.style_dict = {} self.ltype_dict = {'CONTINUOUS': { '2': 'CONTINUOUS', # Linetype name '3': 'Solid line', # Descriptive text for linetype '49': [], # Dash, dot or space length #(one entry per element) } } self.layer_dict = {'0': { '2': '0', # Layer name '6': 'CONTINUOUS', #Linetype name '62': 0, # Color number '370': None, #Line weight } } self.block_dict = {} self.stack = [] self.stack_trafo = [] self.default_layer = '0' self.default_style = 'STANDARD' self.default_block = None self.default_line_width = 30 self.EXTMIN = (1e+20, 1e+20) self.EXTMAX = (-1e+20, -1e+20) self.PEXTMIN = (1e+20, 1e+20) self.PEXTMAX = (-1e+20, -1e+20) self.general_param = { '8': self.default_layer, # Layer name '6': 'BYLAYER', # Linetype name '62': 256, # Color number '48': 1.0, # Linetype scale #'60': 0, # Object visibility. If 1 Invisible } self.curstyle = Style() self.update_trafo() def update_trafo(self, scale = 1): EXT_hight = self.EXTMAX[0] - self.EXTMIN[0] EXT_width = self.EXTMAX[1] - self.EXTMIN[1] PEXT_hight = self.PEXTMAX[0] - self.PEXTMIN[0] PEXT_width = self.PEXTMAX[1] - self.PEXTMIN[1] if EXT_hight > 0: scale = 840 / max(EXT_hight, EXT_width) self.unit_to_pt = scale x = self.EXTMIN[0] * scale y = self.EXTMIN[1] * scale elif PEXT_hight > 0: scale = 840 / max(PEXT_hight, PEXT_width) self.unit_to_pt = scale x = self.PEXTMIN[0] * scale y = self.PEXTMIN[1] * scale else: x = 0 y = 0 self.trafo = Trafo(scale, 0, 0, scale, -x, -y) def push_trafo(self, trafo = None): # save trafo in stack_trafo if trafo is None: trafo = self.trafo self.stack_trafo.append(trafo) def pop_trafo(self): self.trafo = self.stack_trafo.pop() def get_pattern(self, color_index): # 0 = Color BYBLOCK if color_index == 0: block_name = self.default_block if block_name is None: layer_name = '0' else: layer_name = self.block_dict[block_name]['8'] color_index = self.layer_dict[layer_name]['62'] # 256 = Color BYLAYER if color_index == 256 or color_index is None: layer_name = self.default_layer color_index = self.layer_dict[layer_name]['62'] ## FIXMY 257 = Color BYENTITY if color_index < 0: pattern = EmptyPattern else: pattern = SolidPattern(colors[color_index]) return pattern def get_line_width(self, layer_name = None): if layer_name is None: layer_name = self.default_layer layer = self.layer_dict[layer_name] if '370' in layer: width = layer['370'] if width == -3 or width is None: width = self.default_line_width width = width * 72.0 / 2.54 /1000 # th 100 mm to pt if width <= 0.0: # XXX width = 0.1 return width def get_line_type(self, linetype_name = None, scale = 1.0, width = 1.0, layer_name = None): #if linetype_name == 'BYBLOCK': #block_name = self.default_block #layer_name = self.block_dict[block_name]['8'] if layer_name is None: layer_name = self.default_layer if linetype_name is None or linetype_name == 'BYLAYER' or linetype_name == 'BYBLOCK': linetype_name = self.layer_dict[layer_name]['6'] linetype = self.ltype_dict[upper(linetype_name)]['49'] lscale = scale * self.unit_to_pt / width dashes = map(lambda i : abs(linetype[i]) * lscale, xrange(len(linetype))) return tuple(dashes) def get_line_style(self, **kw): if kw['8'] in self.layer_dict: self.default_layer = layer_name = kw['8'] else: layer_name = self.default_layer linetype_name = upper(kw['6']) scale = kw['48'] color_index = kw['62'] style = Style() style.line_width = self.get_line_width() style.line_join = const.JoinRound style.line_cap = const.CapRound style.line_dashes = self.get_line_type(linetype_name = linetype_name, scale = scale, width = style.line_width) style.line_pattern = self.get_pattern(color_index) return style ################ # HEADER Section # def load_HEADER(self): return_code = False header_dict = {} variable = None params = {} line1, line2 = self.read_record() while line1 or line2: if variable and (line1 == '9' or line1 == '0'): header_dict[variable] = params else: params[line1] = line2 if line1 == '0' and line2 == 'ENDSEC': return_code = True break elif line1 == '9': params = {} variable = line2 line1, line2 = self.read_record() return return_code, header_dict def process_header(self, header): if '$DWGCODEPAGE' in header: self.DWGCODEPAGE = 'cp'+ upper(header['$DWGCODEPAGE']['3']).replace('ANSI_', '').replace('DOS','') if '$INSUNITS' in header: INSUNITS = convert('70', header['$INSUNITS']['70']) if INSUNITS in unit: self.unit_to_pt = unit[INSUNITS] if '$EXTMIN' in header: param10 = convert('10', header['$EXTMIN']['10']) param20 = convert('20', header['$EXTMIN']['20']) self.EXTMIN = (param10, param20) if '$EXTMAX' in header: param10 = convert('10', header['$EXTMAX']['10']) param20 = convert('20', header['$EXTMAX']['20']) self.EXTMAX = (param10, param20) if '$PEXTMIN' in header: param10 = convert('10', header['$PEXTMIN']['10']) param20 = convert('20', header['$PEXTMIN']['20']) self.PEXTMIN = (param10, param20) if '$PEXTMAX' in header: param10 = convert('10', header['$PEXTMAX']['10']) param20 = convert('20', header['$PEXTMAX']['20']) self.PEXTMAX = (param10, param20) self.update_trafo() if '$CLAYER' in header: self.default_layer = convert('8', header['$CLAYER']['8'], self.DWGCODEPAGE) ################ # TABLES Section # def load_TABLE(self): param={ '2': '', # Table name '70': 0 # Maximum number of entries in table } param = self.read_param(param) table_name = param['2'] table_number = param['70'] print '****', table_name, table_number line1, line2 = self.read_record() while line1 or line2: if line1 == '0' and line2 == 'ENDTAB': break if table_name == 'LTYPE': self.load_LTYPE() elif table_name == 'LAYER': self.load_LAYER() elif table_name == 'STYLE': self.load_STYLE() line1, line2 = self.read_record() def load_LTYPE(self): param={ '2': '', # Linetype name '3': '', # Descriptive text for linetype #'73': 0, # The number of linetype elements #'40': 0, # Total pattern length '49': [], # Dash, dot or space length (one entry per element) } param = self.read_param(param, [0]) name = upper(param['2']) if name: self.ltype_dict[name] = param dashes = [] for i in xrange(len(param['49'])): dashes.append(abs(param['49'][i]) * self.unit_to_pt) name3 = param['3'] #print name3, dashes if name3 and dashes: style = Style() style.line_dashes = tuple(dashes) style = style.AsDynamicStyle() style.SetName(name + name3) self.dynamic_style_dict[name] = style def load_LAYER(self): param={ '2': None, # Layer name '6': None, #Linetype name '62': 0, # Color number '370': None, #Line weight } param = self.read_param(param, [0]) layer_name = param['2'] if layer_name: self.layer_dict[layer_name]=param self.layer(name = layer_name) def load_STYLE(self): param={ '2': None, # Style name '70': 0, # Flag '40': 0.0, # Fixed text height; 0 if not fixed '41': 0.0, # Width factor '42': 0.0, # Last height used '50': 0.0, # Oblique angle '71': 0, # Text generation flags '3': None, # Primary font file name '4': None, # Bigfont file name '1000': None, } param = self.read_param(param, [0]) style_name = upper(param['2']) self.style_dict[style_name] = param ################ # BLOCKS Section # def load_BLOCK(self): param={ '2': '', # Block name '10': 0.0, # X Base point '20': 0.0, # Y Base point #'30': 0.0, # Z Base point '8': self.default_layer, # Layer name 'data': [], # block data } param = self.read_param(param) block_name = param['2'] print '****', block_name line1, line2 = self.read_record() while line1 or line2: if line1 == '0' and line2 == 'ENDBLK': param = self.read_param(param) break param['data'].append(line1) param['data'].append(line2) line1, line2 = self.read_record() param['data'].reverse() self.block_dict[block_name] = param # print self.block_dict[block_name] ################ # ENTITIES Section # def load_line(self): param={ '10': None, # X coordinat '20': None, # y coordinat #'30': None, # Z coordinat '11': None, # X coordinat endpoint '21': None, # y coordinat endpoint #'31': None, # z coordinat endpoint } param.update(self.general_param) param = self.read_param(param) self.path = CreatePath() self.path.AppendLine(self.trafo(param['10'], param['20'])) self.path.AppendLine(self.trafo(param['11'], param['21'])) style = self.get_line_style(**param) self.prop_stack.AddStyle(style.Duplicate()) self.bezier(self.path,) def load_lwpolyline(self): param={ '90': 0, # Number of vertices '70': 0, # bit codes for Polyline entity '40': None, # Starting width '43': 0, '370': None, #Line weight } param.update(self.general_param) param = self.read_param(param,[10,20,42]) if param['40'] is not None: line_width = param['40'] * self.unit_to_pt else: line_width = param['43'] * self.unit_to_pt if param['370'] is not None: line_width = param['370'] * self.unit_to_pt * 72.0 / 2.54 /1000 self.curstyle = self.get_line_style(**param) # if Group 70 Flag bit value set 1 This is a closed Polyline path_flag = param['70'] vertex_path = [] for i in xrange(param['90']): vertex={ '10': None, # X coordinat '20': None, # Y coordinat '42': 0.0 # Bulge } # 10 line1, line2 = self.read_record() vertex[line1] = convert(line1, line2, self.DWGCODEPAGE) # 20 line1, line2 = self.read_record() vertex[line1] = convert(line1, line2, self.DWGCODEPAGE) # 42 line1, line2 = self.read_record() if line1 == '42': vertex[line1] = convert(line1, line2, self.DWGCODEPAGE) else: self.push_record(line1, line2) vertex_path.append((vertex['10'], vertex['20'], vertex['42'])) self.load_seqend(vertex_path, path_flag) def load_polyline(self): param={ '70': 0, # bit codes for Polyline entity '40': 0.01, #XXX FIXMY } param.update(self.general_param) param = self.read_param(param) self.vertex_path = [] self.curstyle.line_width=param['40'] * 72 # XXX self.unit_to_pt self.curstyle.line_pattern = self.get_pattern(param['62']) # if Group 70 Flag bit value set 1 This is a closed Polyline self.path_flag = param['70'] def load_vertex(self): param={#'62': 7, # color #'6': 'CONTINUOUS', # style '10': None, # X coordinat '20': None, # Y coordinat '42': 0.0 # Bulge } param = self.read_param(param) self.vertex_path.append((param['10'], param['20'], param['42'])) def load_seqend(self, line = None, path_flag = None): if line is None: line = self.vertex_path if path_flag is None: path_flag = self.path_flag if path_flag > 1: print 'FIXMY. Curves and smooth surface type', path_flag close_path = path_flag & 1 == 1 path = CreatePath() if len(line): for i in line: x, y, bulge = i #print x, y, bulge path.AppendLine(self.trafo(x, y)) if close_path: if path.Node(0) != path.Node(-1): path.AppendLine(path.Node(0)) path.ClosePath() self.prop_stack.AddStyle(self.curstyle.Duplicate()) self.bezier(path,) def load_circle(self): param={ '10': None, # X coordinat center '20': None, # Y coordinat center #'30': None, # Z coordinat center '40': 0.0 # radius } param.update(self.general_param) param = self.read_param(param) x = param['10'] y = param['20'] r = param['40'] t = self.trafo(Trafo(r,0,0,r,x,y)) style = self.get_line_style(**param) self.prop_stack.AddStyle(style.Duplicate()) apply(self.ellipse, t.coeff()) def load_arc(self): param={ '10': None, # X coordinat center '20': None, # Y coordinat center #'30': None, # Z coordinat center '40': 0.0, # radius '50': 0.0, # Start angle '51': 0.0 # End angle } param.update(self.general_param) param = self.read_param(param) cx = param['10'] cy = param['20'] rx = ry = param['40'] start_angle = param['50'] * degrees end_angle = param['51'] * degrees trafo = self.trafo(Trafo(rx, 0, 0, ry, cx, cy)) rx, w1, w2, ry, cx, cy = trafo.coeff() style = self.get_line_style(**param) self.prop_stack.AddStyle(style.Duplicate()) apply(self.ellipse, (rx, w1, w2, ry, cx, cy, start_angle, end_angle, ArcArc)) def load_ellips(self): param={ '10': 0.0, # X coordinat center '20': 0.0, # Y coordinat center #'30': 0.0, # Z coordinat center '11': 0.0, # Endpoint of major axis, relative to the center '21': 0.0, #'31': 0.0, '40': 0.0, # Ratio of minor axis to major axis '41': 0.0, # Start parameter (this value is 0.0 for a full ellipse) '42': 0.0, # End parameter (this value is 2pi for a full ellipse) } param.update(self.general_param) param = self.read_param(param) cx = param['10'] cy = param['20'] rx = sqrt(param['21']**2 + param['11']**2) ry = rx * param['40'] start_angle = param['41'] end_angle = param['42'] angle=atan2(param['21'], param['11']) center = self.trafo(cx, cy) radius = self.trafo.DTransform(rx, ry) trafo = Trafo(radius.x, 0, 0, radius.y) trafo = Rotation(angle)(trafo) trafo = Translation(center)(trafo) rx, w1, w2, ry, cx, cy = trafo.coeff() style = self.get_line_style(**param) self.prop_stack.AddStyle(style.Duplicate()) apply(self.ellipse, (rx, w1, w2, ry, cx, cy, start_angle, end_angle, ArcArc)) def load_point(self): param={ '10': None, # X coordinat center '20': None, # Y coordinat center #'30': None, # Z coordinat center } param.update(self.general_param) param = self.read_param(param) x = param['10'] y = param['20'] r = 0.3 t = self.trafo(Trafo(r,0,0,r,x,y)) style = self.curstyle.Duplicate() style.line_pattern = EmptyPattern style.fill_pattern = self.get_pattern(param['62']) self.prop_stack.AddStyle(style.Duplicate()) apply(self.ellipse, t.coeff()) def load_solid(self): param={ '10': None, '20': None, #'30': None, '11': None, '21': None, #'31': None, '12': None, '22': None, #'32': None, '13': None, '23': None, #'33': None, } param.update(self.general_param) param = self.read_param(param) style = self.curstyle.Duplicate() style.line_pattern = EmptyPattern style.fill_pattern = self.get_pattern(param['62']) self.path = CreatePath() self.path.AppendLine(self.trafo(param['10'], param['20'])) self.path.AppendLine(self.trafo(param['11'], param['21'])) self.path.AppendLine(self.trafo(param['12'], param['22'])) self.path.AppendLine(self.trafo(param['13'], param['23'])) self.path.ClosePath() self.prop_stack.AddStyle(style.Duplicate()) self.bezier(self.path,) def load_insert(self): param={ '2': None, # Block name '10': 0.0, # X coordinat '20': 0.0, # Y coordinat #'30': 0.0, # Z coordinat '41': 1.0, # X scale factor '42': 1.0, # Y scale factor #'43': 1.0, # Z scale factor '50': 0.0, # Rotation angle '66': 0, # Attributes-follow flag } param = self.read_param(param) block_name = self.default_block = param['2'] if block_name: self.stack += ['POP_TRAFO', '0'] + self.block_dict[block_name]['data'] self.push_trafo() x = param['10'] y = param['20'] block_x = self.block_dict[block_name]['10'] block_y = self.block_dict[block_name]['20'] scale_x = param['41'] * self.trafo.m11 scale_y = param['42'] * self.trafo.m22 angle = param['50'] * degrees translate = self.trafo(x, y) trafo = Trafo(1, 0, 0, 1, -block_x, -block_y) trafo = Scale(scale_x,scale_y)(trafo) trafo = Rotation(angle)(trafo) trafo = Translation(translate)(trafo) self.trafo = trafo if param['66'] != 0: line1, line2 = self.read_record() while line1 or line2: if line1 == '0' and line2 == 'SEQEND': break else: if line1 == '0': self.run(line2) line1, line2 = self.read_record() def load_text(self): param={ '10': 0.0, '20': 0.0, '40': None, # Text height '1': '', # Default value '50': 0, # Text rotation '41': 1, # Relative X scale factor—width # '8': self.default_layer, # Layer name '7': self.default_style, # Style name '72': 0, #Horizontal text justification type } param.update(self.general_param) param = self.read_param(param) x = param['10'] y = param['20'] scale_x = param['41'] scale_y = 1 angle = param['50'] * pi / 180 font_size = param['40'] * self.trafo.m11 halign = [ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, \ ALIGN_LEFT, ALIGN_LEFT, ALIGN_LEFT][param['72']] text = unicode_decoder(param['1'], self.DWGCODEPAGE) #style = self.style_dict[param['7']] # print style style_text = self.curstyle.Duplicate() style_text.line_pattern = EmptyPattern style_text.fill_pattern = self.get_pattern(param['62']) style_name = upper(param['7']) style = self.style_dict[style_name] font_name = style['1000'] if font_name == 'Arial': # XXX font_name = 'ArialMT' style_text.font = GetFont(font_name) # print style_text.font style_text.font_size = font_size trafo_text = Translation(self.trafo(x, y))(Rotation(angle))(Scale(scale_x, scale_y)) self.prop_stack.AddStyle(style_text.Duplicate()) self.simple_text(strip(text), trafo_text, halign = halign) def load_3dface(self): param={ '10': None, '20': None, #'30': None, '11': None, '21': None, #'31': None, '12': None, '22': None, #'32': None, '13': None, '23': None, #'33': None, '70': 0, # Invisible edge flags } param.update(self.general_param) param = self.read_param(param) self.path = CreatePath() if param['70'] != 0: print 'FIXMY. 3dface Invisible edge flags', param['70'] self.path.AppendLine(self.trafo(param['10'], param['20'])) self.path.AppendLine(self.trafo(param['11'], param['21'])) self.path.AppendLine(self.trafo(param['12'], param['22'])) self.path.AppendLine(self.trafo(param['13'], param['23'])) self.path.ClosePath() style = self.get_line_style(**param) self.prop_stack.AddStyle(style.Duplicate()) self.bezier(self.path,) def load_spline(self): param={ '70': 0, # Spline flag '71': 0, # Degree of the spline curve '72': 0, # Number of knots '73': 0, # Number of control points '74': 0, # Number of fit points '40': [], # Knot value '10': [], # Control points X '20': [], # Control points Y #'30': [], # Control points Z } param.update(self.general_param) param = self.read_param(param) closed = param['70'] & 1 path = CreatePath() f13 = 1.0 / 3.0 f23 = 2.0 / 3.0 curve = path.AppendBezier straight = path.AppendLine pts = map(lambda x, y: self.trafo(x, y), param['10'],param['20']) print 'SPLINE', param['70'], len(pts) #for i in range(0, len(pts)-1): #self.ellipse(.2, 0, 0, .2, pts[i][0],pts[i][1]) if param['70'] <= 1: straight(pts[0]) for i in range(1, len(pts) / 4): node = pts[i * 4] c1 = pts[i * 4 - 3] c2 = pts[i * 4 - 2] print c1, c2, node curve(c1, c2, node) #straight(node) if closed: curve(pts[-3], pts[-2], pts[0]) else: curve(pts[-4], pts[-4], pts[-1]) if param['70'] & 4 == 4: last = pts[0] cur = pts[1] start = node = (last + cur) / 2 if closed: straight(node) else: straight(last) straight(node) last = cur for cur in pts[2:]: c1 = f13 * node + f23 * last node = (last + cur) / 2 c2 = f13 * node + f23 * last curve(c1, c2, node) last = cur if closed: curve(f13 * node + f23 * last, f13 * start + f23 * last, start) else: straight(last) if param['70'] & 8 == 8: node = pts[0] c1 = pts[1] c2 = pts[2] # first node straight(node) if len(pts) > 4: c2 = (pts[2] + pts[1]) / 2 c3 = pts[3] * f13 + pts[2] * f23 node = (c3 + c2) / 2 curve(c1, c2, node) c1 = c3 for i in range(3, len(pts) - 3): c2 = pts[i - 1] * f13 + pts[i] * f23 c3 = pts[i] * f23 + pts[i + 1] * f13 node = (c3 + c2) / 2 curve(c1, c2, node) c1 = c3 c2 = pts[-4] * f13 + pts[-3] * f23 c3 = (pts[-3] + pts[-2]) / 2 node = (c3 + c2) / 2 curve(c1, c2, node) c1 = c3 # last node curve(c1, pts[-2], pts[-1]) style = self.get_line_style(**param) self.prop_stack.AddStyle(style.Duplicate()) self.bezier(path,) def load_bypass(self): pass ########################################################################### def get_compiled(self): funclist={} for char, name in self.functions.items(): method = getattr(self, name) argc = method.im_func.func_code.co_argcount - 1 funclist[char] = (method, argc) return funclist def push_record(self, line1, line2): # save data in stack self.stack.append(line2) self.stack.append(line1) def read_record(self): # if the stack is empty read two lines from a file if self.stack: line1 = self.stack.pop() line2 = self.stack.pop() else: line1 = self.file.readline().strip() line2 = self.file.readline().strip() return line1, line2 def read_param(self, param, stop=None): # read data and fill in the dictionary if stop is None: stop = [0, 9] line1, line2 = self.read_record() while line1 or line2: if int(line1) in stop: self.push_record(line1, line2) return param else: if line1 in param: value = convert(line1, line2, self.DWGCODEPAGE) if type(param[line1]) == list: param[line1].append(value) else: param[line1] = value line1,line2 = self.read_record() return False def find_record(self, code1, code2): # read data until to not overlap line1 == code1 and line2 == code2 # return True # else return False line1, line2 = self.read_record() while line1 or line2: if line1 == code1 and line2 == code2: return True line1, line2 = self.read_record() return False def load_section(self): return_code = False file = self.file parsed = self.parsed parsed_interval = self.parsed_interval line1, line2 = self.read_record() while line1 or line2: interval_count = file.tell() / parsed_interval if interval_count > parsed: parsed += 10 # 10% progress app.updateInfo(inf2 = '%u' % parsed + _('% of file is parsed...'), inf3 = parsed) if line1 == '0' and line2 == 'ENDSEC': return_code = True break elif line1 == '0': self.run(line2) line1, line2 = self.read_record() self.parsed = parsed return return_code def load_sections(self): return_code = False param={ '2': '', # name section } param = self.read_param(param) name=param['2'] print '**',name if name == 'HEADER': return_code, header_dict = self.load_HEADER() self.process_header(header_dict) elif name == 'CLASSES': return_code = self.find_record('0','ENDSEC') elif name == 'OBJECTS': return_code = self.find_record('0','ENDSEC') elif name == 'THUMBNAILIMAGE': return_code = self.find_record('0','ENDSEC') else: return_code = self.load_section() return return_code def interpret(self): file = self.file if type(file) == StringType: file = open(file, 'r') file.seek(0) readline = file.readline fileinfo = os.stat(self.filename) totalsize = fileinfo[6] self.parsed = 0 self.parsed_interval = totalsize / 99 + 1 line1, line2 = self.read_record() while line1 or line2: if line1 == '0': if line2 == 'EOF': break elif not self.load_sections(): warn_tb(INTERNAL, _('DXFLoader: error. Non find end of sections')) line1, line2 = self.read_record() def run(self,keyword, *args): if keyword is None: return return_code = False unknown_operator = (None, None) funclist = self.funclist if keyword is not None: method, argc = funclist.get(keyword, unknown_operator) if method is not None: try: ##print '******', keyword if len(args): i = 0 while i<len(args): return_code = apply(method, args[i:argc+i]) i+=argc else: return_code = method() except: warn_tb(INTERNAL, 'DXFLoader: error') else: self.add_message(_('Not interpreted %s') % keyword) return return_code def Load(self): import time start_time = time.clock() #print ' ************ "DXF_objects" **************' self.funclist = self.get_compiled() self.document() self.layer(name = _("DXF_objects")) self.interpret() self.end_all() for style in self.dynamic_style_dict.values(): self.object.load_AddStyle(style) self.object.load_Completed() print 'times',time.clock() - start_time return self.object
class WMFLoader(GenericLoader): def __init__(self, file, filename, match): GenericLoader.__init__(self, file, filename, match) self.file = file self.curstyle = Style() self.verbosity = 0 self.gdiobjects = [] self.dcstack = [] self.curpoint = Point(0, 0) def _print(self, format, *args, **kw): if self.verbosity: try: if kw: text = format % kw elif args: text = format % args else: text = format except: text = string.join([format] + map(str, args)) if text[-1] != '\n': text = text + '\n' sys.stdout.write(text) def get_struct(self, format): size = calcsize(format) return unpack(format, self.file.read(size)) def get_int16(self): return self.get_struct('<h')[0] def get_int32(self): return self.get_struct('<i')[0] def read_headers(self): self.file.seek(0) placeable = self.file.read(calcsize(struct_placeable_header)) key, handle, left, top, right, bottom, inch, reserved, checksum\ = unpack(struct_placeable_header, placeable) if key != rx_magic: raise SketchLoadError(_("The file is not a placeable " "windows metafile")) self._print("The file is not a placeable windows metafile") sum = 0 for word in unpack('<10h', placeable[:20]): sum = sum ^ word if sum != checksum: #raise SketchLoadError(_("The file has an incorrect checksum")) self._print("The file has an incorrect checksum") self.inch = inch self.bbox = (left, top, right, bottom) factor = 72.0 / self.inch self.wx = self.wy = 0 self.wwidth = right - left self.wheight = bottom - top self.vx = self.vy = 0 self.vwidth = self.wwidth self.vheight = self.wheight self.base_trafo = Trafo(factor, 0, 0, -factor, 0, factor * self.vheight) self.update_trafo() header = self.file.read(calcsize(struct_wmf_header)) filetype, headersize, version, filesize, numobj, maxrecord, numparams\ = unpack(struct_wmf_header, header) self._print('\nHeader\n------\n') fmt = '% 10s: %s\n' self._print(fmt, 'inch', self.inch) self._print(fmt, 'bbox', self.bbox) self._print(fmt, 'headersize', headersize) self._print(fmt, 'version', version) self._print(fmt, 'numobj', numobj) self._print(fmt, 'numparams', numparams) self._print(fmt, 'maxrecord', maxrecord) self._print('\n') def update_trafo(self): wt = Translation(-self.wx, -self.wy) vt = Translation(self.vx, self.vy) scale = Scale(float(self.vwidth) / self.wwidth, float(self.vheight) / self.wheight) self.trafo = self.base_trafo(vt(scale(wt))) def add_gdiobject(self, object): try: idx = self.gdiobjects.index(None) except ValueError: self.gdiobjects.append(object) else: self.gdiobjects[idx] = object def delete_gdiobject(self, idx): self.gdiobjects[idx] = None def SelectObject(self): idx = self.get_int16() try: object = self.gdiobjects[idx] except IndexError: print 'Index Error:', idx, self.gdiobjects raise for property, value in object: setattr(self.curstyle, property, value) self._print('->', idx, object) def DeleteObject(self): idx = self.get_int16() self.delete_gdiobject(idx) self._print('->', idx) def get_dc(self): return self.curstyle.Duplicate(), self.trafo, self.curpoint def set_dc(self, dc): self.curstyle, self.trafo, self.curpoint = dc def SaveDC(self): self.dcstack.append(self.get_dc()) def RestoreDC(self): self.set_dc(self.dcstack[-1]) del self.dcstack[-1] def SetMapMode(self): mode = self.get_int16() self._print('->', mode) def SetWindowOrg(self): self.wy, self.wx = self.get_struct('<hh') self.update_trafo() self._print('->', self.wx, self.wy) def SetWindowExt(self): self.wheight, self.wwidth = self.get_struct('<hh') self.update_trafo() self._print('->', self.wwidth, self.wheight) def SetPolyFillMode(self): mode = self.get_int16() self._print('->', mode) SetBkMode = noop SetBkColor = noop SetROP2 = noop def CreateBrushIndirect(self): style, r, g, b, hatch = self.get_struct('<hBBBxh') if style == 1: pattern = EmptyPattern else: pattern = SolidPattern(CreateRGBColor(r/255.0, g/255.0, b/255.0)) self.add_gdiobject((('fill_pattern', pattern),)) self._print('->', style, r, g, b, hatch) def DibCreatePatternBrush(self): self.add_message(_("Bitmap brushes not yet implemented. Using black")) pattern = SolidPattern(StandardColors.black) self.add_gdiobject((('fill_pattern', pattern),)) def CreatePenIndirect(self): style, widthx, widthy, r, g, b = self.get_struct('<hhhBBBx') cap = (style & 0x0F00) >> 8 join = (style & 0x00F0) >> 4 style = style & 0x000F if style == 5: pattern = EmptyPattern else: pattern = SolidPattern(CreateRGBColor(r/255.0, g/255.0, b/255.0)) width = abs(widthx * self.trafo.m11) self.add_gdiobject((('line_pattern', pattern,), ('line_width', width))) self._print('->', style, widthx, widthy, r, g, b, cap, join) def CreatePalette(self): self.add_gdiobject((('ignore', None),)) def CreateRegion(self): self.add_gdiobject((('ignore', None),)) CreateFontIndirect = CreatePalette SelectPalette = noop RealizePalette = noop SetTextColor = noop SetTextAlign = noop SetTextJustification = noop SetStretchBltMode = noop def read_points(self, num): coords = self.get_struct('<' + num * 'hh') points = []; append = points.append trafo = self.trafo for i in range(0, 2 * num, 2): append(trafo(coords[i], coords[i + 1])) return points def Polyline(self): points = self.read_points(self.get_int16()) if points: path = CreatePath() map(path.AppendLine, points) self.prop_stack.AddStyle(self.curstyle.Duplicate()) self.prop_stack.SetProperty(fill_pattern = EmptyPattern) self.bezier((path,)) #for i in range(len(points)): # self._print('->', points[i]) def Polygon(self): points = self.read_points(self.get_int16()) if points: path = CreatePath() map(path.AppendLine, points) if path.Node(-1) != path.Node(0): #print 'correct polygon' path.AppendLine(path.Node(0)) path.load_close() self.prop_stack.AddStyle(self.curstyle.Duplicate()) self.bezier((path,)) #for i in range(len(points)): # self._print('->', points[i]) def PolyPolygon(self): nr_of_polygons = self.get_int16() nr_of_points = [] for i in range(nr_of_polygons): nr_of_points.append(self.get_int16()) path = () for i in nr_of_points: points = self.read_points(i) if points: subpath = CreatePath() map(subpath.AppendLine, points) if subpath.Node(-1) != subpath.Node(0): subpath.AppendLine(subpath.Node(0)) subpath.load_close() path = path + (subpath,) if path: self.prop_stack.AddStyle(self.curstyle.Duplicate()) self.bezier(path) def MoveTo(self): y, x = self.get_struct('<hh') self.curpoint = self.trafo(x, y) self._print('->', self.curpoint) def LineTo(self): y, x = self.get_struct('<hh') p = self.trafo(x, y) self.prop_stack.AddStyle(self.curstyle.Duplicate()) self.prop_stack.SetProperty(fill_pattern = EmptyPattern) path = CreatePath() path.AppendLine(self.curpoint) path.AppendLine(p) self.bezier((path,)) self.curpoint = p self._print('->', self.curpoint) def Ellipse(self): bottom, right, top, left = self.get_struct('<hhhh') left, top = self.trafo(left, top) right, bottom = self.trafo(right, bottom) self.prop_stack.AddStyle(self.curstyle.Duplicate()) self.ellipse((right - left) / 2, 0, 0, (bottom - top) / 2, (right + left) / 2, (top + bottom) / 2) def Arc(self, arc_type = const.ArcArc): ye, xe, ys, xs, bottom, right, top, left = self.get_struct('<hhhhhhhh') left, top = self.trafo(left, top) right, bottom = self.trafo(right, bottom) xs, ys = self.trafo(xs, ys) xe, ye = self.trafo(xe, ye) self.prop_stack.AddStyle(self.curstyle.Duplicate()) if arc_type == const.ArcArc: self.prop_stack.SetProperty(fill_pattern = EmptyPattern) if left != right and top != bottom: t = Trafo((right - left) / 2, 0, 0, (bottom - top) / 2, (right + left) / 2, (top + bottom) / 2).inverse() # swap start and end-angle end_angle = t(xs, ys).polar()[1] start_angle = t(xe, ye).polar()[1] else: start_angle = end_angle = 0.0 self.ellipse((right - left) / 2, 0, 0, (bottom - top) / 2, (right + left) / 2, (top + bottom) / 2, start_angle = start_angle, end_angle = end_angle, arc_type = arc_type) def Pie(self): self.Arc(const.ArcPieSlice) def Rectangle(self): bottom, right, top, left = self.get_struct('<hhhh') left, top = self.trafo(left, top) right, bottom = self.trafo(right, bottom) self.prop_stack.AddStyle(self.curstyle.Duplicate()) self.rectangle(right - left, 0, 0, bottom - top, left, top) def RoundRect(self): ellh, ellw, bottom, right, top, left = self.get_struct('<hhhhhh') left, top = self.trafo(left, top) right, bottom = self.trafo(right, bottom) ellw, ellh = self.trafo.DTransform(ellw, ellh) self._print('->', left, top, right, bottom, ellw, ellh) self.prop_stack.AddStyle(self.curstyle.Duplicate()) self.rectangle(right - left, 0, 0, bottom - top, left, top, radius1 = abs(ellw / (right - left)), radius2 = abs(ellh / (bottom - top))) def Escape(self): pass def interpret(self): tell = self.file.tell function = -1 while function: pos = tell() size, function = self.get_struct('<ih') self._print('%5d: %4x: %s' % (size, function, wmf_functions.get(function, ''))) if hasattr(self, wmf_functions.get(function, '')): getattr(self, wmf_functions[function])() else: if function: self.file.read(2 * (size - 3)) self._print('*** unimplemented:', wmf_functions.get(function, '')) pos = pos + 2 * size if tell() < pos: self.file.read(pos - tell()) elif tell() > pos: self._print('read too many bytes') self.file.seek(pos - tell(), 1) def Load(self): self.document() self.layer(name = _("WMF objects")) self.read_headers() self.interpret() self.end_all() self.object.load_Completed() return self.object
class DSTLoader(GenericLoader): def __init__(self, file, filename, match): GenericLoader.__init__(self, file, filename, match) self.file = file self.basename, self.ext = os.path.splitext(filename) def initialize(self): self.draw = 0 self.scale = .283464566929 self.cur_x = 0.0 self.cur_y = 0.0 self.palette = Palette(self.basename) self.path = CreatePath() self.cur_style = Style() self.cur_style.line_width = 0.6 self.cur_style.line_join = const.JoinRound self.cur_style.line_cap = const.CapRound self.cur_style.line_pattern = self.palette.next_color(1) def readInt32(self, file): try: data = unpack('<I', file.read(4))[0] except: data = None return data def readInt8(self, file): try: data = int(unpack('B', file.read(1))[0]) except: data = None return data def get_position(self, x=None, y=None): if x is None: x = self.cur_x else: x = float(x) * self.scale + self.cur_x if y is None: y = self.cur_y else: y = float(y) * self.scale + self.cur_y return x, y def bezier(self): if self.path.len > 1: self.prop_stack.AddStyle(self.cur_style.Duplicate()) GenericLoader.bezier(self, paths=(self.path, )) self.path = CreatePath() def jump(self, x, y): x, y = self.get_position(x, y) self.cur_x = x self.cur_y = y def needle_move(self, x, y): if self.draw == 1: self.path.AppendLine(x, y) else: self.bezier() self.path.AppendLine(x, y) self.cur_x = x self.cur_y = y def needle_down(self, x=None, y=None): self.draw = 1 x, y = self.get_position(x, y) self.needle_move(x, y) def needle_up(self, x=None, y=None): if self.draw == 1: self.bezier() self.draw = 0 x, y = self.get_position(x, y) self.needle_move(x, y) def decode_x(self, d1, d2, d3): x = 1 * byte(d1, 7) - 1 * byte(d1, 6) + 9 * byte(d1, 5) - 9 * byte( d1, 4) x += 3 * byte(d2, 7) - 3 * byte(d2, 6) + 27 * byte(d2, 5) - 27 * byte( d2, 4) x += 81 * byte(d3, 5) - 81 * byte(d3, 4) return x def decode_y(self, d1, d2, d3): y = 1 * byte(d1, 0) - 1 * byte(d1, 1) + 9 * byte(d1, 2) - 9 * byte( d1, 3) y += 3 * byte(d2, 0) - 3 * byte(d2, 1) + 27 * byte(d2, 2) - 27 * byte( d2, 3) y += 81 * byte(d3, 2) - 81 * byte(d3, 3) return y def decode_flag(self, d3): if d3 == 243: return END if d3 & 195 == 3: return NORMAL elif d3 & 195 == 131: return JUMP elif d3 & 195 == 195: return CHANGECOLOR else: return UNKNOWN def readheader(self, file): file.seek(0) header = file.read(512).split('\r') dict = {} for i in header: if i[2] == ':': dict[i[0:2]] = i[3:].replace(' ', '') x = int(dict['-X']) y = int(dict['-Y']) self.jump(x, y) def Load(self): file = self.file fileinfo = os.stat(self.filename) totalsize = fileinfo[6] self.initialize() self.readheader(file) self.document() self.layer(name=_("DST_objects")) parsed = 0 parsed_interval = totalsize / 99 + 1 flag = UNKNOWN while 1: interval_count = file.tell() / parsed_interval if interval_count > parsed: parsed += 10 # 10% progress app.updateInfo(inf2='%u' % parsed + '% of file is parsed...', inf3=parsed) data = file.read(3) if len(data) < 3 or flag == 'END': self.needle_up() ## END INTERPRETATION app.updateInfo(inf2=_('Parsing is finished'), inf3=100) break d1, d2, d3 = unpack('BBB', data) x = self.decode_x(d1, d2, d3) y = self.decode_y(d1, d2, d3) #XXX swap coordinate x, y = y, x flag = self.decode_flag(d3) if flag == NORMAL: self.needle_down(x, y) elif flag == CHANGECOLOR: self.needle_up(x, y) self.cur_style.line_pattern = self.palette.next_color() elif flag == JUMP: #self.bezier() # cut the rope self.jump(x, y) self.end_all() self.object.load_Completed() return self.object