def read(self, stream: Stream, version): if not stream.read_0d_terminator(): raise UnreadableSymbolException('Could not find 0d terminator at {}'.format(hex(stream.tell() - 8))) # consume unused properties - MultiLayerMarkerSymbol implements IMarkerSymbol # so that the size/offsets/angle are required properties. But they aren't used # or exposed anywhere for MultiLayerMarkerSymbol _ = stream.read_double('unused marker size') _ = stream.read_double('unused marker x/y/offset or angle') _ = stream.read_double('unused marker x/y/offset or angle') _ = stream.read_double('unused marker x/y/offset or angle') _ = stream.read_object('unused color') self.halo = stream.read_int() == 1 self.halo_size = stream.read_double('halo size') self.halo_symbol = stream.read_object('halo') # useful stuff number_layers = stream.read_int('layers') for i in range(number_layers): layer = stream.read_object('symbol layer {}/{}'.format(i + 1, number_layers)) self.levels.extend([layer]) for l in self.levels: l.read_enabled(stream) for l in self.levels: l.read_locked(stream) _ = stream.read_double('unknown size') _ = stream.read_double('unknown size') if version >= 3: for l in self.levels: l.read_tags(stream)
def read(self, stream: Stream, version): stream.read_int('unknown') stream.read_int('unknown 2') self.file = stream.read_embedded_file('image') self.color_foreground = stream.read_object('color 1') self.color_background = stream.read_object('color 2') self.color_transparent = stream.read_object('color 3') self.angle = stream.read_double('angle') self.size = stream.read_double('size') self.x_offset = stream.read_double('x offset') self.y_offset = stream.read_double('y offset') stream.read_double('unknown') stream.read_double('unknown') stream.read_0d_terminator() self.swap_fb_gb = bool(stream.read_uchar('swap fgbg')) check = binascii.hexlify(stream.read(2)) if check != b'ffff': raise UnreadableSymbolException( 'Expected ffff at {}, got {}'.format(check, hex(stream.tell() - 2))) # unknown stream.read(6)
def _read(self, stream: Stream, version): self.color = stream.read_object('color') number_layers = stream.read_int('layers') for i in range(number_layers): stream.consume_padding() layer = stream.read_object('symbol layer {}/{}'.format( i + 1, number_layers)) self.levels.extend([layer]) # the next section varies in size. To handle this we jump forward to a known anchor # point, and then move back by a known amount # burn up to the 02 stream.log('burning up to 02...') while not binascii.hexlify(stream.read(1)) == b'02': pass # jump back a known amount stream.rewind(8 * number_layers + 1) for l in self.levels: l.read_enabled(stream) for l in self.levels: l.read_locked(stream)
def read(self, stream: Stream, version): self.color = stream.read_object('color') self.unicode = stream.read_int('unicode') self.angle = stream.read_double('angle') self.size = stream.read_double('size') self.x_offset = stream.read_double('x offset') self.y_offset = stream.read_double('y offset') stream.read_double('unknown 1') stream.read_double('unknown 2') self.read_0d_terminator(stream) if binascii.hexlify(stream.read(2)) != b'ffff': raise UnreadableSymbolException('Expected ffff') self.font = stream.read_string('font name') # lot of unknown stuff stream.read_double('unknown 3') # or object? stream.read_double('unknown 4') # or object? if binascii.hexlify(stream.read(2)) != b'9001': raise UnreadableSymbolException('Expected 9001') stream.read(4) stream.read(6) # std OLE font .. maybe contains useful stuff like bold/etc, but these aren't exposed in ArcGIS anyway.. self.std_font = stream.read_object('font')
def read_ramp_name_type(self, stream: Stream): """ Reads the ramp name type from a stream """ name_length = stream.read_int('name size') self.ramp_name_type = stream.read(name_length * 2).decode('utf-16') stream.log('Ramp name \'{}\''.format(self.ramp_name_type), name_length * 2) stream.read(2)
def _read(self, stream: Stream, version): # consume section of unknown purpose _ = stream.read_double('unknown size') unknown_object = stream.read_object('unknown') if unknown_object is not None: assert False, unknown_object _ = stream.read_double('unknown size') self.color = stream.read_object('color') self.halo = stream.read_int() == 1 self.halo_size = stream.read_double('halo size') self.halo_symbol = stream.read_object('halo') # not sure about this - there's an extra 02 here if a full fill symbol is used for the halo if False and isinstance(self.halo_symbol, Symbol): check = binascii.hexlify(stream.read(1)) if check != b'02': raise UnreadableSymbolException( 'Found unexpected value {} at {}, expected x02'.format( check, hex(stream.tell() - 1))) stream.read(1) if isinstance(self.halo_symbol, SymbolLayer): stream.read(4) # useful stuff number_layers = stream.read_int('layers') for i in range(number_layers): layer = stream.read_object('symbol layer {}/{}'.format( i + 1, number_layers)) self.levels.extend([layer]) for l in self.levels: l.read_enabled(stream) for l in self.levels: l.read_locked(stream) _ = stream.read_double('unknown size') _ = stream.read_double('unknown size')
def read(self, stream: Stream, version): # first bit is either an entire LineSymbol or just a LineSymbolLayer outline = stream.read_object('outline') if outline is not None: if issubclass(outline.__class__, SymbolLayer): self.outline_layer = outline else: self.outline_symbol = outline self.color = stream.read_object('color') stream.read_0d_terminator() _ = stream.read_int('unknown int')
def read(self, stream: Stream, version): self.pattern_interval = stream.read_double('pattern interval') pattern_part_count = stream.read_int('pattern parts') self.pattern_parts = [] for p in range(pattern_part_count): filled_squares = stream.read_double() empty_squares = stream.read_double() self.pattern_parts.append([filled_squares, empty_squares]) pattern = '' for p in self.pattern_parts: pattern += '-' * int(p[0]) + '.' * int(p[1]) stream.log('deciphered line pattern {} ending'.format(pattern))
def read(self, stream: Stream, version): if not stream.read_0d_terminator(): raise UnreadableSymbolException('Could not find 0d terminator at {}'.format(hex(stream.tell() - 8))) _ = stream.read_object('unused color') number_layers = stream.read_int('layers') for i in range(number_layers): layer = stream.read_object('symbol layer {}/{}'.format(i + 1, number_layers)) self.levels.extend([layer]) # stream.read(4) for l in self.levels: l.read_enabled(stream) for l in self.levels: l.read_locked(stream) if version >= 2: for l in self.levels: l.read_tags(stream)
def read(self, stream: Stream, version): self.color = stream.read_object('color') self.size = stream.read_double('size') type_code = stream.read_int() type_dict = { 0: 'circle', 1: 'square', 2: 'cross', 3: 'x', 4: 'diamond' } if type_code not in type_dict: raise UnreadableSymbolException( 'Unknown marker type at {}, got {}'.format( hex(stream.tell() - 4), type_code)) stream.log('found a {}'.format(type_dict[type_code]), 4) self.type = type_dict[type_code] # look for 0d terminator if not binascii.hexlify(stream.read(8)) == b'0d00000000000000': raise UnreadableSymbolException() stream.read_double('unknown') self.x_offset = stream.read_double('x offset') self.y_offset = stream.read_double('y offset') has_outline = stream.read_uchar() if has_outline == 1: self.outline_enabled = True self.outline_width = stream.read_double('outline width') self.outline_color = stream.read_object('outline color') check = binascii.hexlify(stream.read(2)) if check != b'ffff': raise UnreadableSymbolException( 'Expected ffff at {}, got {}'.format(check, hex(stream.tell() - 2)))
def read(self, stream: Stream, version): version = binascii.hexlify(stream.read(1)) if version != b'01': raise UnsupportedVersionException( 'Unsupported Font version {}'.format(version)) self.charset = stream.read_ushort('charset') # Not exposed in ArcMap front end: attributes = stream.read_uchar('attributes') self.italic = attributes & self.Italic self.underline = attributes & self.Underline self.strikethrough = attributes & self.Strikethrough self.weight = stream.read_ushort('weight') # From https://docs.microsoft.com/en-us/windows/desktop/api/olectl/ns-olectl-tagfontdesc # Use the int64 member of the CY structure and scale your font size (in points) by 10000. self.size = stream.read_int('font size') / 10000 name_length = stream.read_uchar('font name size') self.font_name = stream.read(name_length).decode()
def read(self, stream: Stream, version): self.cap = self.read_cap(stream) stream.log('read cap of {}'.format(self.cap), 1) self.offset = stream.read_double('offset') self.pattern_marker = stream.read_object('pattern marker') self.template = stream.read_object('template') self.decoration = stream.read_object('decoration') stream.read_0d_terminator() _ = stream.read_double('unknown double') _ = stream.read_int('unknown int') _ = stream.read_uchar('unknown char') self.join = self.read_join(stream) unknown = binascii.hexlify(stream.read(3)) if unknown != b'000000': raise UnreadableSymbolException( 'Differing unknown string {}'.format(unknown)) _ = stream.read_double('unknown double')
def read(self, stream: Stream, version): self.random = bool(stream.read_int('random')) self.offset_x = stream.read_double('offset x') self.offset_y = stream.read_double('offset y') self.separation_x = stream.read_double('separation x') self.separation_y = stream.read_double('separation y') _ = stream.read_double('unused double') _ = stream.read_double('unused double') self.marker = stream.read_object('fill marker') # either an entire LineSymbol or just a LineSymbolLayer outline = stream.read_object('outline') if outline is not None: if issubclass(outline.__class__, SymbolLayer): self.outline_layer = outline else: self.outline_symbol = outline stream.read_0d_terminator() _ = stream.read_double('unused double')