Last active
July 27, 2021 00:47
-
-
Save s-m-e/527b26ad2423a11999bb9c3f887a0e96 to your computer and use it in GitHub Desktop.
A Python (3) class for figuring out the width and height of a formatted svg text.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
# Loosely based on http://stackoverflow.com/a/28741636/1672565 | |
import subprocess | |
import struct | |
import os | |
class svg_text_length(object): | |
def __init__( | |
self, text = 'Hello World', | |
font = 'Arial', font_size = 10, font_weight = 400, font_style = 'normal', | |
clean_up = True | |
): | |
# Cross-platform ... | |
temp_svg_name = 'temp_svg_text_length.svg' | |
temp_png_name = 'temp_svg_text_length.png' | |
# Speeding this thing up on Linux for lots of queries! | |
# temp_svg_name = '/dev/shm/temp_svg_text_length.svg' | |
# temp_png_name = '/dev/shm/temp_svg_text_length.png' | |
svg_cnt = self.__get_dummy_svg__(text, font, font_size, font_weight, font_style) | |
self.__write_text__(temp_svg_name, svg_cnt) | |
self.__convert_svg2png__(temp_svg_name, temp_png_name) | |
png_cnt = self.__read_binary__(temp_png_name) | |
self.width, self.height = self.__get_image_info__(png_cnt) | |
if clean_up: | |
self.__clean_up__([temp_svg_name, temp_png_name]) | |
def get_size(self): | |
return self.width, self.height | |
def get_width(self): | |
return self.width | |
def __clean_up__(self, file_names): | |
for file_name in file_names: | |
os.remove(file_name) | |
def __convert_svg2png__(self, dest, targ): | |
# TODO not exactly cross platform ... | |
inkscape_p = subprocess.Popen( | |
['inkscape', '-f', dest, '-e', targ, '-d', '90', '-D'], | |
stdin = subprocess.PIPE, | |
stdout = subprocess.PIPE | |
) | |
inkscape_out = inkscape_p.communicate()[0].decode(encoding = 'UTF-8') | |
def __get_dummy_svg__(self, text, font, font_size, font_weight, font_style): | |
return ''' | |
<svg xmlns="http://www.w3.org/2000/svg"> | |
<text | |
font-weight="%d" font-size="%0.2f" font-family="%s" letter-spacing="0" | |
font-style="%s" word-spacing="0"> | |
<tspan font-family="%s">%s</tspan> | |
</text> | |
</svg> | |
''' % (font_weight, font_size, font, font_style, font, text) | |
def __get_image_info__(self, data): | |
if self.__is_png__(data): | |
w, h = struct.unpack('>LL', data[16:24]) | |
width = int(w) | |
height = int(h) | |
else: | |
raise Exception('not a png image') | |
return width, height | |
def __is_png__(self, data): | |
return (data[:8] == b'\x89PNG\r\n\x1a\n'and (data[12:16] == b'IHDR')) | |
def __read_binary__(self, file_name): | |
f = open(file_name, 'rb') | |
data = f.read() | |
f.close() | |
return data | |
def __write_text__(self, file_name, cnt): | |
f = open(file_name, 'w') | |
f.write(cnt) | |
f.close() | |
if __name__ == '__main__': | |
print(svg_text_length( | |
text = 'Hello world! Even more text.', | |
font = 'Arial', | |
font_size = 25.0, | |
font_weight = 400, | |
font_style = 'italic', | |
clean_up = False | |
).get_size()) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment