/*========================================================================= Program: Visualization Toolkit Module: vtkQtStringToImage.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkQtStringToImage.h" #include "vtkQImageToImageSource.h" #include "vtkStdString.h" #include "vtkUnicodeString.h" #include "vtkTextProperty.h" #include "vtkVector.h" #include "vtkImageData.h" #include "vtkObjectFactory.h" // Qt classes #include #include #include #include #include #include #include #include #include #include namespace { struct vtkQtLabelMapEntry { QString Text; QColor Color; QFont Font; }; } // End of anonymous namespace class vtkQtStringToImage::Internals { public: QFont TextPropertyToFont(vtkTextProperty* tprop, int dpi) { QFont fontSpec(tprop->GetFontFamilyAsString()); fontSpec.setBold(tprop->GetBold()); fontSpec.setItalic(tprop->GetItalic()); fontSpec.setPixelSize(static_cast(tprop->GetFontSize() * (dpi / 72.))); return fontSpec; } QColor TextPropertyToColor(double* fc, double opacity) { QColor textColor( static_cast(fc[0]*255), static_cast(fc[1]*255), static_cast(fc[2]*255), static_cast(opacity*255)); return textColor; } }; //----------------------------------------------------------------------------- vtkStandardNewMacro(vtkQtStringToImage); //----------------------------------------------------------------------------- vtkQtStringToImage::vtkQtStringToImage() { this->Implementation = new Internals; this->QImageToImage = vtkSmartPointer::New(); } //----------------------------------------------------------------------------- vtkQtStringToImage::~vtkQtStringToImage() { delete this->Implementation; } //----------------------------------------------------------------------------- vtkVector2i vtkQtStringToImage::GetBounds(vtkTextProperty *property, const vtkUnicodeString& string, int dpi) { vtkVector2i recti(0, 0); if (!QApplication::instance()) { vtkErrorMacro("You must initialize a QApplication before using this class."); return recti; } if (!property) { return recti; } QFont fontSpec = this->Implementation->TextPropertyToFont(property, dpi); QString text = QString::fromUtf8(string.utf8_str()); QRectF rect; QPainterPath path; path.addText(0, 0, fontSpec, text); rect = path.boundingRect(); recti.SetX(static_cast(rect.width())); recti.SetY(static_cast(rect.height())); return recti; } //----------------------------------------------------------------------------- vtkVector2i vtkQtStringToImage::GetBounds(vtkTextProperty *property, const vtkStdString& string, int dpi) { vtkVector2i recti(0, 0); if (!QApplication::instance()) { vtkErrorMacro("You must initialize a QApplication before using this class."); return recti; } if (!property) { return recti; } QFont fontSpec = this->Implementation->TextPropertyToFont(property, dpi); QString text(string.c_str()); QRectF rect; QPainterPath path; path.addText(0, 0, fontSpec, text); rect = path.boundingRect(); recti.SetX(static_cast(rect.width())); recti.SetY(static_cast(rect.height())); return recti; } int vtkQtStringToImage::RenderString(vtkTextProperty *property, const vtkUnicodeString& string, int dpi, vtkImageData *data, int textDims[2]) { if (!QApplication::instance()) { vtkErrorMacro("You must initialize a QApplication before using this class."); return 0; } // Get the required size, and initialize a new QImage to draw on. vtkVector2i box = this->GetBounds(property, string, dpi); if (box.GetX() == 0 || box.GetY() == 0) { return 0; } if (textDims) { textDims[0] = box.GetX(); textDims[1] = box.GetY(); } QString text = QString::fromUtf8(string.utf8_str()); QFont fontSpec = this->Implementation->TextPropertyToFont(property, dpi); QFontMetrics fontMetric(fontSpec); // Get properties from text property double rotation = -property->GetOrientation(); QColor textColor = this->Implementation->TextPropertyToColor(property->GetColor(), property->GetOpacity()); int shOff[2]; property->GetShadowOffset(shOff); double pixelPadding = 2; double pixelPaddingX = pixelPadding + shOff[0]; double pixelPaddingY = pixelPadding - shOff[1]; QPainterPath path; path.addText(0, 0, fontSpec, text); QRectF bounds = path.boundingRect(); bounds.setWidth(bounds.width() + pixelPaddingX); bounds.setHeight(bounds.height() + pixelPaddingY); QTransform trans; trans.rotate(rotation); QRectF rotBounds = trans.mapRect(bounds); QImage image(static_cast(ceil(rotBounds.width() + pixelPaddingX)), static_cast(ceil(rotBounds.height() + pixelPaddingY)), QImage::Format_ARGB32_Premultiplied); image.fill(qRgba(0,0,0,0)); QPainter p(&image); p.setRenderHint(QPainter::TextAntialiasing, this->Antialias); p.setRenderHint(QPainter::Antialiasing, this->Antialias); p.translate(-rotBounds.left(), -rotBounds.top()); p.rotate(rotation); if (property->GetShadow()) { p.save(); p.translate(shOff[0], -shOff[1]); double sc[3]; property->GetShadowColor(sc); QColor shadowColor = this->Implementation->TextPropertyToColor(sc, property->GetOpacity()); p.fillPath(path, shadowColor); p.restore(); } p.fillPath(path, textColor); this->QImageToImage->SetQImage(&image); this->QImageToImage->Modified(); this->QImageToImage->Update(); data->DeepCopy( vtkImageData::SafeDownCast(this->QImageToImage->GetOutputDataObject(0))); this->QImageToImage->SetQImage(nullptr); return 1; } int vtkQtStringToImage::RenderString(vtkTextProperty *property, const vtkStdString& string, int dpi, vtkImageData *data, int textDims[2]) { return this->RenderString(property, vtkUnicodeString::from_utf8(string), dpi, data, textDims); } //----------------------------------------------------------------------------- void vtkQtStringToImage::DeepCopy(vtkQtStringToImage *) { } //----------------------------------------------------------------------------- void vtkQtStringToImage::PrintSelf(ostream &os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); }