Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ For example, if you want to convert [the sample cursor](sample/crosshair.cur)
to Linux format:

mkdir output/
win2xcur sample/crosshair.cur -o output/
win2xcur sample/crosshair.cur -o output/ --size 32 48 64

`-s` can be specified to enable shadows.
Multiple cursors files can be specified on the command line.
For example, to convert a directory of cursors with shadows enabled:

win2xcur input/*.{ani,cur} -o output/
win2xcur input/*.{ani,cur} -o output/ --size 32 48 64

For more information, run `win2xcur --help`.

Expand All @@ -43,7 +43,7 @@ For more information, run `win2xcur --help`.
For example, if you want to convert DMZ-White to Windows:

mkdir dmz-white/
x2wincur /usr/share/icons/DMZ-White/cursors/* -o dmz-white/
x2wincur /usr/share/icons/DMZ-White/cursors/* -o dmz-white/ --size 32 48 64

## Troubleshooting

Expand Down
5 changes: 5 additions & 0 deletions win2xcur/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def __init__(self, image: SingleImage, hotspot: Tuple[int, int], nominal: int) -
def __repr__(self) -> str:
return f'CursorImage(image={self.image!r}, hotspot={self.hotspot!r}, nominal={self.nominal!r})'

def clone(self):
return CursorImage(self.image.clone(), self.hotspot, self.nominal)

class CursorFrame:
images: List[CursorImage]
Expand All @@ -36,3 +38,6 @@ def __iter__(self) -> Iterator[CursorImage]:

def __repr__(self) -> str:
return f'CursorFrame(images={self.images!r}, delay={self.delay!r})'

def clone(self):
return CursorFrame([img.clone() for img in self.images], self.delay)
13 changes: 10 additions & 3 deletions win2xcur/main/win2xcur.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ def main() -> None:
help='y-offset of shadow (as fraction of height)')
parser.add_argument('-c', '--shadow-color', default='#000000',
help='color of the shadow')
parser.add_argument('--scale', default=None, type=float,
help='Scale the cursor by the specified factor.')
parser.add_argument('--scale', nargs='*', type=float, default=None,
help='Scale the cursor by the specified factor. Multi-scale "[0.125,0.1875,0.25]"')
parser.add_argument('--size', nargs='*', type=int, default=None,
help='Scale the cursor to the specified size. Multi-size "[32,48,64]"')

args = parser.parse_args()
print_lock = Lock()
Expand All @@ -49,7 +51,12 @@ def process(file: BinaryIO) -> None:
traceback.print_exc()
else:
if args.scale:
scale.apply_to_frames(cursor.frames, scale=args.scale)
cursor.frames = scale.apply_to_frames_by_scales(cursor.frames, scales=args.scale)
elif args.size:
cursor.frames = scale.apply_to_frames_to_sizes(cursor.frames, sizes=args.size)
else:
raise NotImplementedError('Please specify either --scale or --size')

if args.shadow:
shadow.apply_to_frames(cursor.frames, color=args.shadow_color, radius=args.shadow_radius,
sigma=args.shadow_sigma, xoffset=args.shadow_x, yoffset=args.shadow_y)
Expand Down
13 changes: 10 additions & 3 deletions win2xcur/main/x2wincur.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ def main() -> None:
help='X11 cursor files to convert (no extension)')
parser.add_argument('-o', '--output', '--output-dir', default=os.curdir,
help='Directory to store converted cursor files.')
parser.add_argument('-S', '--scale', default=None, type=float,
help='Scale the cursor by the specified factor.')
parser.add_argument('-S', '--scale', nargs='*', type=float, default=None,
help='Scale the cursor by the specified factor. Multi-scale "[0.125,0.1875,0.25]"')
parser.add_argument('--size', nargs='*', type=int, default=None,
help='Scale the cursor to the specified size. Multi-size "[32,28,64]"')

args = parser.parse_args()
print_lock = Lock()
Expand All @@ -35,7 +37,12 @@ def process(file: BinaryIO) -> None:
traceback.print_exc()
else:
if args.scale:
scale.apply_to_frames(cursor.frames, scale=args.scale)
cursor.frames = scale.apply_to_frames_by_scales(cursor.frames, scales=args.scale)
elif args.size:
cursor.frames = scale.apply_to_frames_to_sizes(cursor.frames, sizes=args.size)
else:
raise NotImplementedError('Please specify either --scale or --size')

ext, result = to_smart(cursor.frames)
output = os.path.join(args.output, os.path.basename(name) + ext)
with open(output, 'wb') as f:
Expand Down
38 changes: 31 additions & 7 deletions win2xcur/scale.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,35 @@

from win2xcur.cursor import CursorFrame

def apply_to_frames_by_scales(frames: List[CursorFrame], *, scales: List[float] = None) -> List[CursorFrame]:
all_frames = []
for scale in scales:
for frame in frames:
frame = frame.clone()
for cursor in frame:
cursor.image.scale(
int(round(cursor.image.width * scale)),
int(round(cursor.image.height * scale)),
)
cursor.nominal = int(cursor.nominal * scale)
hx, hy = cursor.hotspot
cursor.hotspot = (int(hx * scale), int(hy * scale))
all_frames.append(frame)
return all_frames

def apply_to_frames(frames: List[CursorFrame], *, scale: float) -> None:
for frame in frames:
for cursor in frame:
cursor.image.scale(
int(round(cursor.image.width * scale)),
int(round(cursor.image.height) * scale),
)
def apply_to_frames_to_sizes(frames: List[CursorFrame], *, sizes: List[int] = None) -> List[CursorFrame]:
all_frames = []
for size in sizes:
for frame in frames:
frame = frame.clone()
for cursor in frame:
scale = size / cursor.image.width
cursor.image.scale(
size,
size,
)
cursor.nominal = int(cursor.nominal * scale)
hx, hy = cursor.hotspot
cursor.hotspot = (int(hx * scale), int(hy * scale))
all_frames.append(frame)
return all_frames