jitenbot/bot/yomichan/glossary/icons.py

133 lines
3.6 KiB
Python
Raw Permalink Normal View History

from bs4 import BeautifulSoup
from PIL import Image
from functools import cache
@cache
def calculate_ratio(path):
if path.endswith(".svg"):
ratio = __calculate_svg_ratio(path)
else:
ratio = __calculate_bitmap_ratio(path)
return ratio
@cache
def make_rectangle(path, text, rect_stroke, rect_fill, text_fill):
svg = __svg_text_rectangle(text, rect_stroke, rect_fill, text_fill)
with open(path, "w", encoding="utf-8") as f:
f.write(svg)
@cache
def make_monochrome_fill_rectangle(path, text):
svg = __svg_masked_rectangle(text)
with open(path, "w", encoding="utf-8") as f:
f.write(svg)
2023-07-18 05:43:38 +00:00
@cache
def make_accent(path):
svg = __svg_accent()
with open(path, "w", encoding="utf-8") as f:
f.write(svg)
@cache
def make_heiban(path):
svg = __svg_heiban()
with open(path, "w", encoding="utf-8") as f:
f.write(svg)
@cache
def make_red_char(path, char):
svg = __svg_red_character(char)
with open(path, "w", encoding="utf-8") as f:
f.write(svg)
def __calculate_svg_ratio(path):
2023-05-02 01:03:03 +00:00
with open(path, "r", encoding="utf-8") as f:
xml = f.read()
soup = BeautifulSoup(xml, "xml")
svg = soup.svg
if svg.has_attr("width") and svg.has_attr("height"):
width = float(svg.attrs["width"])
height = float(svg.attrs["height"])
ratio = width / height
elif svg.has_attr("viewBox"):
_, _, width, height = svg.attrs["viewBox"].split(" ")
ratio = float(width) / float(height)
else:
raise Exception(f"Cannot calculate ratio for SVG\n{svg.prettify()}")
return ratio
def __calculate_bitmap_ratio(path):
img = Image.open(path)
img_w = img.size[0]
img_h = img.size[1]
ratio = img_w / img_h
return ratio
def __svg_text_rectangle(text, rect_stroke, rect_fill, text_fill):
height = 128
width = len(text) * height
svg = f"""
<svg lang='ja' width='{width}' height='{height}' viewBox='0 0 {width} {height}'
xmlns='http://www.w3.org/2000/svg' version='1.1'>
<rect width='{width}' height='{height}' ry='20' stroke='{rect_stroke}'
fill='{rect_fill}' stroke-width='8'/>
<text text-anchor='middle' x='50%' y='50%' dy='.35em'
font-family='sans-serif' font-size='100px'
fill='{text_fill}'>{text}</text>
</svg>"""
return svg.strip()
def __svg_masked_rectangle(text):
height = 128
width = len(text) * height
svg = f"""
<svg lang='ja' width='{width}' height='{height}' viewBox='0 0 {width} {height}'
xmlns='http://www.w3.org/2000/svg' version='1.1'>
<mask id='a'>
<rect width='{width}' height='{height}' fill='white'/>
<text text-anchor='middle' x='50%' y='50%' dy='.35em'
font-family='sans-serif' font-size='100px'
fill='black'>{text}</text>
</mask>
<rect width='{width}' height='{height}' ry='20'
fill='black' mask='url(#a)'/>
</svg>"""
return svg.strip()
2023-07-18 05:43:38 +00:00
def __svg_heiban():
svg = f"""
<svg viewBox='0 0 210 300' xmlns='http://www.w3.org/2000/svg' version='1.1'>
<rect width='210' height='30' fill='red'/>
</svg>"""
return svg.strip()
def __svg_accent():
svg = f"""
<svg viewBox='0 0 150 300' xmlns='http://www.w3.org/2000/svg' version='1.1'>
<rect width='150' height='30' fill='red'/>
<rect width='30' height='150' x='120' fill='red'/>
</svg>"""
return svg.strip()
def __svg_red_character(char):
svg = f"""
<svg viewBox='0 0 300 300' xmlns='http://www.w3.org/2000/svg' version='1.1'>
<text text-anchor='middle' x='50%' y='50%' dy='.37em'
font-family='sans-serif' font-size='300px'
fill='red'>{char}</text>
</svg>"""
return svg.strip()