Loading ballontranslator/ui/misc.py +13 −0 Original line number Diff line number Diff line Loading @@ -498,6 +498,19 @@ class ProgramConfig: self.let_uppercase_flag = let_uppercase_flag class LruIgnoreArgs: def __init__(self, **kwargs) -> None: for key in kwargs: setattr(self, key, kwargs[key]) def __hash__(self) -> int: return hash(type(self)) def __eq__(self, other): return isinstance(other, type(self)) span_pattern = re.compile(r'<span style=\"(.*?)\">', re.DOTALL) p_pattern = re.compile(r'<p style=\"(.*?)\">', re.DOTALL) fragment_pattern = re.compile(r'<!--(.*?)Fragment-->', re.DOTALL) Loading ballontranslator/ui/textlayout.py +49 −9 Original line number Diff line number Diff line from qtpy.QtCore import Qt, QRectF, QPointF, QPoint, Signal, QSizeF from qtpy.QtGui import QTransform, QPalette, QPainter, QTextFrame, QTextBlock, QAbstractTextDocumentLayout, QTextLayout, QFont, QFontMetrics, QTextOption, QTextLine, QTextFormat, QTextFragment from qtpy.QtCore import Qt, QRectF, QPointF, QPoint, Signal, QSizeF, QSize from qtpy.QtGui import QImage, QTransform, QPalette, QPainter, QTextFrame, QTextBlock, QAbstractTextDocumentLayout, QTextLayout, QFont, QFontMetrics, QTextOption, QTextLine, QTextFormat, QTextFragment from typing import List, Set import cv2 from typing import List, Set, Any from functools import lru_cache, cached_property from .misc import pixmap2ndarray, LruIgnoreArgs def print_transform(tr: QTransform): print(f'[[{tr.m11(), tr.m12(), tr.m13()}]\n [{tr.m21(), tr.m22(), tr.m23()}]\n [{tr.m31(), tr.m32(), tr.m33()}]]') Loading @@ -16,7 +19,7 @@ PUNSET_PAUSEORSTOP = {'。', '.', ',', '、', ':', ';', '!', '‼', ' PUNSET_BRACKETL = {'「', '『', '“', '‘', '(', '《', '〈', '【', '〖', '〔', '[', '{'} PUNSET_BRACKETR = {'」', '』', '”', '’', ')', '》', '〉', '】', '〗', '〕', ']', '}'} PUNSET_BRACKET = PUNSET_BRACKETL.union(PUNSET_BRACKETR) PUNSET_NONBRACKET = {'⸺', '…', '⋯', '~', '-', '–', '—', '_', '﹏', '●', '•'} PUNSET_NONBRACKET = {'⸺', '…', '⋯', '~', '-', '–', '—', '_', '﹏', '●', '•', '~'} PUNSET_VERNEEDROTATE = PUNSET_NONBRACKET.union(PUNSET_BRACKET).union(PUNSET_HALF) Loading @@ -37,6 +40,18 @@ def get_char_width(char: str, ffamily: str, size: float) -> int: fm = _font_metrics(ffamily, size) return fm.width(char) # @lru_cache(maxsize=1024) # buggy to work with lru def punc_actual_rect(line: LruIgnoreArgs, family: str, size: float, weight: int) -> List[int]: # QtextLine line is invisibale to lru line: QTextLine = line.line pixmap = QImage(line.naturalTextWidth(), line.height(), QImage.Format.Format_ARGB32) pixmap.fill(Qt.GlobalColor.transparent) p = QPainter(pixmap) line.draw(p, QPointF(-line.x(), -line.y())) p.end() mask = pixmap2ndarray(pixmap, keep_alpha=True)[..., -1] return cv2.boundingRect(cv2.findNonZero(mask)) class CharFontFormat: def __init__(self, font: QFont) -> None: Loading @@ -58,6 +73,23 @@ class CharFontFormat: def punc_rect(self, punc: str) -> List[QRectF]: return get_punc_rect(punc, self.font.family(), self.font.pointSizeF()) @property def family(self) -> str: return self.font.family() @property def weight(self) -> float: return self.font.weight() @property def size(self) -> float: return self.font.pointSizeF() def punc_actual_rect(self, line: QTextLine) -> List[int]: line = LruIgnoreArgs(line=line) ar = punc_actual_rect(line, self.family, self.size, self.weight) return ar class VerticalTextDocumentLayout(QAbstractTextDocumentLayout): size_enlarged = Signal() Loading Loading @@ -187,6 +219,10 @@ class VerticalTextDocumentLayout(QAbstractTextDocumentLayout): if char in PUNSET_VERNEEDROTATE: char = blk_text[char_idx] line_x, line_y = line.x(), line.y() if char in PUNSET_NONBRACKET: non_bracket_br = cfmt.punc_actual_rect(line) y_x = line_y - line_x y_p_x = line_y + line_x transform = QTransform(0, 1, 0, -1, 0, 0, y_p_x, y_x, 1) Loading @@ -194,16 +230,22 @@ class VerticalTextDocumentLayout(QAbstractTextDocumentLayout): painter.setTransform(transform, True) pun_tbr, pun_br = cfmt.punc_rect(char) hight_comp = pun_tbr.width() - pun_br.width() + 2 if char.isalpha(): yoff = -cfmt.tbr.top() - fm.ascent() - cfmt.tbr.width() hight_comp = 0 elif char in PUNSET_NONBRACKET: yoff = -non_bracket_br[1] - non_bracket_br[3] if self.punc_align_center: yoff = yoff - cfmt.tbr.width() / 2 + non_bracket_br[3] / 3 else: yoff = yoff - cfmt.tbr.width() + non_bracket_br[3] else: yoff = -pun_tbr.top() - fm.ascent() - pun_tbr.height() / 2 - cfmt.br.width() / 2 if char in PUNSET_NONBRACKET: yoff = -cfmt.tbr.width() - pun_br.height() + cfmt.br.width() # line.draw(painter, QPointF(hight_comp, yoff - pun_tbr.height()), o) line.draw(painter, QPointF(hight_comp, yoff), o) painter.setTransform(inv_transform, True) elif char in PUNSET_PAUSEORSTOP: pun_tbr, pun_br = cfmt.punc_rect(char) yoff = pun_br.top() - pun_tbr.top() Loading @@ -214,9 +256,7 @@ class VerticalTextDocumentLayout(QAbstractTextDocumentLayout): xoff -= line.naturalTextWidth() - cfmt.br.width() xoff += cfmt.br.width() - pun_tbr.width() line.draw(painter, QPointF(xoff, yoff), o) # p = QPainter() else: yoff = 0 yoff = line.naturalTextWidth() - cfmt.br.width() line.draw(painter, QPointF(-yoff, -cfmt.tbr.top() - fm.ascent() + yoff), o) Loading Loading
ballontranslator/ui/misc.py +13 −0 Original line number Diff line number Diff line Loading @@ -498,6 +498,19 @@ class ProgramConfig: self.let_uppercase_flag = let_uppercase_flag class LruIgnoreArgs: def __init__(self, **kwargs) -> None: for key in kwargs: setattr(self, key, kwargs[key]) def __hash__(self) -> int: return hash(type(self)) def __eq__(self, other): return isinstance(other, type(self)) span_pattern = re.compile(r'<span style=\"(.*?)\">', re.DOTALL) p_pattern = re.compile(r'<p style=\"(.*?)\">', re.DOTALL) fragment_pattern = re.compile(r'<!--(.*?)Fragment-->', re.DOTALL) Loading
ballontranslator/ui/textlayout.py +49 −9 Original line number Diff line number Diff line from qtpy.QtCore import Qt, QRectF, QPointF, QPoint, Signal, QSizeF from qtpy.QtGui import QTransform, QPalette, QPainter, QTextFrame, QTextBlock, QAbstractTextDocumentLayout, QTextLayout, QFont, QFontMetrics, QTextOption, QTextLine, QTextFormat, QTextFragment from qtpy.QtCore import Qt, QRectF, QPointF, QPoint, Signal, QSizeF, QSize from qtpy.QtGui import QImage, QTransform, QPalette, QPainter, QTextFrame, QTextBlock, QAbstractTextDocumentLayout, QTextLayout, QFont, QFontMetrics, QTextOption, QTextLine, QTextFormat, QTextFragment from typing import List, Set import cv2 from typing import List, Set, Any from functools import lru_cache, cached_property from .misc import pixmap2ndarray, LruIgnoreArgs def print_transform(tr: QTransform): print(f'[[{tr.m11(), tr.m12(), tr.m13()}]\n [{tr.m21(), tr.m22(), tr.m23()}]\n [{tr.m31(), tr.m32(), tr.m33()}]]') Loading @@ -16,7 +19,7 @@ PUNSET_PAUSEORSTOP = {'。', '.', ',', '、', ':', ';', '!', '‼', ' PUNSET_BRACKETL = {'「', '『', '“', '‘', '(', '《', '〈', '【', '〖', '〔', '[', '{'} PUNSET_BRACKETR = {'」', '』', '”', '’', ')', '》', '〉', '】', '〗', '〕', ']', '}'} PUNSET_BRACKET = PUNSET_BRACKETL.union(PUNSET_BRACKETR) PUNSET_NONBRACKET = {'⸺', '…', '⋯', '~', '-', '–', '—', '_', '﹏', '●', '•'} PUNSET_NONBRACKET = {'⸺', '…', '⋯', '~', '-', '–', '—', '_', '﹏', '●', '•', '~'} PUNSET_VERNEEDROTATE = PUNSET_NONBRACKET.union(PUNSET_BRACKET).union(PUNSET_HALF) Loading @@ -37,6 +40,18 @@ def get_char_width(char: str, ffamily: str, size: float) -> int: fm = _font_metrics(ffamily, size) return fm.width(char) # @lru_cache(maxsize=1024) # buggy to work with lru def punc_actual_rect(line: LruIgnoreArgs, family: str, size: float, weight: int) -> List[int]: # QtextLine line is invisibale to lru line: QTextLine = line.line pixmap = QImage(line.naturalTextWidth(), line.height(), QImage.Format.Format_ARGB32) pixmap.fill(Qt.GlobalColor.transparent) p = QPainter(pixmap) line.draw(p, QPointF(-line.x(), -line.y())) p.end() mask = pixmap2ndarray(pixmap, keep_alpha=True)[..., -1] return cv2.boundingRect(cv2.findNonZero(mask)) class CharFontFormat: def __init__(self, font: QFont) -> None: Loading @@ -58,6 +73,23 @@ class CharFontFormat: def punc_rect(self, punc: str) -> List[QRectF]: return get_punc_rect(punc, self.font.family(), self.font.pointSizeF()) @property def family(self) -> str: return self.font.family() @property def weight(self) -> float: return self.font.weight() @property def size(self) -> float: return self.font.pointSizeF() def punc_actual_rect(self, line: QTextLine) -> List[int]: line = LruIgnoreArgs(line=line) ar = punc_actual_rect(line, self.family, self.size, self.weight) return ar class VerticalTextDocumentLayout(QAbstractTextDocumentLayout): size_enlarged = Signal() Loading Loading @@ -187,6 +219,10 @@ class VerticalTextDocumentLayout(QAbstractTextDocumentLayout): if char in PUNSET_VERNEEDROTATE: char = blk_text[char_idx] line_x, line_y = line.x(), line.y() if char in PUNSET_NONBRACKET: non_bracket_br = cfmt.punc_actual_rect(line) y_x = line_y - line_x y_p_x = line_y + line_x transform = QTransform(0, 1, 0, -1, 0, 0, y_p_x, y_x, 1) Loading @@ -194,16 +230,22 @@ class VerticalTextDocumentLayout(QAbstractTextDocumentLayout): painter.setTransform(transform, True) pun_tbr, pun_br = cfmt.punc_rect(char) hight_comp = pun_tbr.width() - pun_br.width() + 2 if char.isalpha(): yoff = -cfmt.tbr.top() - fm.ascent() - cfmt.tbr.width() hight_comp = 0 elif char in PUNSET_NONBRACKET: yoff = -non_bracket_br[1] - non_bracket_br[3] if self.punc_align_center: yoff = yoff - cfmt.tbr.width() / 2 + non_bracket_br[3] / 3 else: yoff = yoff - cfmt.tbr.width() + non_bracket_br[3] else: yoff = -pun_tbr.top() - fm.ascent() - pun_tbr.height() / 2 - cfmt.br.width() / 2 if char in PUNSET_NONBRACKET: yoff = -cfmt.tbr.width() - pun_br.height() + cfmt.br.width() # line.draw(painter, QPointF(hight_comp, yoff - pun_tbr.height()), o) line.draw(painter, QPointF(hight_comp, yoff), o) painter.setTransform(inv_transform, True) elif char in PUNSET_PAUSEORSTOP: pun_tbr, pun_br = cfmt.punc_rect(char) yoff = pun_br.top() - pun_tbr.top() Loading @@ -214,9 +256,7 @@ class VerticalTextDocumentLayout(QAbstractTextDocumentLayout): xoff -= line.naturalTextWidth() - cfmt.br.width() xoff += cfmt.br.width() - pun_tbr.width() line.draw(painter, QPointF(xoff, yoff), o) # p = QPainter() else: yoff = 0 yoff = line.naturalTextWidth() - cfmt.br.width() line.draw(painter, QPointF(-yoff, -cfmt.tbr.top() - fm.ascent() + yoff), o) Loading