/*************************************************************************** File : QTeXPaintEngine.cpp Project : QTeXEngine GNU GPL v. 3.0 -------------------------------------------------------------------- Copyright : (C) 2009 by Ion Vasilief Email (use @ for *) : ion_vasilief*yahoo.fr Description : Enables the export of QPainter grafics to .tex files ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2.1 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "QTeXEngine.h" #include #include #include #include QTeXPaintEngine::QTeXPaintEngine(const QString& f, QTeXPaintDevice::Unit u) : QPaintEngine(QPaintEngine::AllFeatures), fname(f), d_pixmap_index(1), d_unit(u) { d_pgf_mode = false; d_open_scope = false; d_gray_scale = false; d_document_mode = false; d_escape_text = true; d_font_size = true; d_clip_path = QPainterPath(); d_current_color = QColor(); d_pattern_color = QColor(); d_horizontal_alignment = Qt::AlignHCenter; } bool QTeXPaintEngine::begin(QPaintDevice* p) { setPaintDevice(p); file = new QFile(fname); if (file->open(QIODevice::WriteOnly)){ QTextStream t(file); t.setCodec("UTF-8"); if (d_document_mode){ t << "\\documentclass{article}\n"; t << "\\usepackage[left=0.2cm,top=0.1cm,right=0.2cm,nohead,nofoot]{geometry}\n"; if (d_pgf_mode){ t << "\\usepackage{pgf}\n"; t << "\\usepgflibrary{patterns}\n"; } else { t << "\\usepackage{tikz}\n"; t << "\\usetikzlibrary{patterns}\n"; } t << "\\usepackage{ulem}\n";//used for striked out fonts (\sout command) t << "\\begin{document}\n"; } QString pictureEnv = "\\begin{tikzpicture}{0"; if (d_pgf_mode) pictureEnv = "\\begin{pgfpicture}{0"; QString u = unit(); t << pictureEnv + u + "}{0" + u + "}{"; t << QString::number(p->width()) + u + "}{"; t << QString::number(p->height()) + u + "}\n"; if (!d_pgf_mode){ QPainterPath path; path.addRect(QRect(0, 0, p->width(), p->height())); t << "\t\\clip" + tikzPath(path); } return true; } delete file; return false; } bool QTeXPaintEngine::end() { QTextStream t(file); t.setCodec("UTF-8"); if (d_open_scope) t << endScope(); if (d_pgf_mode) t << "\\end{pgfpicture}\n"; else t << "\\end{tikzpicture}\n"; if (d_document_mode) t << "\\end{document}\n"; file->close(); return true; } void QTeXPaintEngine::drawPoints ( const QPointF * points, int pointCount ) { if (emptyStringOperation()) return; QMatrix m = painter()->worldMatrix(); double lw = painter()->pen().widthF(); QString s = QString::null; if (addNewPenColor()){ d_current_color = painter()->pen().color(); s = color(d_current_color); } for (int i = 0; i < pointCount; i++){ QPointF p = m.map(points[i]); if (d_pgf_mode){ QString path = pgfPoint(convertPoint(p)); path += pgfPoint(QPointF(lw, lw)) + "\n"; s += "\\pgfrect[fill]" + path; } else { QString path = tikzPoint(convertPoint(p)); path += " rectangle " + tikzPoint(convertPoint(QPointF(p.x() + lw, p.y() + lw))) + ";\n"; s += "\\fill " + path; } } writeToFile(s); } void QTeXPaintEngine::drawLines ( const QLineF * lines, int lineCount ) { if (painter()->pen().style() == Qt::NoPen) return; QString s; for (int i = 0; i < lineCount; i++){ QPainterPath path(lines[i].p1()); path.lineTo(lines[i].p2()); s += drawShape(Line, this->path(path)); } writeToFile(s); } void QTeXPaintEngine::drawPolygon ( const QPointF * points, int pointCount, PolygonDrawMode mode ) { if (emptyStringOperation()) return; QVector pts; for (int i = 0; i < pointCount; i++) pts << points[i]; QPainterPath path; path.addPolygon(QPolygonF(pts)); if (mode != QPaintEngine::PolylineMode) path.closeSubpath (); QString s;; if (mode != QPaintEngine::PolylineMode){ path.closeSubpath (); s += drawShape(Polygon, this->path(path)); } else s += drawShape(Polyline, this->path(path)); writeToFile(s); } void QTeXPaintEngine::drawTextItem ( const QPointF & p, const QTextItem & textItem ) { QString s = QString::null; if (addNewPenColor()){ s = color(painter()->pen().color()); d_current_color = painter()->pen().color(); } QMatrix m = painter()->worldMatrix(); s += "\\pgftext["; QPointF origin = p; switch(d_horizontal_alignment){ case Qt::AlignLeft: s += "left"; break; case Qt::AlignHCenter: case Qt::AlignJustify: origin = QPointF(p.x() + 0.5*textItem.width(), p.y()); s += "center"; break; case Qt::AlignRight: origin = QPointF(p.x() + textItem.width(), p.y()); s += "right"; break; default: break; } s += ", base, at="; s += pgfPoint(convertPoint(m.map(origin))); if (painter()->transform().isRotating ()){ double angle = 180.0/M_PI*acos(m.m11()); if (m.m11() != 0.0 && m.m12() > 0) angle = -angle; s += ",rotate=" + QString::number(angle); } s += "]{"; QFont f = textItem.font(); if (d_font_size) s += "\\fontsize{" + QString::number(int(f.pointSizeF())) + "}{0}\\selectfont{"; if (f.underline()) s += "\\underline{"; if (f.italic()) s += "\\textit{"; if (f.bold()) s += "\\textbf{"; if (f.strikeOut()) s += "\\sout{"; QString text = textItem.text(); text.remove(QRegExp("~\\")); if (d_escape_text){ text.replace("$", "\\$"); text.replace("_", "\\_"); text.replace("{", "\\{"); text.replace("}", "\\}"); text.replace("^", "\\^"); text.replace("&", "\\&"); text.replace("%", "\\%"); text.replace("#", "\\#"); } s += text; if (d_font_size) s += "}"; if (f.italic()) s += "}"; if (f.bold()) s += "}"; if (f.underline()) s += "}"; if (f.strikeOut()) s += "}"; s += "}\n"; writeToFile(s); } void QTeXPaintEngine::drawRects ( const QRectF * rects, int rectCount ) { if (emptyStringOperation()) return; QString s; for (int i = 0; i < rectCount; i++){ QPainterPath path; path.addPolygon(QPolygonF(rects[i])); s += drawShape(Path, this->path(path)); } writeToFile(s); } void QTeXPaintEngine::drawEllipse ( const QRectF & rect ) { if (emptyStringOperation()) return; QPointF p = painter()->worldMatrix().map(rect.bottomLeft()); QString path; if (d_pgf_mode){ path = pgfPoint(convertPoint(QPointF(p.x() + 0.5*rect.width(), p.y() - 0.5*rect.height()))); path += pgfPoint(QPointF(0, 0.5*rect.height()*resFactorY())); path += pgfPoint(QPointF(0.5*rect.width()*resFactorX(), 0)) + "\n"; } else { path = tikzPoint(convertPoint(QPointF(p.x() + 0.5*rect.width(), p.y() - 0.5*rect.height()))); path += " ellipse ("; QString u = unit(); path += QString::number(0.5*rect.width()*resFactorX()) + u + " and "; path += QString::number(0.5*rect.height()*resFactorY()) + u + ");\n"; } writeToFile(drawShape(Ellipse, path)); } void QTeXPaintEngine::drawPath ( const QPainterPath & path ) { if (emptyStringOperation()) return; writeToFile(drawShape(Path, this->path(path))); } QString QTeXPaintEngine::drawPgfShape(Shape shape, const QString & path) { if (path.isEmpty()) return QString::null; QString stroke_command = path + "\\pgfstroke\n"; QString fill_command = path + "\\pgffill\n"; switch(shape){ case Line: case Polygon: case Polyline: case Path: case Points: break; case Rect: stroke_command = "\\pgfrect[stroke]" + path; fill_command = "\\pgfrect[fill]" + path; break; case Ellipse: stroke_command = "\\pgfellipse[stroke]" + path; fill_command = "\\pgfellipse[fill]" + path; break; } QString s = QString::null; if (shape != Line && shape != Polyline && painter()->brush().style() != Qt::NoBrush){ // fill the background s += pgfBrush(painter()->brush()); s += fill_command; } if (painter()->pen().style() != Qt::NoPen){// draw the contour s += pgfPen(painter()->pen()); s += stroke_command; } return s; } QString QTeXPaintEngine::drawShape(Shape shape, const QString & path) { if (d_pgf_mode) return drawPgfShape(shape, path); return drawTikzShape(shape, path); } QString QTeXPaintEngine::drawTikzShape(Shape shape, const QString & path) { QString s = QString::null; if (path.isEmpty()) return s; if (shape != Line && shape != Polyline && painter()->brush().style() != Qt::NoBrush) // fill the background s += tikzBrush(painter()->brush()) + path; if (painter()->pen().style() != Qt::NoPen)// draw the contour s += tikzPen(painter()->pen()) + path; return s; } void QTeXPaintEngine::drawImage(const QRectF & r, const QImage & image, const QRectF & sr, Qt::ImageConversionFlags flags) { drawPixmap(QPixmap::fromImage(image, flags).copy(sr.toAlignedRect()), r); } void QTeXPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) { drawPixmap(pm.copy(sr.toAlignedRect()), r); } void QTeXPaintEngine::drawPixmap(const QPixmap &pix, const QRectF &r) { QFileInfo fi(*file); QString base = fi.baseName() + "-images-"; base += QDateTime::currentDateTime().toString("ddMMyy-hhmmss"); if (!fi.dir().exists(base)){ if (!fi.dir().mkdir(base)) return; } QString name = fi.dir().absolutePath(); name += "/" + base + "/image" + QString::number(d_pixmap_index); name = QDir::cleanPath(name); if (!pix.save(name + ".png", "PNG")) return; d_pixmap_index++; QTextStream t(file); t.setCodec("UTF-8"); t << "\\pgfputat"; t << pgfPoint(convertPoint(painter()->worldMatrix().map(r.bottomLeft()))); t << "{\\pgfimage[interpolate=false,width="; QString u = unit(); t << QString::number(r.width()*resFactorX()) + u + ",height="; t << QString::number(r.height()*resFactorY()) + u + "]{"; t << name; t << "}}\n"; } QString QTeXPaintEngine::clipPath() { if (painter()->hasClipping()){ QPainterPath path = painter()->clipPath().simplified(); if (path.elementCount() > 1000)//latex has a limited main memory size return QString::null; if (d_pgf_mode) return pgfPath(path) + "\\pgfclip\n"; else return "\\clip" + tikzPath(path); } return QString::null; } QString QTeXPaintEngine::defineColor(const QColor& c, const QString& name) { QString col = "\\definecolor{" + name + "}{"; if (d_gray_scale){ col += "gray}{"; double gray = qGray(c.rgb())/255.0; col += QString::number(gray) + "}\n"; } else { col += "rgb}{"; col += QString::number(c.redF()) + ","; col += QString::number(c.greenF()) + ","; col += QString::number(c.blueF()) + "}\n"; } return col; } QString QTeXPaintEngine::tikzBrush(const QBrush& brush) { QString options = QString::null; if (addNewPatternColor()){ options = defineColor(brush.color(), "c"); d_pattern_color = brush.color(); } options += "\\fill [pattern color=c, pattern="; switch(brush.style()){ case Qt::NoBrush: return QString::null; break; case Qt::SolidPattern: { QString s = QString::null; if (addNewBrushColor()){ d_current_color = brush.color(); s = color(brush.color()); } s += "\\fill"; double alpha = painter()->brush().color().alphaF(); if(alpha > 0.0 && alpha < 1.0) s += "[opacity=" + QString::number(alpha) + "]"; return s; } break; case Qt::Dense1Pattern: case Qt::Dense2Pattern: case Qt::Dense3Pattern: case Qt::Dense4Pattern: options += "crosshatch dots"; break; case Qt::Dense5Pattern: case Qt::Dense6Pattern: case Qt::Dense7Pattern: options += "dots"; break; case Qt::HorPattern: options += "horizontal lines"; break; case Qt::VerPattern: options += "vertical lines"; break; case Qt::CrossPattern: options += "grid"; break; case Qt::BDiagPattern: options += "north east lines"; break; case Qt::FDiagPattern: options += "north west lines"; break; case Qt::DiagCrossPattern: options += "crosshatch"; break; case Qt::LinearGradientPattern: { const QLinearGradient *qtgradient = (const QLinearGradient *)brush.gradient(); QGradientStops stops = qtgradient->stops(); QString lc = defineColor(stops.first().second, "lc"); QString rc = defineColor(stops.last().second, "rc"); QMatrix m = painter()->worldMatrix(); QPointF sp = m.map(qtgradient->start()); QPointF ep = m.map(qtgradient->finalStop()); options = lc + rc + "\\fill ["; options += "left color=lc, "; options += "right color=rc, "; options += "shading angle=" + QString::number(-QLineF(sp, ep).angle()); } break; case Qt::RadialGradientPattern: { const QRadialGradient *qtgradient = (const QRadialGradient *)brush.gradient(); QGradientStops stops = qtgradient->stops(); QString colors; int count = stops.count(); colors += defineColor(stops[0].second, "c1"); colors += defineColor(stops[count - 1].second, "c2"); /*for (int i = 0; i < count; i++){ QGradientStop stop = stops[i]; colors += defineColor(stop.second, "c" + QString::number(i + 1)); }*/ options = colors + "\\fill ["; options += "inner color=c1, "; options += "outer color=c2, "; options += "shading=radial"; qWarning("QTeXEngine: Uncentered Qt::RadialGradientPattern with more than two colors not supported."); } break; case Qt::ConicalGradientPattern: { qWarning("QTeXEngine: Qt::ConicalGradientPattern is not supported."); return QString::null; } break; default: break; } return options + "]"; } QString QTeXPaintEngine::pgfBrush(const QBrush& brush) { QString s = QString::null; QColor c = brush.color(); QString col = defineColor(c, "c"); QString command = "\\pgfsetfillpattern{"; switch(brush.style()){ case Qt::NoBrush: break; case Qt::SolidPattern: s += color(c); break; case Qt::Dense1Pattern: case Qt::Dense2Pattern: case Qt::Dense3Pattern: case Qt::Dense4Pattern: s += col + command + "crosshatch dots}{c}\n"; break; case Qt::Dense5Pattern: case Qt::Dense6Pattern: case Qt::Dense7Pattern: s += col + command + "dots}{c}\n"; break; case Qt::HorPattern: s += col + command + "horizontal lines}{c}\n"; break; case Qt::VerPattern: s += col + command + "vertical lines}{c}\n"; break; case Qt::CrossPattern: s += col + command + "grid}{c}\n"; break; case Qt::BDiagPattern: s += col + command + "north east lines}{c}\n"; break; case Qt::FDiagPattern: s += col + command + "north west lines}{c}\n"; break; case Qt::DiagCrossPattern: s += col + command + "crosshatch}{c}\n"; break; default: break; } return s; } QString QTeXPaintEngine::path(const QPainterPath & path) { if (path.isEmpty ()) return QString::null; if (d_pgf_mode) return pgfPath(path); return tikzPath(path); } QString QTeXPaintEngine::pgfPath(const QPainterPath & path) { QString s = QString::null; int points = path.elementCount(); QMatrix m = painter()->worldMatrix(); int curvePoints = 0; for (int i = 0; i < points; i++){ QPainterPath::Element el = path.elementAt(i); QPointF p = m.map(QPointF(el.x, el.y)); switch(el.type){ case QPainterPath::MoveToElement: s += "\\pgfmoveto" + pgfPoint(convertPoint(p)) + "\n"; break; case QPainterPath::LineToElement: s += "\\pgflineto" + pgfPoint(convertPoint(p)) + "\n"; break; case QPainterPath::CurveToElement: s += "\\pgfcurveto" + pgfPoint(convertPoint(p)); curvePoints = 0; break; case QPainterPath::CurveToDataElement: s += pgfPoint(convertPoint(p)); curvePoints++; if (curvePoints == 2) s += "\n"; break; } } return s; } QString QTeXPaintEngine::tikzPath(const QPainterPath & path) { QString s = QString::null; if (path.isEmpty()) return s; int points = path.elementCount(); QMatrix m = painter()->worldMatrix(); int curvePoints = 0; for (int i = 0; i < points; i++){ QPainterPath::Element el = path.elementAt(i); QPointF p = m.map(QPointF(el.x, el.y)); switch(el.type){ case QPainterPath::MoveToElement: s += tikzPoint(convertPoint(p)); break; case QPainterPath::LineToElement: s += " -- " + tikzPoint(convertPoint(p)); break; case QPainterPath::CurveToElement: s += " .. controls " + tikzPoint(convertPoint(p)); curvePoints = 0; break; case QPainterPath::CurveToDataElement: curvePoints++; if (curvePoints == 1) s += " and " + tikzPoint(convertPoint(p)); else if (curvePoints == 2) s += " .. " + tikzPoint(convertPoint(p)); break; } } return s + ";\n"; } QPointF QTeXPaintEngine::convertPoint( const QPointF& p) { return QPointF(resFactorX()*p.x(), paintDevice()->height() - resFactorY()*p.y()); } double QTeXPaintEngine::unitFactor() { double factor = 1.0; switch (d_unit){ case QTeXPaintDevice::pt: factor = 72.27; break; case QTeXPaintDevice::bp: factor = 72; break; case QTeXPaintDevice::mm: factor = 25.4; break; case QTeXPaintDevice::cm: factor = 2.54; break; case QTeXPaintDevice::in: case QTeXPaintDevice::ex: case QTeXPaintDevice::em: break; } return factor; } double QTeXPaintEngine::resFactorX() { return unitFactor()/(double)paintDevice()->logicalDpiX(); } double QTeXPaintEngine::resFactorY() { return unitFactor()/(double)paintDevice()->logicalDpiY(); } QString QTeXPaintEngine::pgfPoint( const QPointF& p) { QString u = unit(); QString s = "{\\pgfpoint{" + QString::number(p.x()); s += u + "}{" + QString::number(p.y()) + u + "}}"; return s; } QString QTeXPaintEngine::tikzPoint(const QPointF & p) { QString u = unit(); QString s = "(" + QString::number(p.x()); s += u + "," + QString::number(p.y()) + u + ")"; return s; } QString QTeXPaintEngine::color( const QColor& col) { QString s = "\\color["; if (d_gray_scale){ s += "gray]{"; double gray = qGray(col.rgb())/255.0; s += QString::number(gray) + "}\n"; } else { s += "rgb]{"; s += QString::number(col.redF()) + ","; s += QString::number(col.greenF()) + ","; s += QString::number(col.blueF()) + "}\n"; } return s; } QString QTeXPaintEngine::pgfPen(const QPen& pen) { QString s = QString::null; if (pen.style() == Qt::NoPen) return s; s += color(pen.color()); s += "\\pgfsetlinewidth{" + QString::number(painter()->pen().widthF()) + "pt}\n"; QString aux = "\\pgfsetdash{"; QString term = "}{0cm}\n"; double space_length = 0.08*pen.widthF(); double dot_length = 0.3*space_length; double dash_length = 1.5*space_length; QString dash = "{" + QString::number(dash_length) + "cm}"; QString dot = "{" + QString::number(dot_length) + "cm}"; QString space = "{" + QString::number(space_length) + "cm}"; switch (pen.style()){ case Qt::SolidLine: break; case Qt::DashLine: s += aux + dash + space + term; break; case Qt::DotLine: s += aux + dot + space + term; break; case Qt::DashDotLine: s += aux + dash + space + dot + space + term; break; case Qt::DashDotDotLine: s += aux + dash + space + dot + space + dot + space + term; break; case Qt::CustomDashLine: { s += aux; QVector pattern = pen.dashPattern(); int count = pattern.count(); QString u = unit(); for (int i = 0; i < count; i++) s += "{" + QString::number(pattern[i]) + u + "}"; s += term; break; } default: break; } switch (pen.joinStyle()){ case Qt::MiterJoin: s += "\\pgfsetmiterjoin\n"; //s += "\\pgfsetmiterlimit{" + QString::number(pen.miterLimit()) + "pt}\n"; break; case Qt::BevelJoin: s += "\\pgfsetbeveljoin\n"; break; case Qt::RoundJoin: s += "\\pgfsetroundjoin\n"; break; case Qt::SvgMiterJoin: s += "\\pgfsetmiterjoin\n"; break; default: break; } switch (pen.capStyle()){ case Qt::FlatCap: s += "\\pgfsetrectcap\n"; break; case Qt::SquareCap: s += "\\pgfsetrectcap\n"; break; case Qt::RoundCap: s += "\\pgfsetroundcap\n"; break; default: break; } return s; } QString QTeXPaintEngine::tikzPen(const QPen& pen) { if (pen.style() == Qt::NoPen) return QString::null; QString col = QString::null; if (addNewPenColor()){ col = color(pen.color()); d_current_color = pen.color(); } QString options = "[line width="; options += QString::number(painter()->pen().widthF()) + "pt, "; double space_length = 0.08*pen.widthF(); double dot_length = 0.3*space_length; double dash_length = 1.5*space_length; QString dash = "on " + QString::number(dash_length) + "cm"; QString dot = "on " + QString::number(dot_length) + "cm"; QString space = " off " + QString::number(space_length) + "cm"; QString aux = "dash pattern="; QString term = ", dash phase=0pt, "; switch (pen.style()){ case Qt::SolidLine: break; case Qt::DashLine: options += aux + dash + space + term; break; case Qt::DotLine: options += aux + dot + space + term; break; case Qt::DashDotLine: options += aux + dash + space + dot + space + term; break; case Qt::DashDotDotLine: options += aux + dash + space + dot + space + dot + space + term; break; case Qt::CustomDashLine: { options += aux; QVector pattern = pen.dashPattern(); int count = pattern.count(); QString u = unit(); for (int i = 0; i < count; i++){ QString s = "on "; if (i%2) s = " off "; options += s + QString::number(pattern[i]) + u; } options += term; break; } default: break; } options += "line join="; switch (pen.joinStyle()){ case Qt::MiterJoin: options += "miter, "; break; case Qt::BevelJoin: options += "bevel, "; break; case Qt::RoundJoin: options += "round, "; break; case Qt::SvgMiterJoin: options += "miter, "; break; default: break; } options += "line cap="; switch (pen.capStyle()){ case Qt::FlatCap: options += "rect]"; break; case Qt::SquareCap: options += "rect]"; break; case Qt::RoundCap: options += "round]"; break; default: break; } return col + "\\draw" + options; } QString QTeXPaintEngine::indentString(const QString& s) { QStringList lst = s.split("\n", QString::SkipEmptyParts); for(int i = 0; i < lst.count(); i++) lst[i].prepend("\t"); return lst.join("\n") + "\n"; } QString QTeXPaintEngine::beginScope() { QString s = "\\begin{scope}\n"; if (d_pgf_mode) s = "\\begin{pgfscope}\n"; if (painter()->hasClipping()){ QString clip = clipPath(); if (!clip.isEmpty()) s += indentString(clip); } d_pattern_color = QColor(); d_current_color = QColor(); return s; } QString QTeXPaintEngine::endScope() { if (d_pgf_mode) return "\\end{pgfscope}\n"; return "\\end{scope}\n"; } void QTeXPaintEngine::writeToFile(const QString& s) { QTextStream t(file); t.setCodec("UTF-8"); if (d_pgf_mode){ t << beginScope(); t << indentString(s); t << endScope(); return; } QString scope; if (d_open_scope) scope = endScope(); if (changedClipping()){ scope += beginScope(); scope += indentString(s); t << scope; d_open_scope = true; if (painter()->hasClipping()) d_clip_path = painter()->clipPath(); else d_clip_path = QPainterPath(); } else t << indentString(s); } bool QTeXPaintEngine::emptyStringOperation() { if ((painter()->brush().style() == Qt::NoBrush || (painter()->brush().color().alpha() == 0)) && painter()->pen().style() == Qt::NoPen) return true; return false; } bool QTeXPaintEngine::changedClipping() { QPainterPath clipPath = QPainterPath(); if (painter()->hasClipping()){ if (painter()->clipPath().elementCount() > 1000) return false; clipPath = painter()->clipPath(); } if (clipPath != d_clip_path) return true; return false; } bool QTeXPaintEngine::addNewPatternColor() { Qt::BrushStyle style = painter()->brush().style(); if (style <= Qt::SolidPattern || style >= Qt::LinearGradientPattern) return false; if (!d_pattern_color.isValid() || d_pattern_color != painter()->brush().color()) return true; return false; } bool QTeXPaintEngine::addNewBrushColor() { if (!d_current_color.isValid() || changedClipping() || d_current_color.name() != painter()->brush().color().name()) return true; return false; } bool QTeXPaintEngine::addNewPenColor() { if (!d_current_color.isValid() || (changedClipping() && painter()->brush().style() == Qt::NoBrush) || d_current_color.name() != painter()->pen().color().name()) return true; return false; } QString QTeXPaintEngine::unit() { switch (d_unit){ case QTeXPaintDevice::pt: return "pt"; break; case QTeXPaintDevice::bp: return "bp"; break; case QTeXPaintDevice::mm: return "mm"; break; case QTeXPaintDevice::cm: return "cm"; break; case QTeXPaintDevice::in: return "in"; break; case QTeXPaintDevice::ex: return "ex"; break; case QTeXPaintDevice::em: return "em"; break; } return "pt"; }