Optimize social plugin: cache word width computation

This commit is contained in:
Oleh Prypin 2022-10-17 13:39:12 +02:00
parent c681be2f7f
commit 38aca1e206
No known key found for this signature in database
GPG Key ID: A93637E52C2AD3F5
2 changed files with 24 additions and 12 deletions

View File

@ -206,26 +206,32 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]):
def _render_card_background(self, size, fill): def _render_card_background(self, size, fill):
return Image.new(mode = "RGBA", size = size, color = fill) return Image.new(mode = "RGBA", size = size, color = fill)
@functools.lru_cache(maxsize=None)
def _tmp_context(self):
image = Image.new(mode = "RGBA", size = (50, 50))
return ImageDraw.Draw(image)
@functools.lru_cache(maxsize=None)
def _text_bounding_box(self, text, font):
return self._tmp_context().textbbox((0, 0), text, font = font)
# Render social card text # Render social card text
def _render_text(self, size, font, text, lmax, spacing = 0): def _render_text(self, size, font, text, lmax, spacing = 0):
width = size[0]
lines, words = [], [] lines, words = [], []
# Remove remnant HTML tags # Remove remnant HTML tags
text = re.sub(r"(<[^>]+>)", "", text) text = re.sub(r"(<[^>]+>)", "", text)
# Create temporary image
image = Image.new(mode = "RGBA", size = size)
# Retrieve y-offset of textbox to correct for spacing # Retrieve y-offset of textbox to correct for spacing
yoffset = 0 yoffset = 0
# Create drawing context and split text into lines # Create drawing context and split text into lines
context = ImageDraw.Draw(image)
for word in text.split(" "): for word in text.split(" "):
combine = " ".join(words + [word]) combine = " ".join(words + [word])
textbox = context.textbbox((0, 0), combine, font = font) textbox = self._text_bounding_box(combine, font = font)
yoffset = textbox[1] yoffset = textbox[1]
if not words or textbox[2] <= image.width: if not words or textbox[2] <= width:
words.append(word) words.append(word)
else: else:
lines.append(words) lines.append(words)

View File

@ -206,26 +206,32 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]):
def _render_card_background(self, size, fill): def _render_card_background(self, size, fill):
return Image.new(mode = "RGBA", size = size, color = fill) return Image.new(mode = "RGBA", size = size, color = fill)
@functools.lru_cache(maxsize=None)
def _tmp_context(self):
image = Image.new(mode = "RGBA", size = (50, 50))
return ImageDraw.Draw(image)
@functools.lru_cache(maxsize=None)
def _text_bounding_box(self, text, font):
return self._tmp_context().textbbox((0, 0), text, font = font)
# Render social card text # Render social card text
def _render_text(self, size, font, text, lmax, spacing = 0): def _render_text(self, size, font, text, lmax, spacing = 0):
width = size[0]
lines, words = [], [] lines, words = [], []
# Remove remnant HTML tags # Remove remnant HTML tags
text = re.sub(r"(<[^>]+>)", "", text) text = re.sub(r"(<[^>]+>)", "", text)
# Create temporary image
image = Image.new(mode = "RGBA", size = size)
# Retrieve y-offset of textbox to correct for spacing # Retrieve y-offset of textbox to correct for spacing
yoffset = 0 yoffset = 0
# Create drawing context and split text into lines # Create drawing context and split text into lines
context = ImageDraw.Draw(image)
for word in text.split(" "): for word in text.split(" "):
combine = " ".join(words + [word]) combine = " ".join(words + [word])
textbox = context.textbbox((0, 0), combine, font = font) textbox = self._text_bounding_box(combine, font = font)
yoffset = textbox[1] yoffset = textbox[1]
if not words or textbox[2] <= image.width: if not words or textbox[2] <= width:
words.append(word) words.append(word)
else: else:
lines.append(words) lines.append(words)