def load(self, filename): """Loads the font from a ``.dmd`` file (see :meth:`Animation.load`). Fonts are stored in .dmd files with frame 0 containing the bitmap data and frame 1 containing the character widths. 96 characters (32..127, ASCII printables) are stored in a 10x10 grid, starting with space (``' '``) in the upper left at 0, 0. The character widths are stored in the second frame within the 'raw' bitmap data in bytes 0-95. """ self.__anim.load(filename) if self.__anim.width != self.__anim.height: raise ValueError, "Width != height!" if len(self.__anim.frames) == 1: # We allow 1 frame for handmade fonts. # This is so that they can be loaded as a basic bitmap, have their char widths modified, and then be saved. print "Font animation file %s has 1 frame; adding one" % (filename) self.__anim.frames += [ Frame(self.__anim.width, self.__anim.height) ] elif len(self.__anim.frames) != 2: raise ValueError, "Expected 2 frames: %d" % (len( self.__anim.frames)) self.char_size = self.__anim.width / 10 self.bitmap = self.__anim.frames[0] self.char_widths = [] for i in range(96): self.char_widths += [ self.__anim.frames[1].get_dot(i % self.__anim.width, i / self.__anim.width) ] return self
def frame_for_markup(self, markup, y_offset=0): """Returns a Frame with the given markup rendered within it. The frame width is fixed, but the height will be adjusted to fit the contents while respecting min_height. The Y offset can be configured supplying *y_offset*. """ lines = markup.split('\n') for draw in [False, True]: y = y_offset for line in lines: if line.startswith("{") and line.endswith('}'): # frame!! y = self.__draw_frame(y=y, anim=line[1:-1], draw=draw) elif line.startswith('#') and line.endswith('#'): # centered headline! y = self.__draw_text(y=y, text=line[1:-1], font=self.font_bold, justify='center', draw=draw) elif line.startswith('#'): # left-justified headline y = self.__draw_text(y=y, text=line[1:], font=self.font_bold, justify='left', draw=draw) elif line.endswith('#'): # right-justified headline y = self.__draw_text(y=y, text=line[:-1], font=self.font_bold, justify='right', draw=draw) elif line.startswith('[') and line.endswith(']'): # centered text y = self.__draw_text(y=y, text=line[1:-1], font=self.font_plain, justify='center', draw=draw) elif line.endswith(']'): # right-justified text y = self.__draw_text(y=y, text=line[:-1], font=self.font_plain, justify='right', draw=draw) elif line.startswith('['): # left-justified text y = self.__draw_text(y=y, text=line[1:], font=self.font_plain, justify='left', draw=draw) else: # left-justified but nothing to clip off y = self.__draw_text(y=y, text=line, font=self.font_plain, justify='left', draw=draw) if not draw: # this was a test run to get the height self.frame = Frame(width=self.width, height=max(self.min_height, y)) return self.frame
def save(self, filename): """Save the font to the given path.""" out = Animation() out.width = self.__anim.width out.height = self.__anim.height out.frames = [self.bitmap, Frame(out.width, out.height)] for i in range(96): out.frames[1].set_dot(i%self.__anim.width, i/self.__anim.width, self.char_widths[i]) out.save(filename)
def populate_from_dmd_file(self, f): f.seek(0, os.SEEK_END) # Go to the end of the file to get its length file_length = f.tell() f.seek(4) # Skip over the 4 byte DMD header. frame_count = struct.unpack("I", f.read(4))[0] self.width = struct.unpack("I", f.read(4))[0] self.height = struct.unpack("I", f.read(4))[0] if file_length != 16 + self.width * self.height * frame_count: raise ValueError, "File size inconsistent with header information. Old or incompatible file format?" for frame_index in range(frame_count): str_frame = f.read(self.width * self.height) new_frame = Frame(self.width, self.height) new_frame.set_data(str_frame) self.frames.append(new_frame)
def convertImageToOldDMD(src): pal_image= Image.new("P", (1,1)) tuplePal = VgaDMD.get_palette() flatPal = [element for tupl in tuplePal for element in tupl] pal_image.putpalette(flatPal) src_rgb = src.convert("RGB").quantize(palette=pal_image) src_p = src_rgb.convert("P") (w,h) = src.size frame = Frame(w, h) for x in range(w): for y in range(h): color = src_p.getpixel((x,y)) frame.set_dot(x=x, y=y, value=color) return frame
def convertImage(src): image = src.convert("RGB") (w,h) = image.size frame = Frame(w, h) mode = image.mode size = image.size data = image.tostring() #assert mode in 'RGB', 'RGBA' surface = pygame.image.fromstring(data, size, mode) frame.set_surface(surface) return frame
def draw(self, frame, text, x, y, color = None): """Uses this font's characters to draw the given string at the given position.""" #t = self.pygFont.render(text,False,(255,0,255),(0,0,0)) if(color is None): color=(255,255,255) surf = self.pygFont.render(text,False,color,(0,0,0)) (w,h) = surf.get_size() #surf = pygame.surface.Surface((w, h)) #surf.blit(t,(0,0)) #surf.blit(t2,(2,2)) tmp = Frame(w,h) tmp.pySurface = surf tmp.composite_op = "blacksrc" Frame.copy_rect(dst=frame, dst_x=x, dst_y=y, src=tmp, src_x=0, src_y=0, width=w, height=h, op=self.composite_op) #Frame.copy_rect(dst=frame, dst_x=x, dst_y=y, src=self.bitmap, src_x=char_x, src_y=char_y, width=width, height=self.char_size, op=self.composite_op) return x
def populate_from_image_file(self, path, f): if not Image: raise RuntimeError, 'Cannot open non-native image types without Python Imaging Library: %s' % ( path) src = Image.open(f) (w, h) = src.size if len(self.frames) > 0 and (w != self.width or h != self.height): raise ValueError, "Image sizes must be uniform! Anim is %dx%d, image is %dx%d" % ( w, h, self.width, self.height) (self.width, self.height) = (w, h) if path.endswith('.gif'): from . import animgif self.frames += animgif.gif_frames(src) else: alpha = None try: alpha = Image.fromstring('L', src.size, src.tostring('raw', 'A')) except: pass # No alpha channel available? reduced = src.convert("L") frame = Frame(w, h) # Construct a lookup table from 0-255 to 0-15: eight_to_four_map = [0] * 256 for l in range(256): eight_to_four_map[l] = int(round((l / 255.0) * 15.0)) for x in range(w): for y in range(h): color = eight_to_four_map[reduced.getpixel((x, y))] if alpha: color += eight_to_four_map[alpha.getpixel((x, y))] << 4 frame.set_dot(x=x, y=y, value=color) self.frames.append(frame)
def drawHD(self, frame, text, x, y, line_color, line_width, interior_color, fill_color): """Uses this font's characters to draw the given string at the given position.""" #t = self.pygFont.render(text,False,(255,0,255),(0,0,0)) #surf = self.pygFont.render(text,False,self.color,(0,0,0)) if(text == ""): return x if(fill_color==None): fill_color=(0,0,0) surf = self.textHollow(text,line_color, interior_color, 2*line_width, fill_color) (w,h) = surf.get_size() tmp = Frame(w,h) tmp.pySurface = surf Frame.copy_rect(dst=frame, dst_x=x, dst_y=y, src=tmp, src_x=0, src_y=0, width=w, height=h, op=self.composite_op) #Frame.copy_rect(dst=frame, dst_x=x, dst_y=y, src=self.bitmap, src_x=char_x, src_y=char_y, width=width, height=self.char_size, op=self.composite_op) return x
def populate_from_dmd_file(self, f): f.seek(0, os.SEEK_END) # Go to the end of the file to get its length file_length = f.tell() ## MJO: Don't just skip the header! Check it. f.seek(0) # Skip over the 4 byte DMD header. dmd_version = struct.unpack("I", f.read(4))[0] dmd_style = 0 # old if(dmd_version == 0x00646D64): # print("old dmd style") pass elif(dmd_version == 0x00DEFACE): # print("full color dmd style") dmd_style = 1 frame_count = struct.unpack("I", f.read(4))[0] self.width = struct.unpack("I", f.read(4))[0] self.height = struct.unpack("I", f.read(4))[0] if(dmd_style==0): if file_length != 16 + self.width * self.height * frame_count: logging.getLogger('game.dmdcache').warning(f) logging.getLogger('game.dmdcache').warning("expected size = {%d} got {%d}", (16 + self.width * self.height * frame_count), (file_length)) raise ValueError, "File size inconsistent with original DMD format header information. Old or incompatible file format?" elif(dmd_style==1): if file_length != 16 + self.width * self.height * frame_count * 3: logging.getLogger('game.dmdcache').warning(f) raise ValueError, "File size inconsistent with true-color DMD format header information. Old or incompatible file format?" for frame_index in range(frame_count): new_frame = Frame(self.width, self.height) if(dmd_style==0): str_frame = f.read(self.width * self.height) new_frame.build_surface_from_8bit_dmd_string(str_frame) elif(dmd_style==1): str_frame = f.read(self.width * self.height * 3) surface = pygame.image.fromstring(str_frame, (self.width, self.height), 'RGB') new_frame.set_surface(surface) self.frames.append(new_frame)