Files
VX5_KRO_GearPump/scene/pictextitem.cpp
T
2026-06-25 11:04:34 +08:00

485 lines
12 KiB
C++

#include <QtGui>
#include "pictextitem.h"
#include "picscene.h"
#include <cmath>
#include <QPainter>
//#include "moveinput.h"
#include <QStyleOptionGraphicsItem>
//extern MoveInput* moveInput;
PicTextItem::PicTextItem(QGraphicsItem *parent, QGraphicsScene *scene, const SourceType t) :
QGraphicsTextItem(parent), //edit@02-07
m_sourceType(t)
{
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemIsSelectable);
setFlag(QGraphicsItem::ItemIsFocusable);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
QFont f("Dinkie9");
// font.setFamily("wenquanyi");
// font.setPixelSize(5);
f.setLetterSpacing(QFont::AbsoluteSpacing, 1);
setFont(f);
document()->setDefaultStyleSheet("p { margin: 0; }");
document()->setDocumentMargin(0);
SpecialConditions = false;
CatchCnt1CurrValue = -1;
CatchCnt1StartValue = -1;
}
PicTextItem::~PicTextItem()
{
}
QVariant PicTextItem::source()
{
return m_source;
}
QImage clipImage(QImage img, const QRgb bg)
{
QRect clipRect;
for(int x = 0; x < img.width(); ++x) {
for(int y = 0; y < img.height(); ++y) {
auto rgb = img.pixel(x, y);
if(rgb != bg) {
clipRect.setLeft(x);
goto top;
}
}
}
top:
for(int y = 0; y < img.height(); ++y) {
for(int x = 0; x < img.width(); ++x) {
if(img.pixel(x, y) != bg) {
clipRect.setTop(y);
goto right;
}
}
}
right:
for(int x = img.width() - 1; x >= 0; --x) {
for(int y = 0; y < img.height(); ++y) {
if(img.pixel(x, y) != bg) {
clipRect.setRight(x + 1);
goto bottom;
}
}
}
bottom:
for(int y = img.height() - 1; y >= 0; --y) {
for(int x = 0; x < img.width(); ++x) {
if(img.pixel(x, y) != bg) {
clipRect.setBottom(y + 1);
goto end;
}
}
}
end:
QRect originRect = img.rect();
return img.copy(clipRect);
}
QImage PicTextItem::applyImgeTranslation(QImage img)
{
auto scaledWidth = boldMultiple() * img.width();
QImage ret = img.scaled(QSize(scaledWidth, img.height()));
switch(direction()) {
case NORMAL:
break;
case MIRROR_V:
ret = ret.mirrored(false, true);
break;
case MIRROR_H:
ret = ret.mirrored(true, false);
break;
case MIRROR_VH:
ret = ret.mirrored(true, true);
break;
case MIRROR_H_R270: {
QTransform trans;
trans.rotate(180, Qt::YAxis);
trans.rotate(270.0);
ret = ret.transformed(trans);
break;
}
case R90:
{
QTransform trans;
trans.rotate(90.0);
ret = ret.transformed(trans);
break;
}
case R270:
{
QTransform trans;
trans.rotate(270.0);
ret = ret.transformed(trans);
break;
}
case MIRROR_V_R270:
{
QTransform trans;
trans.rotate(180, Qt::XAxis);
trans.rotate(270.0);
ret = ret.transformed(trans);
break;
}
default:
break;
}
// TODOD:: 添加颜色翻转功能
return ret;
}
void PicTextItem::setSource(QVariant var)
{
m_source = var;
if(SourceType::TEXT != sourceType())
return;
m_untransImage = strToImage(m_source.toString());
applyModify();
}
int PicTextItem::setBoldMultiple(int multiple)
{
m_boldMultiple = multiple;
}
void PicTextItem::setDirection(ItemDirectionType dir)
{
m_direction = dir;
}
void PicTextItem::setColorReversal(bool b)
{
m_colorReversal = b;
colorReversalChanged();
}
void PicTextItem::setCustomFont(QString name)
{
auto newFont = QFont(name);
newFont.setLetterSpacing(QFont::AbsoluteSpacing, letterSpace());
newFont.setStyleStrategy(QFont::NoAntialias);
setFont(newFont);
setSource(source());
}
int PicTextItem::letterSpace()
{
return int(font().letterSpacing());
}
void PicTextItem::setLetterSpace(int space)
{
auto f = font();
f.setLetterSpacing(QFont::AbsoluteSpacing, space);
setFont(f);
letterSpaceChanged();
}
void PicTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
if(sourceType() == SourceType::UNKNOWN) {
QGraphicsTextItem::paint(painter, option, widget);
return;
}
painter->save();
auto r = option->rect;
painter->setFont(font());
painter->drawImage(r, m_itemImage);
if(isSelected()) {
painter->setPen("red");
painter->drawRect(r);
}
painter->restore();
}
QRectF PicTextItem::boundingRect() const
{
if(sourceType() == SourceType::UNKNOWN)
return QGraphicsTextItem::boundingRect();
const QRectF fr(0, 0, m_itemImage.width(), m_itemImage.height());
return fr;
}
QPainterPath PicTextItem::shape() const
{
QPainterPath path;
path.addRect(boundingRect());
return path;
}
void PicTextItem::setAttrs(const QXmlStreamAttributes &attrs)
{
auto dirRef = attrs.value("dir");
if(!dirRef.isEmpty()) {
bool ok = false;
auto d = dirRef.toInt(&ok);
if(ok)
setDirection((ItemDirectionType)d);
}
auto boldMultipleRef = attrs.value("boldMultiple");
if(!boldMultipleRef.isEmpty()) {
bool ok = false;
auto b = boldMultipleRef.toInt(&ok);
if(ok)
setBoldMultiple(b);
}
auto colorReversalRef = attrs.value("colorReversal");
if(!colorReversalRef.isEmpty()) {
auto s = colorReversalRef.toString().toLower();
if(s == "true" || s == "false") {
setColorReversal(s == "true");
}
}
auto letterSpaceRef = attrs.value("letterSpace");
if(!letterSpaceRef.isEmpty()) {
bool ok = false;
auto l = letterSpaceRef.toInt(&ok);
if(ok) {
QFont f = font();
f.setLetterSpacing(QFont::AbsoluteSpacing, l);
setFont(f);
}
}
auto fontFamilyRef = attrs.value("fontFamilay");
if(!fontFamilyRef.isEmpty()) {
setCustomFont(fontFamilyRef.toString());
}
qDebug() << "Text item properties: \r\n"
<< "\t direction: " << direction()
<< "\t boldMultiple: " << boldMultiple()
<< "\t colorReversal: " << colorReversal()
<< "\t letterSpace: " << letterSpace()
<< "\t fontFamily: " << font().family();
setCustomAttrs(attrs);
}
void PicTextItem::saveAttrs(QXmlStreamAttributes &attrs)
{
attrs.append("dir", QString::number(direction()));
attrs.append("boldMultiple", QString::number(boldMultiple()));
attrs.append("colorReversal", colorReversal() ? "true" : "false");
attrs.append("letterSpace", QString::number(int(font().letterSpacing())));
attrs.append("fontFamilay", font().family());
saveCustomAttrs(attrs);
}
void PicTextItem::applyModify()
{
auto img = itemImage();
if(img.isNull()) {
img = emptyImage();
}
prepareGeometryChange();
m_itemImage = applyImgeTranslation(img);
update();
if(scene())
scene()->update();
}
QImage PicTextItem::preview()
{
return m_itemImage;
}
void PicTextItem::setTextItemModel(const TextItemModel &model)
{
setLetterSpace(model.letterSpace);
setBoldMultiple(model.boldMultiple);
setDirection(model.direction);
setColorReversal(model.colorReversal);
}
TextItemModel PicTextItem::textItemModel()
{
return TextItemModel::fromItem(this);
}
//! [1]
QVariant PicTextItem::itemChange(GraphicsItemChange change,
const QVariant &value)
{
if (change == ItemSceneChange && scene()) {
QPointF newPos = value.toPoint();
QRectF rect = scene()->sceneRect();
if (!rect.contains(newPos)) {
newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));
newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
}
}
return QGraphicsItem::itemChange(change, value);
}
//! [1]
//! [2]
void PicTextItem::focusOutEvent(QFocusEvent *event)
{
// moveInput->hide();
emit lostFocus(this);
QGraphicsTextItem::focusOutEvent(event);
//
}
//! [2]
//! [5]
void PicTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
//if (textInteractionFlags() == Qt::NoTextInteraction)
// setTextInteractionFlags(Qt::TextEditorInteraction);
//setTextInteractionFlags(Qt::TextBrowserInteraction);
QGraphicsTextItem::mouseDoubleClickEvent(event);
//emit itemEdit(toHtml());
}
//! [5]
//限制图元拖动范围
void PicTextItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
{
auto newPos = clampItemPos(pos());
this->setPos(qCeil(newPos.x()),qCeil(newPos.y()));
scene()->update();
QGraphicsTextItem::mouseReleaseEvent(event);
}
void PicTextItem::keyPressEvent(QKeyEvent *event)
{
foreach (QGraphicsItem *item, scene()->selectedItems()) {
QPointF newPos = item->pos();
switch(event->key()) {
case Qt::Key_Left:
newPos += QPointF(-1.0, 0.0);
break;
case Qt::Key_Right:
newPos += QPointF(1.0, 0.0);
break;
case Qt::Key_Up:
newPos += QPointF(0.0, -1.0);
break;
case Qt::Key_Down:
newPos += QPointF(0.0, 1.0);
break;
default:
break;
}
newPos = clampItemPos(newPos);
setPos(qCeil(newPos.x()),qCeil(newPos.y()));
}
if(!scene()->selectedItems().empty())
{
scene()->update();
}
QGraphicsTextItem::keyPressEvent(event);
}
QImage PicTextItem::emptyImage()
{
QImage img(10, 10, QImage::Format_ARGB32);
img.fill(Qt::white);
return img;
}
QImage PicTextItem::itemImage()
{
return m_untransImage;
}
void PicTextItem::setCustomAttrs(const QXmlStreamAttributes &attrs)
{
auto sourceVar = attrs.value("source").toString();
PicTextItem::setSource(sourceVar);
}
void PicTextItem::saveCustomAttrs(QXmlStreamAttributes &attrs)
{
attrs.append("source", PicTextItem::source().toString());
}
void PicTextItem::colorReversalChanged()
{
setSource(source());
}
void PicTextItem::letterSpaceChanged()
{
setSource(source());
}
QImage PicTextItem::strToImage(const QString &str)
{
if(str.isEmpty())
return QImage();
QPainter painter;
QFontMetrics fm(font());
QImage img(fm.horizontalAdvance(str), fm.height(), QImage::Format_ARGB32);
QRgb txtColor = colorReversal() ? 0xffffffff : 0xff000000;
QRgb bgColor = colorReversal() ? 0xff000000 : 0x00000000;
img.fill(bgColor);
painter.begin(&img);
painter.setFont(font());
painter.setPen(txtColor);
painter.drawText(img.rect(), str);
painter.end();
return clipImage(img, bgColor);
}
/**
* @brief 限制item的位置,以保证整个item都在scene以内
* @param p 要设置的item的新位置
* @return 被clamp之后的新位置
*/
QPointF PicTextItem::clampItemPos(const QPointF &p)
{
return QPointF (std::min(qreal(scene()->width() - boundingRect().width()), std::max(0.0, p.x())),
std::min(qreal(scene()->height() - boundingRect().height()), std::max(0.0, p.y())));
}
TextItemModel TextItemModel::fromItem(PicTextItem *item)
{
TextItemModel vm;
if (item) {
vm.sourceType = item->sourceType();
vm.direction = item->direction();
vm.boldMultiple = item->boldMultiple();
vm.letterSpace = item->letterSpace();
vm.colorReversal = item->colorReversal();
}
return vm;
}
QString TextItemModel::toString(const TextItemModel &model)
{
return QString("type: %1, letterSpace: %2, dir: %3, bold: %4, coloReversal: %5")
.arg(model.sourceType).arg(model.letterSpace).arg(model.direction).arg(model.boldMultiple).arg(model.colorReversal);
}