#include #include "pictextitem.h" #include "picscene.h" #include #include //#include "moveinput.h" #include //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()); } 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; } //! [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) { 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()))); }