Skip to content

Instantly share code, notes, and snippets.

@grassmunk
Created May 27, 2020 02:47
Show Gist options
  • Save grassmunk/d9026f4f16d21eda8f288a89e3f40698 to your computer and use it in GitHub Desktop.
Save grassmunk/d9026f4f16d21eda8f288a89e3f40698 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
from pluslib import ChicagoPlus
import logging
import sys
from PIL import Image, ImageFont, ImageDraw, ImageEnhance, ImageOps
from pprint import pprint
import struct
import subprocess
import os
from striprtf.striprtf import rtf_to_text
import shutil
import textwrap
import numpy as np
print("Theme:", sys.argv[1])
#theme = sys.argv[1].split("/")[7]
print("Font List...", end=' ', flush=True)
fonts_output = subprocess.check_output(['convert', '-list', 'font'])
fonts = fonts_output.decode().split('\n')
installed_fonts = {}
for index, font in enumerate(fonts):
if "Font:" in font:
installed_fonts[fonts[index].split(":")[1].strip()] = {
fonts[index+1].split(":")[0].strip() : fonts[index+1].split(":")[1].strip(),
fonts[index+2].split(":")[0].strip() : fonts[index+2].split(":")[1].strip(),
fonts[index+3].split(":")[0].strip() : fonts[index+3].split(":")[1].strip(),
fonts[index+4].split(":")[0].strip() : fonts[index+4].split(":")[1].strip(),
fonts[index+5].split(":")[0].strip() : fonts[index+5].split(":")[1].strip()
}
print("OK", end=' ', flush=True)
sys.stdout.flush()
def drawlines(drawcontext, xy, outline=None, width=0):
(x1, y1), (x2, y2) = xy
points = (x1, y1), (x2, y1), (x2, y2), (x1, y2), (x1, y1)
drawcontext.line(points, fill=outline, width=width)
def black_or_white(background_color):
# Counting the perceptive luminance - human eye favors green color...
R, G, B = tuple(int(background_color.lstrip("#")[i:i+2], 16) for i in (0, 2, 4))
luminance = ( (0.299 * R) + (0.587 * G) + (0.114 * B))/255;
if (luminance > 0.5):
d = "#000000" # bright colors - black font
else:
d = "#FFFFFF" # dark colors - white font
return d
def get_font(fontname):
if fontname in ["MS Sans Serif", "MS Serif", "‚l‚r ‚oƒSƒVƒbƒN"]:
fontname = "Microsoft Sans Serif"
if fontname in installed_fonts:
#print("Found installed font {}: {}".format(fontname,installed_fonts[fontname]['glyphs']))
return installed_fonts[fontname]['glyphs']
elif fontname.replace(' ','-') in installed_fonts:
return installed_fonts[fontname.replace(' ','-')]['glyphs']
else:
for i in installed_fonts:
if fontname.lower() == i.lower():
#print("Found installed font {}: {}".format(fontname,installed_fonts[i]['glyphs']))
return installed_fonts[i]['glyphs']
elif fontname.lower() in installed_fonts[i]['family'].lower():
#print("Found installed font {}: {}".format(fontname,installed_fonts[i]['glyphs']))
return installed_fonts[i]['glyphs']
elif fontname.replace(' ','-').lower() in i.lower():
#print("Found installed font {}: {}".format(fontname,installed_fonts[i]['glyphs']))
return installed_fonts[i]['glyphs']
#print("Font: {} NOT FOUND".format(fontname))
return get_font("Microsoft Sans Serif")
def make_icons(plus, ico_name):
icon = "assets/" + ico_name+"~"+".png"
if plus.theme_config['icons'][ico_name]['type'] in ['dll', 'icl']:
index = plus.theme_config['icons'][ico_name]['index']
icon_files = plus.extract_icons_from_dll(plus.theme_config['icons'][ico_name]['path'])
if icon_files:
icon_filename, icon_file = plus.get_icons_size_dll(icon_files, index)
if icon_filename:
f = open("tmp/tmp_"+icon_filename,"wb")
f.write(icon_file)
f.close()
icon = "tmp/tmp_"+icon_filename
else:
icon = "assets/" + ico_name+"~"+".png"
else:
icon_files = plus.extract_ico(plus.theme_config['icons'][ico_name]['path'])
if icon_files == 'bmp':
icon = plus.theme_config['icons'][ico_name]['path']
elif icon_files:
for i in icon_files:
if i['Width'] == 32:
icon = "{}[{}]".format(plus.theme_config['icons'][ico_name]['path'], i['ID'])
break
else:
icon = "{}[{}]".format(plus.theme_config['icons'][ico_name]['path'], i['ID'])
args = ['convert', '-resize', '32x32', icon, ico_name+".png"]
try:
subprocess.check_call(args)
icon_image = Image.open(ico_name+".png").convert('RGBA')
os.remove(ico_name+".png")
except subprocess.CalledProcessError:
icon_image = Image.open("assets/" + ico_name+"~.png").convert('RGBA')
return icon_image
def get_cursors(plus):
cursors = {}
icon_index = 0
if plus.theme_config['cursors']:
for cursor in plus.theme_config['cursors']:
artist = False
title = False
cursor_image = False
cursor_filename = False
if plus.theme_config['cursors'][cursor] and plus.theme_config['cursors'][cursor]['path']:
filename = plus.theme_config['cursors'][cursor]['path']
cursor_filename = plus.theme_config['cursors'][cursor]['filename']
cursor_type = plus.theme_config['cursors'][cursor]['type']
# print(cursor, cursor_type, filename)
if cursor_type == 'ani':
ani_file_config = plus.extract_ani(filename)
if ani_file_config['INFO']:
if 'INAM' in ani_file_config['INFO']:
title = "{}".format(ani_file_config['INFO']['INAM'].replace('\x00', ''))
#print(title)
if 'IART' in ani_file_config['INFO']:
artist = "{}".format(ani_file_config['INFO']['IART'].replace('\x00', ''))
#print(artist)
if ani_file_config['seq']:
icon_index = ani_file_config['seq'][0]
for cur in ani_file_config['icon']:
if cur['index'] == icon_index:
f = open("tmp.cur","wb")
f.write(cur['ico_file'])
f.close()
args = ['convert', '-resize', '32x32', "tmp.cur", cursor+".png"]
try:
subprocess.check_call(args)
except subprocess.CalledProcessError:
print("Error converting cursor {}".format(filename))
continue
try:
cursor_image = Image.open(cursor+".png").convert('RGBA')
except FileNotFoundError:
cursor = cursor +"-0"
cursor_image = Image.open(cursor+".png").convert('RGBA')
elif cursor_type in ['cur', 'ico']: #must be a cursor
cursor_file_config = plus.extract_cur(filename)
cur = cursor_file_config['icon'][0]['ico_file']
f = open("tmp.cur","wb")
f.write(cur)
f.close()
args = ['convert', '-resize', '32x32', "tmp.cur", cursor+".png"]
try:
subprocess.check_call(args)
except subprocess.CalledProcessError:
print("Error converting cursor {}".format(filename))
continue
try:
cursor_image = Image.open(cursor+".png").convert('RGBA')
except FileNotFoundError:
cursor = cursor +"-0"
cursor_image = Image.open(cursor+".png").convert('RGBA')
if cursor_image:
os.remove(cursor+".png")
os.remove("tmp.cur")
cursors[cursor] = { 'img' : cursor_image, 'title' : title, 'artist' : artist, 'filename': cursor_filename }
return cursors
print("Theme...", end=' ', flush=True)
plus = ChicagoPlus(themefile=sys.argv[1],loglevel=logging.CRITICAL)
plus.parse_theme()
print("OK", end=' ', flush=True)
#plus.print_theme_config()
if "zip" in sys.argv[1] or "exe" in sys.argv[1]:
theme_short = sys.argv[1].split("/")[6]
else:
theme_short = plus.theme_name
theme_short = sys.argv[1].split("/")[6]
#args = [
#'xfconf-query',
#"-v", '-l', '-c', 'xsettings',
#"-p", '/Xft/DPI'
#]
#dpi = subprocess.check_output(args).split()[1]
print("Metrics...", end=' ', flush=True)
try:
iCaptionHeight = plus.theme_config['nonclientmetrics']['iCaptionHeight']
iMenuHeight = plus.theme_config['nonclientmetrics']['iMenuHeight']
iScrollWidth = plus.theme_config['nonclientmetrics']['iScrollWidth']
msgfont = plus.theme_config['nonclientmetrics']['lfMessageFont']['lfFaceName[32]']
msgfont_pt = abs(plus.theme_config['nonclientmetrics']['lfMessageFont']['lfHeight'])
caption_font = plus.theme_config['nonclientmetrics']['lfcaptionfont']['lfFaceName[32]']
caption_pt = abs(plus.theme_config['nonclientmetrics']['lfcaptionfont']['lfHeight'])
menufont = plus.theme_config['nonclientmetrics']['lfMenuFont']['lfFaceName[32]']
menufont_pt = abs(plus.theme_config['nonclientmetrics']['lfMenuFont']['lfHeight'])
except:
iCaptionHeight = 18
iMenuHeight = 18
iMenuWidth = 18
iScrollHeight = 13
iScrollWidth = 13
msgfont = "Microsoft Sans Serif"
caption_font = "MS-Reference-Sans-Serif-Bold"
menufont = "Microsoft Sans Serif"
menufont_pt = 10
caption_pt = 10
msgfont_pt = 10
try:
iconfont = plus.theme_config['iconmetrics']['lfFont']['lfFaceName[32]']
iconfont_pt = abs(plus.theme_config['iconmetrics']['lfFont']['lfHeight'])
except:
iconfont = "Microsoft Sans Serif"
iconfont_pt = 10
if iconfont_pt == 8:
iconfont_pt = 10
if msgfont_pt == 8:
msgfont_pt = 10
if caption_pt == 8:
caption_pt = 10
if menufont_pt == 8:
menufont_pt = 10
print("OK", end=' ', flush=True)
print("Fonts...", end=' ')
button_height = iCaptionHeight - 4
button_width = button_height + 2
lfMessageFont = get_font(msgfont)
lfcaptionfont = get_font(caption_font)
lfMenuFont = get_font(menufont)
arial = get_font("Arial")
arial_bold = get_font("Arial-Bold")
lfFont = get_font(iconfont)
cursor_font = get_font("Arial Bold")
cursor_pt = 12
print("OK", end=' ', flush=True)
tile = False
wallpaper = False
print("Wallpaper...", end=' ', flush=True)
# WallpaperStyle=2
#; 0: The image is centered if TileWallpaper=0 or tiled if TileWallpaper=1
#; 2: The image is stretched to fill the screen
#; 6: The image is resized to fit the screen while maintaining the aspect
# ratio. (Windows 7 and later)
#; 10: The image is resized and cropped to fill the screen while maintaining
# the aspect ratio. (Windows 7 and later)
if (plus.theme_config['wallpaper'] and plus.theme_config['wallpaper']['theme_wallpaper'] and
'path' in plus.theme_config['wallpaper']['theme_wallpaper'] and plus.theme_config['wallpaper']['theme_wallpaper']['path']):
#print(plus.theme_config['wallpaper']['theme_wallpaper']['path'])
#print(os.path.splitext(plus.theme_config['wallpaper']['theme_wallpaper']['path'])[1])
if os.path.splitext(plus.theme_config['wallpaper']['theme_wallpaper']['path'])[1].lower() in [".html", ".htm"]:
w = 1024
h = 768
if "800" in plus.theme_config['wallpaper']['theme_wallpaper']['path'] or "800" in plus.theme_name:
w = 800
h = 600
args = ['wkhtmltoimage', '--quiet','--height', str(h), '--width', str(w), plus.theme_config['wallpaper']['theme_wallpaper']['path'],'temp_html.png']
subprocess.check_call(args)
wallpaper = Image.open("temp_html.png").convert('RGBA')
os.remove("temp_html.png")
else:
try:
wallpaper = Image.open(plus.theme_config['wallpaper']['theme_wallpaper']['path']).convert('RGBA')
except OSError:
args = ['convert', '-resize', '32x32', plus.theme_config['wallpaper']['theme_wallpaper']['path'], "temp_bmp.png"]
subprocess.check_call(args)
wallpaper = Image.open("temp_bmp.png").convert('RGBA')
os.remove("temp_bmp.png")
if plus.theme_config['wallpaper']['theme_wallpaper']['tilewallpaper']:
tile = True
style = plus.theme_config['wallpaper']['theme_wallpaper']['wallpaperstyle']
print("OK", end=' ', flush=True)
print("Icons...", end=' ', flush=True)
if plus.theme_config['icons']:
if plus.theme_config['icons']['my_computer']:
my_computer = make_icons(plus,'my_computer')
else:
my_computer = Image.open("assets/my_computer~.png").convert('RGBA')
if plus.theme_config['icons']['network_neighborhood']:
network_neighborhood= make_icons(plus,'network_neighborhood')
else:
network_neighborhood = Image.open("assets/network_neighborhood~.png").convert('RGBA')
if plus.theme_config['icons']['recycle_bin_empty']:
recycle_bin_empty = make_icons(plus,'recycle_bin_empty')
else:
recycle_bin_empty = Image.open("assets/recycle_bin_empty~.png").convert('RGBA')
if plus.theme_config['icons']['my_documents']:
my_documents = make_icons(plus,'my_documents')
else:
my_documents = False
print("OK", end=' ', flush=True)
print("Preview...", end=' ', flush=True)
colors = {
"buttonface": "#C0C0C0",
"buttontext": "#000000",
"inactivetitle": "#808080",
"inactivetitletext": "#DFDFDF",
"inactiveborder": "#C0C0C0",
"buttondkshadow": "#000000",
"buttonshadow": "#808080",
"buttonhilight": "#FFFFFF",
"buttonlight": "#DFDFDF",
"activetitle": "#000080",
"titletext": "#FFFFFF",
"activeborder": "#C0C0C0",
"menutext": "#000000",
"menu": "#C0C0C0",
"hilighttext": "#FFFFFF",
"hilight": "#000080",
"window": "#FFFFFE",
"windowtext": "#000000",
"scrollbar": "#FFFFFF",
"background": "#000000",
"foreground": "#000000"
}
for i in colors:
try:
colors[i] = (plus.theme_config['colors'][i]['color'])
except KeyError:
continue
colors['foreground'] = black_or_white(colors['background'])
buttons = ['minimize','maximize','close']
for button in buttons:
img = Image.new('RGB', (button_width, button_height), color = colors['buttondkshadow'])
draw = ImageDraw.Draw(img)
draw.line([(0,0),(button_width-2, 0), (0,0),(0, button_height-2)],fill=colors['buttonhilight'], width=1)
draw.line([(button_width-2,button_height-2),(button_height, 1)],fill=colors['buttonshadow'], width=1)
draw.line([(1,button_height-2),(button_width-2,button_height-2)],fill=colors['buttonshadow'], width=1)
draw.line([(1,1),(button_width-3, 1), (1,1),(1, button_height-3)],fill=colors['buttonlight'], width=1)
draw.rectangle(((2, 2), (button_width-3, button_height-3)), fill=colors['buttonface'], width=1)
if button_height < 16:
if button == "minimize":
draw.line([(4,9),(10, 9)],fill=colors['buttontext'], width=2)
min_button = img
elif button == 'maximize':
draw.line([(3,10),(11, 10)],fill=colors['buttontext'], width=1)
draw.line([(3,2),(11, 2)],fill=colors['buttontext'], width=2)
draw.line([(3,2),(3, 10)],fill=colors['buttontext'], width=1)
draw.line([(11,2),(11, 10)],fill=colors['buttontext'], width=1)
max_button = img
elif button == 'close':
img.putpixel( (4, 3), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (5, 3), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (5, 4), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (6, 4), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (6, 5), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (7, 5), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (7, 6), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (8, 6), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (8, 7), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (9, 7), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (9, 8), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (10, 8), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (10, 9), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (11, 9), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (4, 9), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (5, 9), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (5, 8), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (6, 8), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (6, 7), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (7, 7), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (7, 6), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (8, 6), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (8, 5), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (9, 5), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (9, 4), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (10, 4), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (10, 3), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
img.putpixel( (11, 3), tuple(int(colors['buttontext'].lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) )
close_button = img
else:
if button == "minimize":
draw.line([(5, button_height - 6),(button_width - 8,button_height - 6)],fill=colors['buttontext'], width=2)
min_button = img
elif button == 'maximize':
draw.line([(4,button_height-5),(button_width - 6 , button_height - 5)],fill=colors['buttontext'], width=1)
draw.line([(4,4),(button_width - 6, 4)],fill=colors['buttontext'], width=2)
draw.line([(4,4),(4, button_height-5)],fill=colors['buttontext'], width=1)
draw.line([(button_width - 6, 4),(button_width - 6, button_height-5)],fill=colors['buttontext'], width=1)
max_button = img
elif button == 'close':
X = Image.open(r"assets/X.png").convert('RGBA')
pixels = X.load()
rgb = struct.unpack('BBB',bytes.fromhex(colors['buttontext'].lstrip('#')))
for i in range(X.size[0]):
for j in range(X.size[1]):
if pixels[i,j] == (0, 0, 0, 255):
pixels[i,j] = rgb
x_w, x_h = X.size
offset = ((button_width - x_w) // 2, (button_height - x_h) // 2)
img.paste(X, offset, mask=X)
close_button = img
tmp = Image.new('RGB', (500, 500), color = colors['activetitle'])
tmp_draw = ImageDraw.Draw(tmp)
msgboxtitle = Image.new('RGB', (173-6, iCaptionHeight), color = colors['activetitle'])
draw = ImageDraw.Draw(msgboxtitle)
myFont = ImageFont.truetype(lfcaptionfont, caption_pt)
w, h = draw.textsize("Message Box", font=myFont)
font_y_offset = myFont.getoffset("Message Box")[1]
draw.fontmode = "1"
draw.text((2,int(((iCaptionHeight-h)-font_y_offset)/2)), "Message Box", fill=colors['titletext'], font=myFont)
inactive_window = Image.new('RGB', (202, iCaptionHeight+118+3), color = colors['buttondkshadow'])
inactivetitle = Image.new('RGB', (inactive_window.size[0]-8, iCaptionHeight), color = colors['inactivetitle'])
draw = ImageDraw.Draw(inactivetitle)
myFont = ImageFont.truetype(lfcaptionfont, caption_pt)
w, h = draw.textsize("Inactive Window", font=myFont)
font_y_offset = myFont.getoffset("Inactive Window")[1]
draw.fontmode = "1"
draw.text((2,int((iCaptionHeight-h)-font_y_offset)/2), "Inactive Window", fill=colors['inactivetitletext'], font=myFont)
activetitle = Image.new('RGB', (217, iCaptionHeight), color = colors['activetitle'])
draw = ImageDraw.Draw(activetitle)
myFont = ImageFont.truetype(lfcaptionfont, caption_pt)
font_y_offset = myFont.getoffset("Active Window")[1]
w, h = draw.textsize("Active Window", font=myFont)
draw.fontmode = "1"
draw.text((2,int((iCaptionHeight-h)-font_y_offset)/2), "Active Window", fill=colors['titletext'], font=myFont)
menufont = ImageFont.truetype(lfMenuFont, menufont_pt)
#normal_w, normal_h = tmp_draw.textsize("Normal", font=menufont)
menubar = Image.new('RGB', (activetitle.size[0], iMenuHeight), color = colors['menu'])
draw = ImageDraw.Draw(menubar)
normal_w, normal_h = draw.textsize("Normal", font=menufont)
font_y_offset = menufont.getoffset("Normal")[1]
draw.fontmode = "1"
draw.text((6,int(((menubar.size[1]-normal_h)-font_y_offset)/2)), "Normal", fill=colors['menutext'], font=menufont)
disabled_w, disabled_h = draw.textsize("Disabled", font=menufont)
draw.text((normal_w+14,(int(((menubar.size[1]-normal_h)-font_y_offset)/2))+1), "Disabled", fill=colors['buttonhilight'], font=menufont)
draw.text((normal_w+13,int(((menubar.size[1]-normal_h)-font_y_offset)/2)), "Disabled", fill=colors['buttonshadow'], font=menufont)
selected_w, selected_h = draw.textsize("Selected", font=menufont)
#myFont.fontmode = "1"
#draw.text((6,int(menubar.size[1]-normal_h)/2), "Selected", fill=colors['hilighttext'], font=menufont)
selected = Image.new('RGB', (selected_w+12,menubar.size[1]), color = colors['hilight'])
selected_draw = ImageDraw.Draw(selected)
selected_draw.fontmode = "1"
font_y_offset = menufont.getoffset("Selected")[1]
selected_draw.text((int((selected.size[0]-selected_w)/2),int(((menubar.size[1]-normal_h)-font_y_offset)/2)), "Selected", fill=colors['hilighttext'], font=menufont)
menubar.paste(selected, (normal_w+13+disabled_w+6,int((menubar.size[1]-selected.size[1])/2)))
uparrow = Image.new('RGB', (iScrollWidth, iScrollWidth), color = colors['buttonface'])
draw = ImageDraw.Draw(uparrow)
draw.line([(0,0),(uparrow.size[0]-2, 0), (0,0), (0,uparrow.size[1]-2)],fill=colors['buttonlight'], width=1)
draw.line([(1,1),(uparrow.size[0]-3, 1), (1,1), (1,uparrow.size[1]-3)],fill=colors['buttonhilight'], width=1)
draw.line([(uparrow.size[0]-1,uparrow.size[1]-1),(uparrow.size[0]-1, 0), (uparrow.size[0]-1,uparrow.size[1]-1), (0,uparrow.size[1]-1)],fill=colors['buttondkshadow'], width=1)
draw.line([(uparrow.size[0]-2,uparrow.size[1]-2),(uparrow.size[0]-2, 1), (uparrow.size[0]-2,uparrow.size[1]-2), (1,uparrow.size[1]-2)],fill=colors['buttonshadow'], width=1)
draw.polygon([(4,7), (8,7), (6,5)], fill = colors['buttontext'])
downarrow = Image.new('RGB', (iScrollWidth, iScrollWidth), color = colors['buttonface'])
draw = ImageDraw.Draw(downarrow)
draw.line([(0,0),(downarrow.size[0]-2, 0), (0,0), (0,downarrow.size[1]-2)],fill=colors['buttonlight'], width=1)
draw.line([(1,1),(downarrow.size[0]-3, 1), (1,1), (1,downarrow.size[1]-3)],fill=colors['buttonhilight'], width=1)
draw.line([(downarrow.size[0]-1,downarrow.size[1]-1),(downarrow.size[0]-1, 0), (downarrow.size[0]-1,downarrow.size[1]-1), (0,downarrow.size[1]-1)],fill=colors['buttondkshadow'], width=1)
draw.line([(downarrow.size[0]-2,downarrow.size[1]-2),(downarrow.size[0]-2, 1), (downarrow.size[0]-2,downarrow.size[1]-2), (1,downarrow.size[1]-2)],fill=colors['buttonshadow'], width=1)
draw.polygon([(4,5), (8,5), (6,7)], fill = colors['buttontext'])
window = Image.new('RGB', (217, 72), color = colors['window'])
draw = ImageDraw.Draw(window)
draw.line([(0,0),(window.size[0]-2, 0), (0,0), (0,window.size[1]-2)],fill=colors['buttonshadow'], width=1)
draw.line([(1,1),(window.size[0]-3, 1), (1,1), (1,window.size[1]-3)],fill=colors['buttondkshadow'], width=1)
draw.line([(window.size[0]-1,window.size[1]-1),(window.size[0]-1, 0), (window.size[0]-1,window.size[1]-1), (0,window.size[1]-1)],fill=colors['buttonhilight'], width=1)
draw.line([(window.size[0]-2,window.size[1]-2),(window.size[0]-2, 1), (window.size[0]-2,window.size[1]-2), (1,window.size[1]-2)],fill=colors['buttonlight'], width=1)
window_font = ImageFont.truetype(arial_bold, 14)
draw.fontmode = "1"
font_y_offset = window_font.getoffset("Window Text")[1]
draw.text((4,7-font_y_offset), "Window Text", fill=colors['windowtext'], font=window_font)
window.paste(uparrow, (window.size[0]-2-uparrow.size[0],2))
draw.rectangle(((window.size[0]-2-uparrow.size[0],2+uparrow.size[1]),(window.size[0]-3, window.size[1]-3)), fill=colors['scrollbar'])
window.paste(downarrow, (window.size[0]-2-downarrow.size[0],window.size[1]-2-downarrow.size[1]))
activewindow = Image.new('RGB', (225, 4+iCaptionHeight+1+iMenuHeight+1+window.size[1]+4), color = colors['buttonface'])
draw = ImageDraw.Draw(activewindow)
draw.line([(0,0),(activewindow.size[0]-2, 0), (0,0), (0,activewindow.size[1]-2)],fill=colors['buttonlight'], width=1)
draw.line([(1,1),(activewindow.size[0]-3, 1), (1,1), (1,activewindow.size[1]-3)],fill=colors['buttonhilight'], width=1)
draw.line([(activewindow.size[0]-1,activewindow.size[1]-1),(activewindow.size[0]-1, 0), (activewindow.size[0]-1,activewindow.size[1]-1), (0,activewindow.size[1]-1)],fill=colors['buttondkshadow'], width=1)
draw.line([(activewindow.size[0]-2,activewindow.size[1]-2),(activewindow.size[0]-2, 1), (activewindow.size[0]-2,activewindow.size[1]-2), (1,activewindow.size[1]-2)],fill=colors['buttonshadow'], width=1)
draw.rectangle(((2, 2), (activewindow.size[0]-3, activewindow.size[1]-3)), fill=colors['activeborder'], width=1)
draw.rectangle(((3, 3), (activewindow.size[0]-4, activewindow.size[1]-4)), fill=colors['buttonface'], width=1)
activewindow.paste(activetitle, (4,4))
activewindow.paste(close_button, (activewindow.size[0]-close_button.size[0]-6, 6))
activewindow.paste(max_button, (activewindow.size[0]-close_button.size[0]-6-2-max_button.size[0], 6))
activewindow.paste(min_button, (activewindow.size[0]-close_button.size[0]-6-2-max_button.size[0]-min_button.size[0], 6))
activewindow.paste(menubar, (4, 4+activetitle.size[1]+1))
activewindow.paste(window, (4, 4+activetitle.size[1]+1+menubar.size[1]+1))
button = Image.new('RGB', (66, 22), color = colors['buttondkshadow'])
draw = ImageDraw.Draw(button)
draw.line([(0,0),(64, 0), (0,0), (0,20)],fill=colors['buttonhilight'], width=1)
draw.line([(button.size[0]-2,1),(button.size[0]-2,button.size[1]-2 )],fill=colors['buttonshadow'], width=1)
draw.line([(1,button.size[1]-2),(button.size[0]-2,button.size[1]-2)],fill=colors['buttonshadow'], width=1)
draw.line([(1,1),(button.size[0]-3, 1), (1,1),(1, button.size[1]-3)],fill=colors['buttonlight'], width=1)
draw.rectangle(((2, 2), (button.size[0]-3, button.size[1]-3)), fill=colors['buttonface'], width=1)
myFont = ImageFont.truetype(arial_bold, msgfont_pt)
draw.fontmode = "1"
font_y_offset = myFont.getoffset("OK")[1]
w, h = draw.textsize("OK", font=myFont)
draw.text(((66-w)/2,((22-h)-font_y_offset)/2), "OK", fill=colors['buttontext'], font=myFont)
#button.save("button.png", "PNG")
myFont = ImageFont.truetype(arial, msgfont_pt)
msg_text_w, msg_text_h = draw.textsize("Message Text", font=myFont)
message_box = Image.new('RGB', (173, iCaptionHeight+8+msg_text_h+3+button.size[1]+6), color = colors['buttondkshadow'])
draw = ImageDraw.Draw(message_box)
draw.line([(0,0),(171, 0), (0,0), (0,message_box.size[1]-2)],fill=colors['buttonlight'], width=1)
draw.line([(message_box.size[0]-2,1),(message_box.size[0]-2,message_box.size[1]-2 )],fill=colors['buttonshadow'], width=1)
draw.line([(1,message_box.size[1]-2),(message_box.size[0]-2,message_box.size[1]-2)],fill=colors['buttonshadow'], width=1)
draw.line([(1,1),(message_box.size[0]-3, 1), (1,1),(1, message_box.size[1]-3)],fill=colors['buttonhilight'], width=1)
draw.rectangle(((2, 2), (message_box.size[0]-3, message_box.size[1]-3)), fill=colors['activeborder'], width=1)
draw.rectangle(((3, 3), (message_box.size[0]-4, message_box.size[1]-4)), fill=colors['buttonface'], width=1)
draw.fontmode = "1"
font_y_offset = myFont.getoffset("Message Text")[1]
draw.text((7,iCaptionHeight+8-font_y_offset), "Message Text", fill=colors['windowtext'], font=myFont)
message_box.paste(msgboxtitle, (3,3))
message_box.paste(close_button, (173-close_button.size[0]-5, 5))
message_box.paste(button, (int((173-button.size[0])/2), iCaptionHeight+8+msg_text_h+3))
draw = ImageDraw.Draw(inactive_window)
draw.line([(0,0),(inactive_window.size[0]-2, 0), (0,0), (0,inactive_window.size[1]-2)],fill=colors['buttonlight'], width=1)
draw.line([(inactive_window.size[0]-2,1),(inactive_window.size[0]-2,inactive_window.size[1]-2 )],fill=colors['buttonshadow'], width=1)
draw.line([(1,inactive_window.size[1]-2),(inactive_window.size[0]-2,inactive_window.size[1]-2)],fill=colors['buttonshadow'], width=1)
draw.line([(1,1),(inactive_window.size[0]-3, 1), (1,1),(1, inactive_window.size[1]-3)],fill=colors['buttonhilight'], width=1)
draw.rectangle(((2, 2), (inactive_window.size[0]-3, inactive_window.size[1]-3)), fill=colors['activeborder'], width=1)
draw.rectangle(((3, 3), (inactive_window.size[0]-4, inactive_window.size[1]-4)), fill=colors['buttonface'], width=1)
inactive_window.paste(inactivetitle, (4,4))
inactive_window.paste(close_button, (inactive_window.size[0]-close_button.size[0]-6, 6))
inactive_window.paste(max_button, (inactive_window.size[0]-close_button.size[0]-6-2-max_button.size[0], 6))
inactive_window.paste(min_button, (inactive_window.size[0]-close_button.size[0]-6-2-max_button.size[0]-min_button.size[0], 6))
height = 39 + (iCaptionHeight * 2) + iMenuHeight + message_box.size[1]
width = 4 + activewindow.size[0]
demowindows = Image.new('RGBA', (width, height), color = (0, 0, 0, 0))
demowindows.paste(inactive_window)
demowindows.paste(activewindow, (4,5+iCaptionHeight))
demowindows.paste(message_box, (12,39 + (iCaptionHeight * 2) + iMenuHeight))
iconfont = ImageFont.truetype(lfFont, iconfont_pt)
size = iconfont.getsize("My Computer")
font_y_offset = iconfont.getoffset("My Computer")[1]
squaresize = (size[0] + 6, size[1] + 6- font_y_offset)
my_computer_text = Image.new('RGBA', squaresize, colors['background'])
iconfont_draw = ImageDraw.Draw(my_computer_text)
iconfont_draw.fontmode = "1"
iconfont_draw.text((3,3-font_y_offset), "My Computer", fill=colors['foreground'], font=iconfont)
size = iconfont.getsize("Network Neighborhood")
font_y_offset = iconfont.getoffset("Network Neighborhood")[1]
squaresize = (size[0] + 6, size[1] + 6 - font_y_offset)
network_neighborhood_text = Image.new('RGBA', squaresize, colors['background'])
iconfont_draw = ImageDraw.Draw(network_neighborhood_text)
iconfont_draw.fontmode = "1"
iconfont_draw.text((3,3-font_y_offset), "Network Neighborhood", fill=colors['foreground'],font=iconfont)
size = iconfont.getsize("Recycle Bin")
font_y_offset = iconfont.getoffset("Recycle Bin")[1]
squaresize = (size[0] + 6, size[1] + 6- font_y_offset)
recycle_bin_empty_text = Image.new('RGBA', squaresize, colors['background'])
iconfont_draw = ImageDraw.Draw(recycle_bin_empty_text)
iconfont_draw.fontmode = "1"
iconfont_draw.text((3,3-font_y_offset), "Recycle Bin", fill=colors['foreground'], font=iconfont)
if my_documents:
size = iconfont.getsize("My Documents")
font_y_offset = iconfont.getoffset("My Documents")[1]
squaresize = (size[0] + 6, size[1] + 6- font_y_offset)
my_documents_text = Image.new('RGBA', squaresize, colors['background'])
iconfont_draw = ImageDraw.Draw(my_documents_text)
iconfont_draw.fontmode = "1"
iconfont_draw.text((3,3-font_y_offset), "My Documents", fill=colors['foreground'], font=iconfont)
total_height = ( my_computer.size[1] + 4 + my_computer_text.size[1] + 16 +
network_neighborhood.size[1] + 4 + network_neighborhood_text.size[1] + 16 +
recycle_bin_empty.size[1] + 4 + recycle_bin_empty_text.size[1] )
if my_documents:
total_height += 16 + my_documents.size[1] + 4 + my_documents_text.size[1]
icons = Image.new('RGBA', (network_neighborhood_text.size[0], total_height), color = (0, 0, 0, 0))
# The center is determined by the longest text
icon_centerline = int((network_neighborhood_text.size[0]-network_neighborhood.size[0])/2)
icons.paste(my_computer, (icon_centerline,0), mask=my_computer)
icons.paste(my_computer_text, (int((icons.size[0]-my_computer_text.size[0])/2),my_computer.size[1]+4))
nn_height = my_computer.size[1] + 4 + my_computer_text.size[1] + 16
nn_text_height = network_neighborhood.size[1] + nn_height + 4
icons.paste(network_neighborhood, (icon_centerline,nn_height), mask=network_neighborhood)
icons.paste(network_neighborhood_text, (0, nn_text_height))
rb_height = nn_height + network_neighborhood.size[1] + 4 + network_neighborhood_text.size[1] + 16
rb_text_height = recycle_bin_empty.size[1] + rb_height + 4
icons.paste(recycle_bin_empty, (icon_centerline,rb_height), mask=recycle_bin_empty)
icons.paste(recycle_bin_empty_text, (int((network_neighborhood_text.size[0]-recycle_bin_empty_text.size[0])/2),rb_text_height))
if my_documents:
md_height = rb_height + recycle_bin_empty.size[1] + 4 + recycle_bin_empty_text.size[1] + 16
md_text_height = my_documents.size[1] + md_height + 4
icons.paste(my_documents, (icon_centerline,md_height), mask=my_documents)
icons.paste(my_documents_text, (int((network_neighborhood_text.size[0]-my_documents_text.size[0])/2),md_text_height))
theme = Image.new('RGB', (392, 332), color = colors['background'])
if wallpaper:
#; 0: The image is centered if TileWallpaper=0 or tiled if TileWallpaper=1
#; 2: The image is stretched to fill the screen
#; 6: The image is resized to fit the screen while maintaining the aspect
# ratio. (Windows 7 and later)
#; 10: The image is resized and cropped to fill the screen while maintaining
# the aspect ratio. (Windows 7 and later)
if tile:
tilew, tileh = wallpaper.resize((int(wallpaper.size[0]/2.6),int(wallpaper.size[1]/2.3))).size
twidth = int(theme.size[0]/tilew) + 1
theight = int(theme.size[1]/tileh) + 1
startw = 0
starth = 0
for i in range(0,theight):
for j in range(0,twidth):
theme.paste(wallpaper.resize((int(wallpaper.size[0]/2.6),int(wallpaper.size[1]/2.3))),
(startw,starth))
startw = startw + wallpaper.resize((int(wallpaper.size[0]/2.6),int(wallpaper.size[1]/2.3))).size[0]
starth = starth + wallpaper.resize((int(wallpaper.size[0]/2.6),int(wallpaper.size[1]/2.3))).size[1]
startw = 0
elif style == 2:
theme.paste(wallpaper.resize((392,332)))
else:
centered_size = wallpaper.resize((int(wallpaper.size[0]/2.6),int(wallpaper.size[1]/2.3))).size
theme.paste(wallpaper.resize((int(wallpaper.size[0]/2.6),int(wallpaper.size[1]/2.3))),
(int((theme.size[0]-centered_size[0])/2),int((theme.size[1]-centered_size[1])/2)))
theme.paste(icons, (1,35), mask=icons)
theme.paste(demowindows, (theme.size[0]- demowindows.size[0] - 2, theme.size[1]- demowindows.size[1]-7), mask=demowindows)
theme.save("./preview/"+theme_short+"_"+plus.theme_name+".png", "PNG")
double = theme.resize((theme.size[0]*2,theme.size[1]*2))
double.save("./preview/"+theme_short+"_"+plus.theme_name+"_double.png", "PNG")
print("OK", end=' ', flush=True)
print("Copy WP...", end=' ', flush=True)
if wallpaper and not tile:
name = "_wallpaper.png"
for i in range(1,100):
if not os.path.exists("preview/"+theme_short+"_wallpaper_"+str(i)+".png"):
wallpaper.save("preview/"+theme_short+"_wallpaper_"+str(i)+".png", "PNG")
break
print("OK", end=' ', flush=True)
print("Text...", end=' ', flush=True)
if not os.path.exists("preview/"+theme_short+"_text.txt"):
text = False
for path in plus.theme_config['all_files']:
if 'logo.sys' in path:
wallpaper = Image.open(plus.theme_config['all_files'][path]).convert('RGBA')
newimg = wallpaper.resize((640,400))
newimg.save("preview/"+theme_short+"_logo.png", "PNG")
if 'logow.sys' in path:
wallpaper = Image.open(plus.theme_config['all_files'][path]).convert('RGBA')
newimg = wallpaper.resize((640,400))
newimg.save("preview/"+theme_short+"_logow.png", "PNG")
if 'logos.sys' in path:
wallpaper = Image.open(plus.theme_config['all_files'][path]).convert('RGBA')
newimg = wallpaper.resize((640,400))
newimg.save("preview/"+theme_short+"_logos.png", "PNG")
if '.txt' in path:
#print("Text: {:<20}".format(path.split('/')[-1]), end='')
try:
with open(plus.theme_config['all_files'][path]) as _file:
text = _file.read()
except UnicodeDecodeError:
with open(plus.theme_config['all_files'][path], encoding="latin-1") as _file:
text = _file.read()
if '.rtf' in path:
#print("Text: {:<20}".format(path.split('/')[-1]), end='')
try:
with open(plus.theme_config['all_files'][path]) as _file:
rtf = _file.read()
text = rtf_to_text(rtf)
except UnicodeDecodeError:
with open(plus.theme_config['all_files'][path], encoding="latin-1") as _file:
rtf = _file.read()
text = rtf_to_text(rtf)
if text:
with open("preview/"+theme_short+"_text.txt", 'w') as _file:
_file.write(text)
print("OK", end=' ', flush=True)
else:
print("NA", end=' ', flush=True)
else:
print("NA", end=' ', flush=True)
print("Author...", end=' ', flush=True)
if not os.path.exists("preview/"+theme_short+"_author.txt"):
author = False
try:
with open(sys.argv[1]) as _file:
comments = []
for line in _file:
if ( line.startswith(';') and
('created by' in line.lower() or 'written by' in line.lower() or 'designed by' in line.lower())
and 'mcnair software' not in line.lower() ):
t = line.lower().strip('|').strip()
if 'created by' in t:
author = t[t.find('created by')+11:].strip()
if 'written by' in t:
author = t[t.find('written by')+11:].strip()
if 'designed by' in t:
author = t[t.find('designed by')+12:].strip()
if author:
#print("Author:", author, end='')
with open("preview/"+theme_short+"_author.txt", 'w') as _file:
_file.write(author)
print("OK", end=' ', flush=True)
else:
print("NA", end=' ', flush=True)
except UnicodeDecodeError:
with open(sys.argv[1], encoding="latin-1") as _file:
comments = []
for line in _file:
if ( line.startswith(';') and
('created by' in line.lower() or 'written by' in line.lower() or 'designed by' in line.lower())
and 'mcnair software' not in line.lower() ):
t = line.lower().strip('|').strip()
if 'created by' in t:
author = t[t.find('created by')+11:].strip()
if 'written by' in t:
author = t[t.find('written by')+11:].strip()
if 'designed by' in t:
author = t[t.find('designed by')+12:].strip()
if author:
#print("Author:", author, end='')
with open("preview/"+theme_short+"_author.txt", 'w') as _file:
_file.write(author)
print("OK", end=' ', flush=True)
else:
print("NA", end=' ', flush=True)
else:
print("NA", end=' ', flush=True)
print("Cursors...", end=' ', flush=True)
cursors = {}
if not os.path.exists("preview/"+theme_short+"_cursors.png"):
if plus.theme_config['cursors']:
cursors = get_cursors(plus)
else:
cursors = {}
if len(cursors) > 0:
cursor_image = Image.new('RGB', (1000, 1000), color = "#FFFFFF")
draw = ImageDraw.Draw(cursor_image)
myFont = ImageFont.truetype(cursor_font, cursor_pt)
# pprint(cursors)
y_pos = 10
for cursor in cursors:
y_offset = 10
text = ''
if cursors[cursor]['filename']:
text += cursor.strip('-0') + ": " + cursors[cursor]['filename']
else:
text += cursor.strip('-0') + ': '
if cursors[cursor]['title']:
y_offset = 30
text += '\nTitle: ' + cursors[cursor]['title'].strip() + ' '
if cursors[cursor]['artist']:
y_offset = 30
text += '\nArtist: ' + cursors[cursor]['artist'].strip() + ' '
cur = cursors[cursor]['img']
cursor_image.paste(cur, (10,y_pos), mask=cur)
#if len(text) > 80:
# word_list = wrapper.wrap(text=text)
# full_text = ''
# for ii in word_list[:-1]:
# full_text = full_text + ii +'\n'
# full_text += word_list[-1]
# text = full_text
w, h = draw.textsize(text, font=myFont)
draw.fontmode = "1"
font_y_offset = myFont.getoffset(text)[1]
draw.text((10 + cur.size[0] + 6,y_pos+int((cur.size[1]-font_y_offset-h)/2)), text, fill="#000000", font=myFont)
y_pos += cur.size[1] + y_offset
invert_im = ImageOps.invert(cursor_image)
start_x, start_y, end_x, end_y = invert_im.getbbox()
img = cursor_image.crop((0,0,end_x+10, end_y+10))
img.save("preview/"+theme_short+"_cursors.png", "PNG")
print("OK", end='')
else:
print("NA", end=' ', flush=True)
print()
#cursor_image.save("preview/"+plus.theme_name+"_cursors.png", "PNG")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment