Spaces:
Running
Running
""" | |
Donut | |
Copyright (c) 2022-present NAVER Corp. | |
MIT License | |
""" | |
from collections import OrderedDict | |
import numpy as np | |
from synthtiger import components | |
from elements.textbox import TextBox | |
from layouts import GridStack | |
class TextReader: | |
def __init__(self, path, cache_size=2 ** 28, block_size=2 ** 20): | |
self.fp = open(path, "r", encoding="utf-8") | |
self.length = 0 | |
self.offsets = [0] | |
self.cache = OrderedDict() | |
self.cache_size = cache_size | |
self.block_size = block_size | |
self.bucket_size = cache_size // block_size | |
self.idx = 0 | |
while True: | |
text = self.fp.read(self.block_size) | |
if not text: | |
break | |
self.length += len(text) | |
self.offsets.append(self.fp.tell()) | |
def __len__(self): | |
return self.length | |
def __iter__(self): | |
return self | |
def __next__(self): | |
char = self.get() | |
self.next() | |
return char | |
def move(self, idx): | |
self.idx = idx | |
def next(self): | |
self.idx = (self.idx + 1) % self.length | |
def prev(self): | |
self.idx = (self.idx - 1) % self.length | |
def get(self): | |
key = self.idx // self.block_size | |
if key in self.cache: | |
text = self.cache[key] | |
else: | |
if len(self.cache) >= self.bucket_size: | |
self.cache.popitem(last=False) | |
offset = self.offsets[key] | |
self.fp.seek(offset, 0) | |
text = self.fp.read(self.block_size) | |
self.cache[key] = text | |
self.cache.move_to_end(key) | |
char = text[self.idx % self.block_size] | |
return char | |
class Content: | |
def __init__(self, config): | |
self.margin = config.get("margin", [0, 0.1]) | |
self.reader = TextReader(**config.get("text", {})) | |
self.font = components.BaseFont(**config.get("font", {})) | |
self.layout = GridStack(config.get("layout", {})) | |
self.textbox = TextBox(config.get("textbox", {})) | |
self.textbox_color = components.Switch(components.Gray(), **config.get("textbox_color", {})) | |
self.content_color = components.Switch(components.Gray(), **config.get("content_color", {})) | |
def generate(self, size): | |
width, height = size | |
layout_left = width * np.random.uniform(self.margin[0], self.margin[1]) | |
layout_top = height * np.random.uniform(self.margin[0], self.margin[1]) | |
layout_width = max(width - layout_left * 2, 0) | |
layout_height = max(height - layout_top * 2, 0) | |
layout_bbox = [layout_left, layout_top, layout_width, layout_height] | |
text_layers, texts = [], [] | |
layouts = self.layout.generate(layout_bbox) | |
self.reader.move(np.random.randint(len(self.reader))) | |
for layout in layouts: | |
font = self.font.sample() | |
for bbox, align in layout: | |
x, y, w, h = bbox | |
text_layer, text = self.textbox.generate((w, h), self.reader, font) | |
self.reader.prev() | |
if text_layer is None: | |
continue | |
text_layer.center = (x + w / 2, y + h / 2) | |
if align == "left": | |
text_layer.left = x | |
if align == "right": | |
text_layer.right = x + w | |
self.textbox_color.apply([text_layer]) | |
text_layers.append(text_layer) | |
texts.append(text) | |
self.content_color.apply(text_layers) | |
return text_layers, texts | |