Commit 1316ceca authored by dmMaze's avatar dmMaze
Browse files

utilize qt's built-in gradient rendering for text

parent 41b51740
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -159,11 +159,11 @@ def ffmt_change_line_spacing_type(param_name: str, values: float, act_ffmt: Font
    for blkitem, value in zip(blkitems, values):
        blkitem.setLineSpacingType(value, restore_cursor=restore_cursor)

@font_formating(push_undostack=True)
@font_formating()
def handle_gradient_enabled(param_name: str, values: List[bool], act_ffmt: FontFormat, is_global: bool, blkitems: List[TextBlkItem], **kwargs):
    set_kwargs = global_default_set_kwargs if is_global else local_default_set_kwargs
    for blkitem, value in zip(blkitems, values):
        blkitem.fontformat.gradient_enabled = value
        blkitem.setGradientEnabled(value)
        blkitem.update()

@font_formating(push_undostack=True)
+35 −53
Original line number Diff line number Diff line
@@ -244,6 +244,8 @@ class TextBlkItem(QGraphicsTextItem):
            cursor.setCharFormat(cfmt)
            cursor.setBlockCharFormat(cfmt)
            self.setTextCursor(cursor)
        if self.fontformat.gradient_enabled:
            self.setGradientEnabled(True)
        self.update_effect(font_fmt, repaint=False)
        self.setStrokeWidth(font_fmt.stroke_width, repaint_background=False)
        self.repaint_background()
@@ -471,57 +473,6 @@ class TextBlkItem(QGraphicsTextItem):
            painter.drawRect(self.unpadRect(br))
        painter.restore()

        if self.fontformat.gradient_enabled:
            # Paint text to a temporary pixmap first
            pixmap = QPixmap(br.size().toSize())
            pixmap.fill(Qt.GlobalColor.transparent)
            temp_painter = QPainter(pixmap)
            temp_painter.setRenderHints(QPainter.RenderHint.Antialiasing | QPainter.RenderHint.TextAntialiasing)
            
            # Draw text in white
            doc = self.document()
            temp_painter.translate(doc.documentMargin(), doc.documentMargin())
            cursor = QTextCursor(doc)
            cursor.select(QTextCursor.SelectionType.Document)
            fmt = cursor.charFormat()
            fmt.setForeground(Qt.GlobalColor.white)
            cursor.mergeCharFormat(fmt)
            doc.drawContents(temp_painter)
            temp_painter.end()

            # Create gradient
            gradient = QLinearGradient()
            angle = self.fontformat.gradient_angle
            rad = math.radians(angle)
            dx = math.cos(rad)
            dy = math.sin(rad)
            
            # Set gradient points with size adjustment
            rect = br
            center = rect.center()
            radius = max(rect.width(), rect.height()) * self.fontformat.gradient_size
            gradient.setStart(center.x() - dx * radius, center.y() - dy * radius)
            gradient.setFinalStop(center.x() + dx * radius, center.y() + dy * radius)
            
            # Set gradient colors
            start_color = QColor(*self.fontformat.gradient_start_color)
            end_color = QColor(*self.fontformat.gradient_end_color)
            gradient.setColorAt(0, start_color)
            gradient.setColorAt(1, end_color)

            # Paint the gradient using the text as a mask
            painter.save()
            painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceOver)
            painter.setBrush(QBrush(gradient))
            painter.setPen(Qt.PenStyle.NoPen)
            painter.drawPixmap(br.topLeft(), pixmap)
            painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceIn)
            painter.drawRect(br)
            painter.restore()

            fmt.setForeground(QColor(*self.fontformat.frgb))
            cursor.mergeCharFormat(fmt)
        else:
        option.state = QStyle.State_None
        super().paint(painter, option, widget)

@@ -855,6 +806,37 @@ class TextBlkItem(QGraphicsTextItem):
        self.set_cursor_cfmt(cursor, cfmt, True)
        self._after_set_ffmt(cursor, repaint_background, restore_cursor, **after_kwargs)

    def setGradientEnabled(self, value: bool, repaint_background: bool = True, set_selected: bool = False, restore_cursor: bool = False):
        self.fontformat.gradient_enabled = value
        cursor, after_kwargs = self._before_set_ffmt(set_selected, restore_cursor)
        cfmt = QTextCharFormat()

        if value:
            gradient = QLinearGradient()
            angle = self.fontformat.gradient_angle
            rad = math.radians(angle)
            dx = math.cos(rad)
            dy = math.sin(rad)
            
            # Set gradient points with size adjustment
            rect = self.boundingRect()
            center = rect.center()
            radius = max(rect.width(), rect.height()) * self.fontformat.gradient_size
            gradient.setStart(center.x() - dx * radius, center.y() - dy * radius)
            gradient.setFinalStop(center.x() + dx * radius, center.y() + dy * radius)
            
            # Set gradient colors
            start_color = QColor(*self.fontformat.gradient_start_color)
            end_color = QColor(*self.fontformat.gradient_end_color)
            gradient.setColorAt(0, start_color)
            gradient.setColorAt(1, end_color)
            cfmt.setForeground(gradient)
        else:
            cfmt.setForeground(QColor(*self.fontformat.frgb))

        self.set_cursor_cfmt(cursor, cfmt, True)
        self._after_set_ffmt(cursor, repaint_background, restore_cursor, **after_kwargs)

    def setLineSpacing(self, value: float, repaint_background: bool = True, set_selected: bool = False, restore_cursor: bool = False):
        self.is_formatting = True
        self.fontformat.line_spacing = value