def render(self, text, _, color): if self.font is None: return "", (0, 0) fm = QFontMetrics(self.font) rect = fm.boundingRect(text) im = QImage( rect.x() + rect.width(), rect.height(), QImage.Format_ARGB32_Premultiplied, ) im.fill(QColor(0, 0, 0, 0)) painter = QPainter() painter.begin(im) painter.setPen(QPen(QColor(*color))) painter.setFont(self.font) painter.drawText(QPoint(0 - rect.x(), 0 - rect.y()), text) painter.end() bits = im.bits() try: pixels = bits.tobytes() except AttributeError: bits.setsize(im.byteCount()) pixels = bytes(bits) return pixels, (rect.x() + rect.width(), rect.height())
def _glowicon_image_imag(self, data, width, height, dark): from fsui.qt import QColor, QImage, QPoint, QSize transparent_color = data[0] num_colors = data[1] + 1 flags = data[2] transparency = flags & 1 != 0 has_palette = flags & 2 != 0 compressed = data[3] != 0 compressed_palette = data[4] != 0 bitdepth = data[5] image_bytes = data[6] * 256 + data[7] + 1 palette_bytes = data[8] * 256 + data[9] + 1 print("transparent_color:", transparent_color) print("num colors:", num_colors) print("flags:", flags) print("- transparency:", transparency) print("- has_palette:", has_palette) print("compression:", compressed) print("palette compression:", compressed_palette) print("bit depth:", bitdepth) print("image bytes:", image_bytes) print("palette bytes:", palette_bytes) if not transparency: transparent_color = -1 image = QImage(QSize(width, height), QImage.Format_RGBA8888) image.fill(0xFFFFFFFF) palette = [] class ParseData: bits = [] bitdepth = 0 offset = 0 # line = b"" palette = True compressed = False color = [] done = False x = 0 y = 0 copy = 0 produce = 0 parsedata = ParseData() parsedata.offset = 10 + image_bytes parsedata.end = 10 + image_bytes + palette_bytes parsedata.compressed = compressed_palette parsedata.palette = True parsedata.bitdepth = 8 # parsedata.data = data # parsedata.ly = 0 # parsedata.lx = 5 # parsedata.line = line def pushentry(value): if parsedata.palette: parsedata.color.append(value) if len(parsedata.color) == 3: # pylint: disable=unbalanced-tuple-unpacking r, g, b = parsedata.color a = 0xFF print(f"PALETTE{len(palette):02d} 0x{r:02x}{g:02x}{b:02x}") if dark: palette.append(QColor(r * 0.66, g * 0.66, b * 0.66, a)) else: palette.append(QColor(r, g, b, a)) parsedata.color = [] # FIXME: More efficient # parsedata.bits = parsedata.bits[8:] if parsedata.palette and len(palette) >= num_colors: parsedata.palette = False elif parsedata.done: pass else: palette_index = value # FIXME: Maybe only subtract 1 etc when transparency is True # print("palette", palette_index) # FIXME: Transparency... correct? if palette_index == transparent_color: color = QColor(0x00, 0x00, 0x00, 0x00) elif palette_index >= len(palette): color = QColor(0xFF, 0x00, 0x00, 0xFF) print("WARNING, palette_index is", palette_index) else: color = palette[palette_index] image.setPixelColor(QPoint(parsedata.x, parsedata.y), color) # FIXME: More efficient # parsedata.bits = parsedata.bits[bitdepth:] parsedata.x += 1 if parsedata.x == width: parsedata.y += 1 parsedata.x = 0 if parsedata.y == height: parsedata.done = True def pushbit(bit): parsedata.bits.append(bit) if parsedata.produce: if len(parsedata.bits) == parsedata.bitdepth: value = bits_to_value(parsedata.bits) for _i in range(parsedata.produce): pushentry(value) parsedata.produce = 0 parsedata.bits.clear() elif parsedata.copy: if len(parsedata.bits) == parsedata.bitdepth: pushentry(bits_to_value(parsedata.bits)) parsedata.copy -= 1 parsedata.bits.clear() elif parsedata.compressed: if len(parsedata.bits) == 8: value = bits_to_value(parsedata.bits) if value <= 0x7F: parsedata.copy = value + 1 elif value == 0x80: pass else: parsedata.produce = 256 - value + 1 parsedata.bits.clear() else: if len(parsedata.bits) == 8: value = bits_to_value(parsedata.bits[: parsedata.bitdepth]) pushentry(value) parsedata.bits.clear() # if parsedata.palette: # if len(parsedata.bits) == 8: # parsedata.color.append(bits_to_value(parsedata.bits[0:8])) # if len(parsedata.color) == 3: # # pylint: disable=unbalanced-tuple-unpacking # r, g, b = parsedata.color # a = 0xFF # print( # f"PALETTE{len(palette):02d} 0x{r:02x}{g:02x}{b:02x}" # ) # if dark: # palette.append( # QColor(r * 0.66, g * 0.66, b * 0.66, a) # ) # else: # palette.append(QColor(r, g, b, a)) # parsedata.color = [] # # FIXME: More efficient # parsedata.bits = parsedata.bits[8:] # if parsedata.palette and len(palette) >= num_colors: # parsedata.palette = False # elif parsedata.done: # pass # else: # # print("x") # if len(parsedata.bits) == bitdepth: # palette_index = bits_to_value(parsedata.bits[0:bitdepth]) # # FIXME: Maybe only subtract 1 etc when transparency is True # # print("palette", palette_index) # # FIXME: Transparency... correct? # if palette_index == 0 and transparency: # color = QColor(0x00, 0x00, 0x00, 0x00) # elif palette_index >= len(palette): # color = QColor(0xFF, 0x00, 0x00, 0xFF) # print("WARNING, palette_index is", palette_index) # else: # color = palette[palette_index] # image.setPixelColor( # QPoint(parsedata.x, parsedata.y), color # ) # # FIXME: More efficient # parsedata.bits = parsedata.bits[bitdepth:] # parsedata.x += 1 # if parsedata.x == width: # parsedata.y += 1 # parsedata.x = 0 # if parsedata.y == height: # parsedata.done = True def pushbyte(value): for i in range(8): pushbit(value >> (7 - i) & 1) # def flush(): # print("flushing", len(parsedata.bits), "bits") # parsedata.bits = [] def dobyte(): value = data[parsedata.offset] # if parsedata.compressed: # # 0x00 .. 0x7F copy the next n entries as they are, where n is "RLE-value"+1 # # 0x80 ignore this, do nothing # # 0x81 .. 0xFF produce the next entry n times, where n is 256-"RLE-value"+1 # # (if using signed chars n is "RLE-value"+1) # if parsedata.produce: # for _i in range(parsedata.produce): # pushbyte(value) # parsedata.produce = 0 # elif parsedata.copy: # pushbyte(value) # parsedata.copy -= 1 # elif value <= 0x7F: # parsedata.copy = value + 1 # elif value == 0x80: # pass # else: # parsedata.produce = 256 - value + 1 # else: # if not parsedata.palette and not parsedata.compressed: # # FIXME: Only push bitdepth bits # raise Exception("TODO: Unsupported") # else: # pushbyte(value) pushbyte(value) parsedata.offset += 1 while parsedata.offset < parsedata.end: dobyte() print(len(parsedata.bits)) parsedata.offset = 10 parsedata.end = 10 + image_bytes parsedata.compressed = compressed parsedata.palette = False parsedata.copy = 0 parsedata.produce = 0 parsedata.bitdepth = bitdepth print(parsedata.offset, parsedata.end) while parsedata.offset < parsedata.end: dobyte() print(width, height) print(parsedata.x, parsedata.y) # import sys # sys.exit(1) return ShellIconImage(image)
def create_retroarch_layout(self): if self.stretching() == self.STRETCH_FILL_SCREEN or not self.bezel(): return if not self.use_fullscreen(): return # FIXME: file cmp? paths = self.prepare_emulator_skin() print(paths) # FIXME: SUPPORT frame = 0 ( bezel = 0) option # FIXME: With no bezel, we should still use a black bezel to # hide screen stretching screen_width, screen_height = self.screen_size() # dst_x = 0 dst_y = 0 # dst_w = 0 # dst_w = 160 dst_h = screen_height # Bezel size is normalized against 1080 (height) scale = screen_height / 1080 # Bezel width: 160 dst_w = round(160 * scale) game_x, game_y, game_w, game_h = self.display_rect_fullscreen() from fsui.qt import Qt, QImage, QPainter, QRect, QSize image = QImage(QSize(screen_width, screen_height), QImage.Format_RGBA8888) image.fill(Qt.transparent) # painter = image.paintEngine() painter = QPainter(image) dst_x = game_x - dst_w left = QImage(paths["left"]) painter.drawImage(QRect(dst_x, dst_y, dst_w, dst_h), left) dst_x = game_x + game_w right = QImage(paths["right"]) painter.drawImage(QRect(dst_x, dst_y, dst_w, dst_h), right) painter.end() overlay_png_file = self.temp_file("overlay.png").path image.save(overlay_png_file) # noinspection SpellCheckingInspection overlay_config = """overlays = 1 overlay0_overlay = {overlay} overlay0_full_screen = true overlay0_rect = "0.0,0.0,1.0,1.0" overlay0_descs = 0 """.format(overlay=overlay_png_file) # overlay_config = ( # """overlays = 2 # overlay0_overlay = {left} # overlay0_full_screen = true # overlay0_rect = "0.0,0.0,0.12,1.0" # overlay0_descs = 0 # overlay1_overlay = {right} # overlay1_full_screen = true # overlay1_rect = "0.8,0.0,0.2,1.0" # overlay1_descs = 0 # # """.format(left=paths["left"], right=paths["right"])) overlay_config_file = self.temp_file("overlay.cfg") with open(overlay_config_file.path, "w") as f: f.write(overlay_config) return overlay_config_file.path
def create_retroarch_layout(self): if self.stretching() == self.STRETCH_FILL_SCREEN or not self.bezel(): return if not self.use_fullscreen(): return # FIXME: file cmp? paths = self.prepare_emulator_skin() print(paths) # FIXME: SUPPORT frame = 0 ( bezel = 0) option # FIXME: With no bezel, we should still use a black bezel to # hide screen stretching screen_width, screen_height = self.screen_size() # dst_x = 0 dst_y = 0 # dst_w = 0 # dst_w = 160 dst_h = screen_height # Bezel size is normalized against 1080 (height) scale = screen_height / 1080 # Bezel width: 160 dst_w = round(160 * scale) game_x, game_y, game_w, game_h = self.display_rect_fullscreen() from fsui.qt import Qt, QImage, QPainter, QRect, QSize image = QImage( QSize(screen_width, screen_height), QImage.Format_RGBA8888 ) image.fill(Qt.transparent) # painter = image.paintEngine() painter = QPainter(image) dst_x = game_x - dst_w left = QImage(paths["left"]) painter.drawImage(QRect(dst_x, dst_y, dst_w, dst_h), left) dst_x = game_x + game_w right = QImage(paths["right"]) painter.drawImage(QRect(dst_x, dst_y, dst_w, dst_h), right) painter.end() overlay_png_file = self.temp_file("overlay.png").path image.save(overlay_png_file) # noinspection SpellCheckingInspection overlay_config = """overlays = 1 overlay0_overlay = {overlay} overlay0_full_screen = true overlay0_rect = "0.0,0.0,1.0,1.0" overlay0_descs = 0 """.format( overlay=overlay_png_file ) # overlay_config = ( # """overlays = 2 # overlay0_overlay = {left} # overlay0_full_screen = true # overlay0_rect = "0.0,0.0,0.12,1.0" # overlay0_descs = 0 # overlay1_overlay = {right} # overlay1_full_screen = true # overlay1_rect = "0.8,0.0,0.2,1.0" # overlay1_descs = 0 # # """.format(left=paths["left"], right=paths["right"])) overlay_config_file = self.temp_file("overlay.cfg") with open(overlay_config_file.path, "w") as f: f.write(overlay_config) return overlay_config_file.path