This commit is contained in:
Michael Chalupiak
2025-02-01 15:42:37 -05:00
parent 8b6ef51156
commit 24d4801414
33652 changed files with 278487 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

View File

@@ -0,0 +1,680 @@
#!/usr/bin/env python3
import struct
# Xcursors Original mapping based on https://revadig.blogspot.com/2017/09/x11-xorg-set-mouse-pointer-cursor.html
# Hashes/Extras: https://fedoraproject.org/wiki/Artwork/EchoCursors/NamingSpec
# QT Cursor names: https://doc.qt.io/archives/qtjambi-4.5.2_01/com/trolltech/qt/gui/QCursor.html
# GDK Cursor: https://developer.gnome.org/gdk3/stable/gdk3-Cursors.html
# Freedesktop cursors (fd): https://www.freedesktop.org/wiki/Specifications/cursor-spec/
import subprocess
import os
import shutil
import sys
# If you're parsing Microsoft Windows 95 default animated cursors, pass the '-s' argument to skip the ugly first frame
cursors = {
'X_cursor': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['X-cursor'],
'name': 'Cursor Logo',
'qt': [],
'xcursors': ['X_cursor',
'boat',
'pirate',
'sailboat',
'shuttle',
'spider, trek',
'umbrella',
'coffee_mug']},
'appstarting': {'Windows Default': True,
'fd': ['progress'],
'gdk': ['progress'],
'hashes': ['08e8e1c95fe2fc01f976f1e063a24ccd',
'3ecb610c1bf2410f44200f48c40d3599', '00000000000000020006000e7e9ffc3f'],
'name': 'Working in Background',
'qt': ['left_ptr_watch', 'half-busy'],
'xcursors': []},
'arrow': {'Windows Default': True,
'fd': ['default'],
'gdk': ['default'],
'hashes': ['top-left-arrow'],
'name': 'Normal Select',
'qt': ['left_ptr'],
'xcursors': ['arrow',
'draft_large',
'draft_small',
'left_ptr',
'top_left_arrow']},
'bottom_tee': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['bottom_tee'],
'name': 'Cell select bottom(?)',
'qt': [],
'xcursors': ['bottom_tee']},
'circle': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Circle? Bullseye?',
'qt': [],
'xcursors': ['circle', 'target']},
'clock': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Clock? Not used?',
'qt': [],
'xcursors': ['clock']},
'copy': {'Windows Default': False,
'fd': ['copy'],
'gdk': ['copy', 'grab', 'grabbing'],
'hashes': ['dnd-copy',
'1081e37283d90000800003c07f3ef6bf',
'6407b0e94181790501fd1e167b474872',
'08ffe1cb5fe6fc01f906f1c063814ccf',
'5aca4d189052212118709018842178c0',
'208530c400c041818281048008011002',
'fcf21c00b30f7e3f83fe0dfd12e71cff'],
'name': 'Drag and drop copy',
'qt': [],
'xcursors': []},
'cross': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Crosshair',
'qt': [],
'xcursors': ['crosshair', 'cross_reverse']},
'crosshair': {'Windows Default': True,
'fd': ['crosshair'],
'gdk': ['crosshair'],
'hashes': [],
'name': 'Precision select',
'qt': ['cross'],
'xcursors': ['cross',
'diamond_cross',
'iron_cross',
'tcross']},
'dotbox': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['dot-box', 'dot_box', 'dot_box_mask'],
'name': 'dot in a box(?)',
'qt': [],
'xcursors': ['dotbox',
'dot',
'bogosity',
'box_spiral',
'draped_box',
'heart, icon',
'rtl_logo']},
'exchange': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Clock? Not used?',
'qt': [],
'xcursors': ['exchange']},
'gumby': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Fun characters',
'qt': [],
'xcursors': ['gumby', 'gobbler', 'man']},
'hand1': {'Windows Default': False,
'fd': ['pointer'],
'gdk': ['pointer'],
'hashes': ['9d800788f1b08800ae810202380a0822',
'e29285e634086352946a0e7090d73106',
'hand', 'HandGrab', 'HandSqueezed'],
'name': 'Hand pointer',
'qt': ['pointing_hand', 'openhand'],
'xcursors': ['hand1', 'hand2']},
'help': {'Windows Default': True,
'fd': ['help', 'context-menu'],
'gdk': ['help', 'context-menu'],
'hashes': ['ask', 'dnd-ask', 'd9ce0ab605698f320427677b458ad60b',
'5c6cd98b3f3ebcb1f9c7f1c204630408'],
'name': 'Help Select',
'qt': ['whats_this'],
'xcursors': ['question_arrow']},
'ibeam': {'Windows Default': True,
'fd': ['text'],
'gdk': ['text'],
'hashes': [],
'name': 'Text Select',
'qt': ['ibeam'],
'xcursors': ['xterm']},
'left_tee': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['left_tee'],
'name': 'Cell select bottom(?)',
'qt': [],
'xcursors': ['left_tee']},
'link': {'Windows Default': False,
'fd': ['link'],
'gdk': ['alias'],
'hashes': ['3085a0e285430894940527032f8b26df',
'640fb0e74195791501fd1ed57b41487f',
'a2a266d0498c3104214a47bd64ab0fc8',
'0876e1c15ff2fc01f906f1c363074c0f', 'dnd-link'],
'name': 'Create link',
'qt': ['closedhand'],
'xcursors': []},
'mouse': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Mouse demo',
'qt': [],
'xcursors': ['mouse', 'middlebutton', 'rightbutton']},
'move': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['move',
'dnd-move',
'4498f0e0c1937ffe01fd06f973665830',
'9081237383d90e509aa00f00170e968f'],
'name': 'color picker',
'qt': [],
'xcursors': []},
'no': {'Windows Default': True,
'fd': ['no-drop', 'not-allowed'],
'gdk': ['no-drop', 'not-allowed'],
'hashes': ['dnd-none',
'03b6e0fcb3499374a867c041f52298f0',
'crossed_circle'],
'name': 'Unavailable/Forbidden',
'qt': ['forbidden', 'dnd-no-drop'],
'xcursors': []},
'pen': {'Windows Default': True,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Handwriting',
'qt': [],
'xcursors': ['pencil']},
'picker': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['picker'],
'name': 'color picker',
'qt': ['color-picker'],
'xcursors': []},
'plus': {'Windows Default': False,
'fd': ['cell'],
'gdk': ['cell'],
'hashes': [],
'name': 'Add a cell',
'qt': [],
'xcursors': ['plus']},
'right_ptr': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Right pointer',
'qt': [],
'xcursors': ['right_ptr']},
'right_tee': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['right_tee'],
'name': 'Cell select right(?)',
'qt': [],
'xcursors': ['right_tee']},
'sb_h_double_arrow': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['14fef782d02440884392942c11205230',
'h_double_arrow', '028006030e0e7ebffc7f7070c0600140',
'right', 'HDoubleArrow'],
'name': 'Resize area between panels',
'qt': ['split_h'],
'xcursors': ['sb_h_double_arrow',
'sb_left_arrow',
'sb_right_arrow']},
'sb_v_double_arrow': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['2870a09082c103050810ffdffffe0204',
'v_double_arrow', 'VDoubleArrow'],
'name': 'Resize area between panels',
'qt': ['split_v'],
'xcursors': ['sb_v_double_arrow',
'sb_up_arrow',
'sb_down_arrow']},
'sizeall': {'Windows Default': True,
'fd': ['all-scroll'],
'gdk': ['move', 'all-scroll'],
'hashes': [],
'name': 'Move',
'qt': ['size_all'],
'xcursors': ['fleur']},
'sizenesw': {'Windows Default': True,
'fd': ['ne-resize', 'sw-resize', 'nesw-resize'],
'gdk': ['ne-resize', 'sw-resize', 'nesw-resize'],
'hashes': ['bd_double_arrow',
'fcf1c3c7cd4491d801f1e1c78f100000'],
'name': 'Diagonal resize 2',
'qt': ['size_bdiag'],
'xcursors': ['bottom_left_corner',
'll_angle',
'top_right_corner',
'ur_angle']},
'sizens': {'Windows Default': True,
'fd': ['row-resize', 'n-resize', 's-resize', 'ns-resize'],
'gdk': ['row-resize', 'n-resize', 's-resize', 'ns-resize'],
'hashes': ['base_arrow_down',
'base_arrow_up',
'v_double_arrow',
'00008160000006810000408080010102'],
'name': 'Vertical resize',
'qt': ['size_ver'],
'xcursors': ['based_arrow_down',
'based_arrow_up',
'double_arrow',
'bottom_side',
'top_side']},
'sizenwse': {'Windows Default': True,
'fd': ['nw-resize', 'se-resize', 'nwse-resize'],
'gdk': ['nw-resize', 'se-resize', 'nwse-resize'],
'hashes': ['fd_double_arrow',
'c7088f0f3e6c8088236ef8e1e3e70000'],
'name': 'Diagonal resize 1',
'qt': ['size_fdiag'],
'xcursors': ['top_left_corner',
'ul_angle',
'lr_angle',
'bottom_right_corner',
'sizing']},
'sizewe': {'Windows Default': True,
'fd': ['col-resize', 'e-resize', 'w-resize', 'ew-resize'],
'gdk': ['col-resize', 'e-resize', 'w-resize', 'ew-resize'],
'hashes': [],
'name': 'Horizontal resize',
'qt': ['size_hor'],
'xcursors': ['left_side', 'right_side']},
'spraycan': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Grafiti time',
'qt': [],
'xcursors': ['spraycan']},
'star': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': [],
'name': 'Star time',
'qt': [],
'xcursors': ['star']},
'top_tee': {'Windows Default': False,
'fd': [],
'gdk': [],
'hashes': ['top_tee'],
'name': 'Cell select top(?)',
'qt': [],
'xcursors': ['top_tee']},
'uparrow': {'Windows Default': True,
'fd': ['up-arrow'],
'gdk': [],
'hashes': ['basic-arrow', 'bassic_arrow'],
'name': 'Alternate Select',
'qt': ['up_arrow'],
'xcursors': ['center_ptr']},
'vertical-text': {'Windows Default': False,
'fd': ['vertical-text'],
'gdk': ['vertical-text'],
'hashes': [],
'name': 'Vertical text selector',
'qt': [],
'xcursors': []},
'wait': {'Windows Default': True,
'fd': ['wait'],
'gdk': ['wait'],
'hashes': [],
'name': 'Busy',
'qt': ['wait'],
'xcursors': ['watch']},
'zoom-in': {'Windows Default': False,
'fd': [],
'gdk': ['zoom-in'],
'hashes': ['f41c0e382c94c0958e07017e42b00462', 'zoomIn'],
'name': 'Zoom in',
'qt': [],
'xcursors': []},
'zoom-out': {'Windows Default': False,
'fd': [],
'gdk': ['zoom-out'],
'hashes': ['f41c0e382c97c0938e07017e42800402', 'zoomOut',
'a2a266d0498c3104214a47bd64ab0fc8'],
'name': 'Drag and drop copy',
'qt': [],
'xcursors': []}
}
def extract_cur(file_name):
print("\tParsing cursor file {}".format(file_name))
# input: .cur file location/name
# output: dict with cursor information
f = open(file_name,'rb')
cur_file = f.read()
f.close()
cur_bytes = bytearray(cur_file)
rtIconDir = False
rtIconDirEntry = False
INFO = False
icon = []
icon.append({
'rtIconDir' : {
'res' : struct.unpack('<H',cur_bytes[0:2])[0],
'ico_type' : struct.unpack('<H',cur_bytes[2:4])[0],
'ico_num_images' : struct.unpack('<H',cur_bytes[4:6])[0]
},
'ico_file' : cur_bytes,
#ICONDIRENTRY
# TODO Add multiple cursors here if needed like icons
'rtIconDirEntry' : {
'bWidth' : cur_bytes[6], # Width, in pixels, of the image
'bHeight' : cur_bytes[7], # Height, in pixels, of the image
'bColorCount' : cur_bytes[8], # Number of colors in image (0 if >=8bpp)
'bReserved' : cur_bytes[9], # Reserved
'wPlanes' : struct.unpack('<H',cur_bytes[10:12])[0], # Color Planes
'wBitCount' : struct.unpack('<H',cur_bytes[12:14])[0], # Bits per pixel
'dwBytesInRes' : struct.unpack('<L',cur_bytes[14:18])[0], # how many bytes in this resource?
'dwDIBOffset' : struct.unpack('<H',cur_bytes[18:20])[0] # RT_ICON rnID
}
})
cursor = {
'icon' : icon
}
return cursor
def convert_cur_files(cursor_filename, output_file_name):
print("\tConverting {} to {}".format(cursor_filename, output_file_name))
convert_path = subprocess.check_output(["which", "convert"]).strip()
args = [
convert_path,
cursor_filename,
output_file_name
]
subprocess.check_call(args)
if os.path.isfile(output_file_name[:-4]+"-0.png"):
shutil.move(output_file_name[:-4]+"-1.png", output_file_name[:-4]+".png")
os.remove(output_file_name[:-4]+"-0.png")
def extract_ani(file_name):
print("\tParsing ani file {}".format(file_name))
f = open(file_name,'rb')
ani_file = f.read()
f.close()
ani_bytes = bytearray(ani_file)
rate = False
seq = False
rtIconDir = False
rtIconDirEntry = False
INFO = False
anih = False
icon = []
icon_count = 0
ckID = ani_bytes[0:4].decode()
ckSize = struct.unpack('<L',ani_bytes[4:8])[0]
ckForm = ani_bytes[8:12].decode()
total_size = 0
print("{:<21} | Extracting cursors/icons from ani file: {}".format("", file_name))
# ANI files are just RIFF files
if ckID == 'RIFF':
print("{:<21} | {} ckSize :{}".format("","RIFF detected", ckSize))
if ckForm == 'ACON': #ACON is optional
#print("ACON detected (optional)")
total_size = 12 # RIFF Header with ACON
else:
total_size = 8 # RIFF Header without ACON
if ckSize == len(ani_bytes) - 8:
ckSize = ckSize + 8 # Sometimes, but not always, the header isn't included in ckSize
print("{:<21} | Adjusting ckSize to actual file size: {}".format("",ckSize))
while total_size < ckSize:
section = ani_bytes[total_size:total_size+4].decode()
total_size = total_size + 4
chunk_size = struct.unpack('<L',ani_bytes[total_size:total_size+4])[0]
total_size = total_size + 4
#print("Chunk {}, Size: {}".format(section, chunk_size))
#print(ani_bytes[total_size:total_size+36])
if section == 'anih': #ANI Header
print("{:<21} | Chunk: anih".format(""))
anih = {
'cbSize': struct.unpack('<L',ani_bytes[total_size:total_size+4])[0],
'nFrames': struct.unpack('<L',ani_bytes[total_size+4:total_size+8])[0],
'nSteps' : struct.unpack('<L',ani_bytes[total_size+8:total_size+12])[0],
'iWidth' : struct.unpack('<L',ani_bytes[total_size+12:total_size+16])[0],
'iHeight' : struct.unpack('<L',ani_bytes[total_size+16:total_size+20])[0],
'iBitCount' : struct.unpack('<L',ani_bytes[total_size+20:total_size+24])[0],
'nPlanes' : struct.unpack('<L',ani_bytes[total_size+24:total_size+28])[0],
'iDispRate' : struct.unpack('<L',ani_bytes[total_size+28:total_size+32])[0], # The value is expressed in 1/60th-of-a-second units, which are known as jiffie, ignored if seq exists
'bfAttributes' : struct.unpack('<L',ani_bytes[total_size+32:total_size+36])[0]
}
elif section == 'rate':
print("{:<21} | Chunk: rate, size: {}".format("", chunk_size))
rate = []
for jiffie in range(0,chunk_size,4):
rate.append(struct.unpack('<L',ani_bytes[total_size+jiffie:total_size+jiffie+4])[0])
elif section == 'seq ':
print("{:<21} | Chunk: seq, size: {}".format("",chunk_size))
seq = []
for sequence in range(0,chunk_size,4):
seq.append(struct.unpack('<L',ani_bytes[total_size+sequence:total_size+sequence+4])[0])
# bfAttributes: 1 == CUR or ICO, 0 == BMP, 3 == 'seq' block is present
elif section == 'LIST':
chunk_type = ani_bytes[total_size:total_size+4].decode()
LIST_item_size = total_size + 4
print("{:<21} | Chunk: {}, size: {}".format("",chunk_type, chunk_size))
if chunk_type == 'INFO':
INFO = {}
while LIST_item_size <= chunk_size:
try:
info_section = ani_bytes[LIST_item_size:LIST_item_size+4].decode()
list_chunk_size = struct.unpack('<L',ani_bytes[LIST_item_size+4:LIST_item_size+8])[0]
INFO[info_section] = ani_bytes[LIST_item_size+8:LIST_item_size+8+list_chunk_size].decode()
except UnicodeDecodeError:
info_section = ani_bytes[LIST_item_size:LIST_item_size+4].decode('latin-1')
list_chunk_size = struct.unpack('<L',ani_bytes[LIST_item_size+4:LIST_item_size+8])[0]
INFO[info_section] = ani_bytes[LIST_item_size+8:LIST_item_size+8+list_chunk_size].decode('latin-1')
if (list_chunk_size % 2) != 0: # Yay DWORD boundaries
list_chunk_size = list_chunk_size + 1
LIST_item_size = LIST_item_size + list_chunk_size + 8
elif chunk_type == 'fram':
info_section = ani_bytes[LIST_item_size:LIST_item_size+4].decode()
while LIST_item_size < chunk_size:
print("{:<21} | Chunk: {}, size: {}".format("",info_section, LIST_item_size))
info_section = ani_bytes[LIST_item_size:LIST_item_size+4].decode()
list_chunk_size = struct.unpack('<L',ani_bytes[LIST_item_size+4:LIST_item_size+8])[0]
if info_section == 'icon':
icon.append({
'index' : icon_count,
#ICONDIR
'rtIconDir' : {
'res' : struct.unpack('<H',ani_bytes[LIST_item_size+8:LIST_item_size+10])[0],
'ico_type' : struct.unpack('<H',ani_bytes[LIST_item_size+10:LIST_item_size+12])[0],
'ico_num_images' : struct.unpack('<H',ani_bytes[LIST_item_size+12:LIST_item_size+14])[0]
},
#ICONDIRENTRY
'rtIconDirEntry' : {
'bWidth' : ani_bytes[LIST_item_size+14], # Width, in pixels, of the image
'bHeight' : ani_bytes[LIST_item_size+15], # Height, in pixels, of the image
'bColorCount' : ani_bytes[LIST_item_size+16], # Number of colors in image (0 if >=8bpp)
'bReserved' : ani_bytes[LIST_item_size+17], # Reserved
'wPlanes' : struct.unpack('<H',ani_bytes[LIST_item_size+18:LIST_item_size+20])[0], # Color Planes (or hotspot X coords for cur)
'wBitCount' : struct.unpack('<H',ani_bytes[LIST_item_size+20:LIST_item_size+22])[0], # Bits per pixel
'dwBytesInRes' : struct.unpack('<L',ani_bytes[LIST_item_size+22:LIST_item_size+26])[0], # how many bytes in this resource?
'dwDIBOffset' : struct.unpack('<H',ani_bytes[LIST_item_size+26:LIST_item_size+28])[0] # RT_ICON rnID
},
'ico_file' : ani_bytes[LIST_item_size+8:LIST_item_size + list_chunk_size + 8]
})
icon_count += 1
#print(info_section, hex(LIST_item_size), list_chunk_size)
if (list_chunk_size % 2) != 0: # Yay DWORD boundaries
list_chunk_size = list_chunk_size + 1
LIST_item_size = LIST_item_size + list_chunk_size + 8
total_size = total_size + chunk_size # The 8 accounts for the chunk id and size which is not included in the size
else:
print("No RIFF ID, is {} an ANI file?".format(file_name))
print("{:<21} | RIFF ID: {}, Form: {}".format("", ckID, ckForm))
if INFO:
for i in INFO:
print("{:<21} | {:<21} | {}".format("",i, INFO[i]))
if anih:
for i in anih:
print("{:<21} | {:<21} | {}".format("",i, anih[i]))
for section in icon:
if section['index']:
print("{:<21} | Index: {}".format("",section['index']))
print("{:<21} | rtIconDir".format(""))
for j in section['rtIconDir']:
print("{:<21} | {:<21} | {}".format("",j, section['rtIconDir'][j]))
print("{:<21} | rtIconDirEntry".format(""))
for j in section['rtIconDirEntry']:
print("{:<21} | {:<21} | {}".format("",j, section['rtIconDirEntry'][j]))
cursor = {
'INFO' : INFO,
'anih' : anih,
'seq' : seq,
'rate' : rate,
'icon' : icon
}
return cursor
if os.path.exists('tmp'):
shutil.rmtree('tmp')
os.makedirs('tmp')
for cursor in cursors:
folder = 'xcursors'
print("Cursor: {}\n\tDesc: {}".format(cursor,cursors[cursor]['name']))
if cursors[cursor]['Windows Default']:
folder = '95'
if os.path.exists("{}/{}.cur".format(folder,cursor)):
ext = ".cur"
elif os.path.exists("{}/{}.ani".format(folder,cursor)):
ext = ".ani"
elif os.path.exists("{}/{}.ico".format(folder,cursor)):
ext = ".ico"
else:
print("{icon}.cur/{icon}.ani/{icon}.ico could not be found. Please place one of {icon}.cur/{icon}.ani/{icon}.ico in {folder}".format(icon=cursor,folder=folder))
if ext in ['.ico', '.cur']:
cursor_file_config = extract_cur(folder+"/"+cursor+ext)
xhot = cursor_file_config['icon'][0]['rtIconDirEntry']['wPlanes']
yhot = cursor_file_config['icon'][0]['rtIconDirEntry']['wBitCount']
size = cursor_file_config['icon'][0]['rtIconDirEntry']['bHeight']
icon_file = cursor_file_config['icon'][0]['ico_file']
f = open("tmp/"+cursor+ext,"wb")
f.write(icon_file)
f.close()
convert_cur_files("tmp/"+cursor+ext, "tmp/"+cursor+".png")
write_conf = open("tmp/"+cursor+".conf", 'w')
print("\tWritting conf file {}: {size} {xhot} {yhot} {filename}".format("tmp/"+cursor+".conf", size=size, xhot=xhot, yhot=yhot, filename=cursor+".png"))
write_conf.write("{size} {xhot} {yhot} {filename}".format(size=size, xhot=xhot, yhot=yhot, filename=cursor+".png"))
write_conf.close()
os.remove("tmp/"+cursor+ext)
elif ext == '.ani':
ani_file_config = extract_ani(folder+"/"+cursor+ext)
#pprint(ani_file_config)
print("{:<21} | Header - nFrames: {}, nSteps: {}, iDispRate: {}".format(cursor+ext, ani_file_config['anih']['nFrames'], ani_file_config['anih']['nSteps'], ani_file_config['anih']['iDispRate']))
write_conf = open("tmp/"+cursor+".conf", 'w')
if ani_file_config['seq']:
for sequence in ani_file_config['seq']:
if ani_file_config['rate']:
rate = ani_file_config['rate'][sequence] * 17
else:
rate = ani_file_config['anih']['iDispRate'] * 17
for icon in ani_file_config['icon']:
if icon['index'] == sequence:
xhot = icon['rtIconDirEntry']['wPlanes']
yhot = icon['rtIconDirEntry']['wBitCount']
size = icon['rtIconDirEntry']['bHeight']
print("{:<21} | Sequence: {}, rate: {}, size: {}, xhot: {}, yhot: {}".format(cursor+ext, sequence, rate, size,xhot, yhot))
cur_filename = cursor+"_"+str(sequence)
f = open("tmp/"+cur_filename+".cur","wb")
f.write(icon['ico_file'])
f.close()
convert_cur_files("tmp/"+cur_filename+".cur", "tmp/"+cur_filename+".png")
write_conf.write("{size} {xhot} {yhot} {filename} {rate}\n".format(size=size, xhot=xhot, yhot=yhot, filename=cur_filename+".png", rate=rate ))
else:
itericons = iter(ani_file_config['icon'])
# This is just for the default windows icons, no idea why
if len(sys.argv) > 1 and sys.argv[1] == '-s':
next(itericons)
for icon in itericons:
xhot = icon['rtIconDirEntry']['wPlanes']
yhot = icon['rtIconDirEntry']['wBitCount']
size = icon['rtIconDirEntry']['bHeight']
rate = ani_file_config['anih']['iDispRate'] * 17
print("{:<21} | Sequence: {}, rate: {}, size: {}, xhot: {}, yhot: {}".format(cursor+ext, icon['index'], rate, size,xhot, yhot))
cur_filename = cursor+"_"+str(icon['index'])
f = open("tmp/"+cur_filename+".cur","wb")
f.write(icon['ico_file'])
f.close()
convert_cur_files("tmp/"+cur_filename+".cur", "tmp/"+cur_filename+".png")
write_conf.write("{size} {xhot} {yhot} {filename} {rate}\n".format(size=size, xhot=xhot, yhot=yhot, filename=cur_filename+".png", rate=rate))
for icon in ani_file_config['icon']:
xhot = icon['rtIconDirEntry']['wPlanes']
yhot = icon['rtIconDirEntry']['wBitCount']
size = icon['rtIconDirEntry']['bHeight']
#print(xhot, yhot, size)
write_conf.close()
print("\tConversion complete\n\tBuilding xcusorfiles in ../cursors")
for linux_type in ['xcursors', 'qt', 'fd', 'gdk', 'hashes']:
for output in cursors[cursor][linux_type]:
print("\t\t{}".format(output))
xcursorgen_path = subprocess.check_output(["which", "xcursorgen"]).strip()
args = [
xcursorgen_path,
"-p",
'tmp',
"tmp/"+cursor+".conf",
"../cursors/"+output
]
subprocess.check_call(args, stdout=subprocess.DEVNULL)
shutil.rmtree('tmp')

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More