Compare commits

..

No commits in common. "master" and "v0.1.1" have entirely different histories.

6 changed files with 7 additions and 41 deletions

View file

@ -1,4 +1,4 @@
# `win2xcur` and `x2wincur` [![Build Status](https://img.shields.io/github/actions/workflow/status/quantum5/win2xcur/build.yml)](https://github.com/quantum5/win2xcur/actions) [![PyPI](https://img.shields.io/pypi/v/win2xcur.svg)](https://pypi.org/project/win2xcur/) [![PyPI - Format](https://img.shields.io/pypi/format/win2xcur.svg)](https://pypi.org/project/win2xcur/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/win2xcur.svg)](https://pypi.org/project/win2xcur/) # `win2xcur` and `x2wincur` [![Build Status](https://img.shields.io/github/workflow/status/quantum5/win2xcur/Python%20package)](https://github.com/quantum5/win2xcur/actions) [![PyPI](https://img.shields.io/pypi/v/win2xcur.svg)](https://pypi.org/project/win2xcur/) [![PyPI - Format](https://img.shields.io/pypi/format/win2xcur.svg)](https://pypi.org/project/win2xcur/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/win2xcur.svg)](https://pypi.org/project/win2xcur/)
`win2xcur` is a tool that converts cursors from Windows format (`*.cur`, `win2xcur` is a tool that converts cursors from Windows format (`*.cur`,
`*.ani`) to Xcursor format. This allows Windows cursor themes to be used on `*.ani`) to Xcursor format. This allows Windows cursor themes to be used on

View file

@ -7,7 +7,7 @@ with open(os.path.join(os.path.dirname(__file__), 'README.md')) as f:
setup( setup(
name='win2xcur', name='win2xcur',
version='0.1.2', version='0.1.1',
packages=find_packages(), packages=find_packages(),
install_requires=['numpy', 'Wand'], install_requires=['numpy', 'Wand'],

View file

@ -7,7 +7,7 @@ from multiprocessing.pool import ThreadPool
from threading import Lock from threading import Lock
from typing import BinaryIO from typing import BinaryIO
from win2xcur import scale, shadow from win2xcur import shadow
from win2xcur.parser import open_blob from win2xcur.parser import open_blob
from win2xcur.writer import to_x11 from win2xcur.writer import to_x11
@ -32,8 +32,6 @@ def main() -> None:
help='y-offset of shadow (as fraction of height)') help='y-offset of shadow (as fraction of height)')
parser.add_argument('-c', '--shadow-color', default='#000000', parser.add_argument('-c', '--shadow-color', default='#000000',
help='color of the shadow') help='color of the shadow')
parser.add_argument('--scale', default=None, type=float,
help='Scale the cursor by the specified factor.')
args = parser.parse_args() args = parser.parse_args()
print_lock = Lock() print_lock = Lock()
@ -48,8 +46,6 @@ def main() -> None:
print(f'Error occurred while processing {name}:', file=sys.stderr) print(f'Error occurred while processing {name}:', file=sys.stderr)
traceback.print_exc() traceback.print_exc()
else: else:
if args.scale:
scale.apply_to_frames(cursor.frames, scale=args.scale)
if args.shadow: if args.shadow:
shadow.apply_to_frames(cursor.frames, color=args.shadow_color, radius=args.shadow_radius, 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) sigma=args.shadow_sigma, xoffset=args.shadow_x, yoffset=args.shadow_y)

View file

@ -7,7 +7,6 @@ from multiprocessing.pool import ThreadPool
from threading import Lock from threading import Lock
from typing import BinaryIO from typing import BinaryIO
from win2xcur import scale
from win2xcur.parser import open_blob from win2xcur.parser import open_blob
from win2xcur.writer import to_smart from win2xcur.writer import to_smart
@ -18,8 +17,6 @@ def main() -> None:
help='X11 cursor files to convert (no extension)') help='X11 cursor files to convert (no extension)')
parser.add_argument('-o', '--output', '--output-dir', default=os.curdir, parser.add_argument('-o', '--output', '--output-dir', default=os.curdir,
help='Directory to store converted cursor files.') help='Directory to store converted cursor files.')
parser.add_argument('-S', '--scale', default=None, type=float,
help='Scale the cursor by the specified factor.')
args = parser.parse_args() args = parser.parse_args()
print_lock = Lock() print_lock = Lock()
@ -34,8 +31,6 @@ def main() -> None:
print(f'Error occurred while processing {name}:', file=sys.stderr) print(f'Error occurred while processing {name}:', file=sys.stderr)
traceback.print_exc() traceback.print_exc()
else: else:
if args.scale:
scale.apply_to_frames(cursor.frames, scale=args.scale)
ext, result = to_smart(cursor.frames) ext, result = to_smart(cursor.frames)
output = os.path.join(args.output, os.path.basename(name) + ext) output = os.path.join(args.output, os.path.basename(name) + ext)
with open(output, 'wb') as f: with open(output, 'wb') as f:

View file

@ -1,12 +0,0 @@
from typing import List
from win2xcur.cursor import CursorFrame
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),
)

View file

@ -1,17 +1,10 @@
from typing import List from typing import List
from wand.color import Color from wand.color import Color
from wand.image import BaseImage, COMPOSITE_OPERATORS, Image from wand.image import BaseImage, Image
from win2xcur.cursor import CursorFrame from win2xcur.cursor import CursorFrame
if 'copy_opacity' in COMPOSITE_OPERATORS:
COPY_ALPHA = 'copy_opacity' # ImageMagick 6 name
NEEDS_NEGATE = False
else:
COPY_ALPHA = 'copy_alpha' # ImageMagick 7 name
NEEDS_NEGATE = True
def apply_to_image(image: BaseImage, *, color: str, radius: float, sigma: float, xoffset: float, def apply_to_image(image: BaseImage, *, color: str, radius: float, sigma: float, xoffset: float,
yoffset: float) -> Image: yoffset: float) -> Image:
@ -20,24 +13,18 @@ def apply_to_image(image: BaseImage, *, color: str, radius: float, sigma: float,
new_width = image.width + 3 * xoffset new_width = image.width + 3 * xoffset
new_height = image.height + 3 * yoffset new_height = image.height + 3 * yoffset
if NEEDS_NEGATE:
channel = image.channel_images['opacity'].clone()
channel.negate()
else:
channel = image.channel_images['opacity']
opacity = Image(width=new_width, height=new_height, pseudo='xc:white') opacity = Image(width=new_width, height=new_height, pseudo='xc:white')
opacity.composite(channel, left=xoffset, top=yoffset) opacity.composite(image.channel_images['opacity'], left=xoffset, top=yoffset)
opacity.gaussian_blur(radius * image.width, sigma * image.width) opacity.gaussian_blur(radius * image.width, sigma * image.width)
opacity.negate() opacity.negate()
opacity.modulate(50) opacity.modulate(50)
shadow = Image(width=new_width, height=new_height, pseudo='xc:' + color) shadow = Image(width=new_width, height=new_height, pseudo='xc:' + color)
shadow.composite(opacity, operator=COPY_ALPHA) shadow.composite(opacity, operator='copy_opacity')
result = Image(width=new_width, height=new_height, pseudo='xc:transparent') result = Image(width=new_width, height=new_height, pseudo='xc:transparent')
result.composite(shadow)
result.composite(image) result.composite(image)
result.composite(shadow, operator='difference')
trimmed = result.clone() trimmed = result.clone()
trimmed.trim(color=Color('transparent')) trimmed.trim(color=Color('transparent'))