This repository has been archived on 2020-08-22. You can view files and clone it, but cannot push or open issues or pull requests.
pyaudviz/src/components/text.py

204 lines
7.3 KiB
Python

from PIL import ImageEnhance, ImageFilter, ImageChops
from PyQt5.QtGui import QColor, QFont
from PyQt5 import QtGui, QtCore, QtWidgets
import os
import logging
from component import Component
from toolkit.frame import FramePainter, PaintColor
log = logging.getLogger('AVP.Components.Text')
class Component(Component):
name = 'Title Text'
version = '1.0.1'
def widget(self, *args):
super().widget(*args)
self.title = 'Text'
self.alignment = 1
self.titleFont = QFont()
self.fontSize = self.height / 13.5
self.page.comboBox_textAlign.addItem("Left")
self.page.comboBox_textAlign.addItem("Middle")
self.page.comboBox_textAlign.addItem("Right")
self.page.comboBox_textAlign.setCurrentIndex(int(self.alignment))
self.page.spinBox_fontSize.setValue(int(self.fontSize))
self.page.lineEdit_title.setText(self.title)
self.page.pushButton_center.clicked.connect(self.centerXY)
self.page.fontComboBox_titleFont.currentFontChanged.connect(
self.update
)
self.trackWidgets({
'textColor': self.page.lineEdit_textColor,
'title': self.page.lineEdit_title,
'alignment': self.page.comboBox_textAlign,
'fontSize': self.page.spinBox_fontSize,
'xPosition': self.page.spinBox_xTextAlign,
'yPosition': self.page.spinBox_yTextAlign,
'fontStyle': self.page.comboBox_fontStyle,
'stroke': self.page.spinBox_stroke,
'strokeColor': self.page.lineEdit_strokeColor,
'shadow': self.page.checkBox_shadow,
'shadX': self.page.spinBox_shadX,
'shadY': self.page.spinBox_shadY,
'shadBlur': self.page.spinBox_shadBlur,
}, colorWidgets={
'textColor': self.page.pushButton_textColor,
'strokeColor': self.page.pushButton_strokeColor,
}, relativeWidgets=[
'xPosition', 'yPosition', 'fontSize',
'stroke', 'shadX', 'shadY', 'shadBlur'
])
self.centerXY()
def update(self):
self.titleFont = self.page.fontComboBox_titleFont.currentFont()
if self.page.checkBox_shadow.isChecked():
self.page.label_shadX.setHidden(False)
self.page.spinBox_shadX.setHidden(False)
self.page.spinBox_shadY.setHidden(False)
self.page.label_shadBlur.setHidden(False)
self.page.spinBox_shadBlur.setHidden(False)
else:
self.page.label_shadX.setHidden(True)
self.page.spinBox_shadX.setHidden(True)
self.page.spinBox_shadY.setHidden(True)
self.page.label_shadBlur.setHidden(True)
self.page.spinBox_shadBlur.setHidden(True)
def centerXY(self):
self.setRelativeWidget('xPosition', 0.5)
self.setRelativeWidget('yPosition', 0.521)
def getXY(self):
'''Returns true x, y after considering alignment settings'''
fm = QtGui.QFontMetrics(self.titleFont)
x = self.pixelValForAttr('xPosition')
if self.alignment == 1: # Middle
offset = int(fm.width(self.title)/2)
x -= offset
if self.alignment == 2: # Right
offset = fm.width(self.title)
x -= offset
return x, self.yPosition
def loadPreset(self, pr, *args):
super().loadPreset(pr, *args)
font = QFont()
font.fromString(pr['titleFont'])
self.page.fontComboBox_titleFont.setCurrentFont(font)
def savePreset(self):
saveValueStore = super().savePreset()
saveValueStore['titleFont'] = self.titleFont.toString()
return saveValueStore
def previewRender(self):
return self.addText(self.width, self.height)
def properties(self):
props = ['static']
if not self.title:
props.append('error')
return props
def error(self):
return "No text provided."
def frameRender(self, frameNo):
return self.addText(self.width, self.height)
def addText(self, width, height):
font = self.titleFont
font.setPixelSize(self.fontSize)
font.setStyle(QFont.StyleNormal)
font.setWeight(QFont.Normal)
font.setCapitalization(QFont.MixedCase)
if self.fontStyle == 1:
font.setWeight(QFont.DemiBold)
if self.fontStyle == 2:
font.setWeight(QFont.Bold)
elif self.fontStyle == 3:
font.setStyle(QFont.StyleItalic)
elif self.fontStyle == 4:
font.setWeight(QFont.Bold)
font.setStyle(QFont.StyleItalic)
elif self.fontStyle == 5:
font.setStyle(QFont.StyleOblique)
elif self.fontStyle == 6:
font.setCapitalization(QFont.SmallCaps)
image = FramePainter(width, height)
x, y = self.getXY()
log.debug('Text position translates to %s, %s', x, y)
if self.stroke > 0:
outliner = QtGui.QPainterPathStroker()
outliner.setWidth(self.stroke)
path = QtGui.QPainterPath()
if self.fontStyle == 6:
# PathStroker ignores smallcaps so we need this weird hack
path.addText(x, y, font, self.title[0])
fm = QtGui.QFontMetrics(font)
newX = x + fm.width(self.title[0])
strokeFont = self.page.fontComboBox_titleFont.currentFont()
strokeFont.setCapitalization(QFont.SmallCaps)
strokeFont.setPixelSize(int((self.fontSize / 7) * 5))
strokeFont.setLetterSpacing(QFont.PercentageSpacing, 139)
path.addText(newX, y, strokeFont, self.title[1:])
else:
path.addText(x, y, font, self.title)
path = outliner.createStroke(path)
image.setPen(QtCore.Qt.NoPen)
image.setBrush(PaintColor(*self.strokeColor))
image.drawPath(path)
image.setFont(font)
image.setPen(self.textColor)
image.drawText(x, y, self.title)
# turn QImage into Pillow frame
frame = image.finalize()
if self.shadow:
shadImg = ImageEnhance.Contrast(frame).enhance(0.0)
shadImg = shadImg.filter(ImageFilter.GaussianBlur(self.shadBlur))
shadImg = ImageChops.offset(shadImg, self.shadX, self.shadY)
shadImg.paste(frame, box=(0, 0), mask=frame)
frame = shadImg
return frame
def commandHelp(self):
print('Enter a string to use as centred white text:')
print(' "title=User Error"')
print('Specify a text color:\n color=255,255,255')
print('Set custom x, y position:\n x=500 y=500')
def command(self, arg):
if '=' in arg:
key, arg = arg.split('=', 1)
if key == 'color':
self.page.lineEdit_textColor.setText(arg)
return
elif key == 'size':
self.page.spinBox_fontSize.setValue(int(arg))
return
elif key == 'x':
self.page.spinBox_xTextAlign.setValue(int(arg))
return
elif key == 'y':
self.page.spinBox_yTextAlign.setValue(int(arg))
return
elif key == 'title':
self.page.lineEdit_title.setText(arg)
return
super().command(arg)