|
shun-iwasawa |
5b2332 |
#include "iwa_textfx.h"
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
#include "tparamuiconcept.h"
|
|
shun-iwasawa |
5b2332 |
#include <qfontmetrics></qfontmetrics>
|
|
shun-iwasawa |
5b2332 |
#include <qimage></qimage>
|
|
shun-iwasawa |
5b2332 |
#include <qpainter></qpainter>
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
Iwa_TextFx::Iwa_TextFx()
|
|
shun-iwasawa |
5b2332 |
: m_text(L"Lorem ipsum")
|
|
shun-iwasawa |
5b2332 |
, m_hAlign(new TIntEnumParam(Qt::AlignLeft, "Left"))
|
|
shun-iwasawa |
5b2332 |
, m_center(TPointD(0.0, 0.0))
|
|
shun-iwasawa |
5b2332 |
, m_width(200.0)
|
|
shun-iwasawa |
5b2332 |
, m_height(60.0)
|
|
shun-iwasawa |
5b2332 |
, m_font(new TFontParam())
|
|
shun-iwasawa |
5b2332 |
, m_textColor(TPixel32::Black)
|
|
shun-iwasawa |
5b2332 |
, m_boxColor(TPixel32::Transparent)
|
|
shun-iwasawa |
5b2332 |
, m_showBorder(false) {
|
|
shun-iwasawa |
5b2332 |
m_targetType->setValue(INPUT_TEXT);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
m_hAlign->addItem(Qt::AlignRight, "Right");
|
|
shun-iwasawa |
5b2332 |
m_hAlign->addItem(Qt::AlignHCenter, "Center");
|
|
shun-iwasawa |
5b2332 |
m_hAlign->addItem(Qt::AlignJustify, "Justify");
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
m_text->setMultiLineEnabled(true);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
m_center->getX()->setMeasureName("fxLength");
|
|
shun-iwasawa |
5b2332 |
m_center->getY()->setMeasureName("fxLength");
|
|
shun-iwasawa |
5b2332 |
m_width->setMeasureName("fxLength");
|
|
shun-iwasawa |
5b2332 |
m_height->setMeasureName("fxLength");
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
m_width->setValueRange(1.0, (std::numeric_limits<double>::max)());</double>
|
|
shun-iwasawa |
5b2332 |
m_height->setValueRange(1.0, (std::numeric_limits<double>::max)());</double>
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
// set the initial font size to 30
|
|
shun-iwasawa |
5b2332 |
QFont font;
|
|
shun-iwasawa |
5b2332 |
font.fromString(QString::fromStdWString(m_font->getValue()));
|
|
shun-iwasawa |
5b2332 |
font.setPixelSize(30);
|
|
shun-iwasawa |
5b2332 |
m_font->setValue(font.toString().toStdWString(), true);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "targetType", m_targetType);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "columnIndex", m_columnIndex);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "text", m_text);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "hAlign", m_hAlign);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "center", m_center);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "width", m_width);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "height", m_height);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "font", m_font);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "textColor", m_textColor);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "boxColor", m_boxColor);
|
|
shun-iwasawa |
5b2332 |
bindParam(this, "showBorder", m_showBorder);
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
bool Iwa_TextFx::doGetBBox(double frame, TRectD &bBox,
|
|
shun-iwasawa |
5b2332 |
const TRenderSettings &ri) {
|
|
shun-iwasawa |
5b2332 |
bBox = TConsts::infiniteRectD;
|
|
shun-iwasawa |
5b2332 |
return true;
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
void Iwa_TextFx::doCompute(TTile &tile, double frame,
|
|
shun-iwasawa |
5b2332 |
const TRenderSettings &ri) {
|
|
shun-iwasawa |
5b2332 |
QString text;
|
|
shun-iwasawa |
5b2332 |
if (m_targetType->getValue() == INPUT_TEXT)
|
|
shun-iwasawa |
5b2332 |
text = QString::fromStdWString(m_text->getValue());
|
|
shun-iwasawa |
5b2332 |
else
|
|
shun-iwasawa |
5b2332 |
text = m_noteLevelStr;
|
|
shun-iwasawa |
5b2332 |
if (text.isEmpty()) return;
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
QFont font;
|
|
shun-iwasawa |
5b2332 |
font.fromString(QString::fromStdWString(m_font->getValue()));
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
double fac = sqrt(fabs(ri.m_affine.det()));
|
|
shun-iwasawa |
5b2332 |
int size = (int)(fac * fabs(font.pixelSize()));
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
TPoint center = convert(
|
|
shun-iwasawa |
5b2332 |
fac * m_center->getValue(frame) -
|
|
shun-iwasawa |
5b2332 |
(tile.m_pos + tile.getRaster()->getCenterD()) +
|
|
shun-iwasawa |
5b2332 |
TPointD(ri.m_cameraBox.getLx() / 2.0, ri.m_cameraBox.getLy() / 2.0));
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
QRect textBoxRect(0, 0, fac * m_width->getValue(frame),
|
|
shun-iwasawa |
5b2332 |
fac * m_height->getValue(frame));
|
|
shun-iwasawa |
5b2332 |
textBoxRect.moveCenter(QPoint(center.x, center.y));
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
Qt::AlignmentFlag hAlignFlag = (Qt::AlignmentFlag)m_hAlign->getValue();
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
// For simplification, text will always be "wrapped".
|
|
shun-iwasawa |
5b2332 |
// If user would like to make the line with no break, they can just expand the
|
|
shun-iwasawa |
5b2332 |
// boundary or set the smaller font size.
|
|
shun-iwasawa |
5b2332 |
int flag = hAlignFlag | Qt::AlignVCenter | Qt::TextWordWrap;
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
QFont tmpFont(font);
|
|
shun-iwasawa |
5b2332 |
tmpFont.setPixelSize(100);
|
|
shun-iwasawa |
5b2332 |
QFontMetricsF tmpFm(tmpFont);
|
|
shun-iwasawa |
5b2332 |
QRectF bbox = tmpFm.boundingRect(textBoxRect, flag, text);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
float ratio = std::min(textBoxRect.width() / bbox.width(),
|
|
shun-iwasawa |
5b2332 |
textBoxRect.height() / bbox.height());
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
// compute the font size which will just fit the item region
|
|
shun-iwasawa |
5b2332 |
int fontSize = (int)(100.0f * ratio);
|
|
shun-iwasawa |
5b2332 |
tmpFont.setPixelSize(fontSize);
|
|
shun-iwasawa |
5b2332 |
tmpFm = QFontMetricsF(tmpFont);
|
|
shun-iwasawa |
5b2332 |
bbox = tmpFm.boundingRect(textBoxRect, flag, text);
|
|
shun-iwasawa |
5b2332 |
bool isInRect;
|
|
shun-iwasawa |
5b2332 |
if (textBoxRect.width() >= bbox.width() &&
|
|
shun-iwasawa |
5b2332 |
textBoxRect.height() >= bbox.height())
|
|
shun-iwasawa |
5b2332 |
isInRect = true;
|
|
shun-iwasawa |
5b2332 |
else
|
|
shun-iwasawa |
5b2332 |
isInRect = false;
|
|
shun-iwasawa |
5b2332 |
while (1) {
|
|
shun-iwasawa |
5b2332 |
fontSize += (isInRect) ? 1 : -1;
|
|
shun-iwasawa |
5b2332 |
if (fontSize <= 0) // cannot draw
|
|
shun-iwasawa |
5b2332 |
return;
|
|
shun-iwasawa |
5b2332 |
if (isInRect && fontSize >= size) break;
|
|
shun-iwasawa |
5b2332 |
tmpFont.setPixelSize(fontSize);
|
|
shun-iwasawa |
5b2332 |
tmpFm = QFontMetricsF(tmpFont);
|
|
shun-iwasawa |
5b2332 |
bbox = tmpFm.boundingRect(textBoxRect, flag, text);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
bool newIsInRect = (textBoxRect.width() >= bbox.width() &&
|
|
shun-iwasawa |
5b2332 |
textBoxRect.height() >= bbox.height());
|
|
shun-iwasawa |
5b2332 |
if (isInRect != newIsInRect) {
|
|
shun-iwasawa |
5b2332 |
if (isInRect) fontSize--;
|
|
shun-iwasawa |
5b2332 |
break;
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
if (size < fontSize) {
|
|
shun-iwasawa |
5b2332 |
fontSize = size;
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
font.setPixelSize(fontSize);
|
|
shun-iwasawa |
5b2332 |
tmpFm = QFontMetricsF(font);
|
|
shun-iwasawa |
5b2332 |
bbox = tmpFm.boundingRect(textBoxRect, flag, text);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
double lineWidth = 0.1 * (double)fontSize;
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
// Usually the text bounding box has less horizontal margin than vertical.
|
|
shun-iwasawa |
5b2332 |
// So here I added more margin to width.
|
|
shun-iwasawa |
5b2332 |
QImage img(bbox.width() + (int)(lineWidth * 4),
|
|
shun-iwasawa |
5b2332 |
bbox.height() + (int)(lineWidth * 2),
|
|
shun-iwasawa |
5b2332 |
QImage::Format_ARGB32_Premultiplied);
|
|
shun-iwasawa |
5b2332 |
img.fill(Qt::transparent);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
bbox.moveCenter(img.rect().center());
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
QPainter painter(&img);
|
|
shun-iwasawa |
5b2332 |
TPixel32 boxColor = m_boxColor->getValue(frame);
|
|
shun-iwasawa |
5b2332 |
TPixel32 color = m_textColor->getValue(frame);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
if (boxColor.m > 0)
|
|
shun-iwasawa |
5b2332 |
painter.fillRect(img.rect(), QColor((int)boxColor.r, (int)boxColor.g,
|
|
shun-iwasawa |
5b2332 |
(int)boxColor.b, (int)boxColor.m));
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
QPen pen(QColor((int)color.r, (int)color.g, (int)color.b, (int)color.m));
|
|
shun-iwasawa |
5b2332 |
painter.setPen(pen);
|
|
shun-iwasawa |
5b2332 |
painter.setFont(font);
|
|
shun-iwasawa |
5b2332 |
painter.drawText(bbox, flag, text);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
if (m_showBorder->getValue()) {
|
|
shun-iwasawa |
5b2332 |
pen.setWidthF(lineWidth);
|
|
shun-iwasawa |
5b2332 |
pen.setJoinStyle(Qt::MiterJoin);
|
|
shun-iwasawa |
5b2332 |
painter.setPen(pen);
|
|
shun-iwasawa |
5b2332 |
painter.drawRect(img.rect().adjusted(lineWidth / 2, lineWidth / 2,
|
|
shun-iwasawa |
5b2332 |
-lineWidth / 2, -lineWidth / 2));
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
TPoint imgRootPos = center - TPoint(img.width() / 2, img.height() / 2);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
tile.getRaster()->clear();
|
|
shun-iwasawa |
5b2332 |
TRaster32P ras32 = (TRaster32P)tile.getRaster();
|
|
shun-iwasawa |
5b2332 |
TRaster64P ras64 = (TRaster64P)tile.getRaster();
|
|
shun-iwasawa |
5b2332 |
if (ras32)
|
|
shun-iwasawa |
5b2332 |
putTextImage<traster32p, tpixel32="">(ras32, imgRootPos, img);</traster32p,>
|
|
shun-iwasawa |
5b2332 |
else if (ras64)
|
|
shun-iwasawa |
5b2332 |
putTextImage<traster64p, tpixel64="">(ras64, imgRootPos, img);</traster64p,>
|
|
shun-iwasawa |
5b2332 |
else
|
|
shun-iwasawa |
5b2332 |
throw TException("Iwa_TextFx: unsupported Pixel Type");
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
void Iwa_TextFx::getParamUIs(TParamUIConcept *&concepts, int &length) {
|
|
shun-iwasawa |
5b2332 |
concepts = new TParamUIConcept[length = 2];
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
concepts[0].m_type = TParamUIConcept::POINT;
|
|
shun-iwasawa |
5b2332 |
concepts[0].m_label = "Center";
|
|
shun-iwasawa |
5b2332 |
concepts[0].m_params.push_back(m_center);
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
concepts[1].m_type = TParamUIConcept::RECT;
|
|
shun-iwasawa |
5b2332 |
concepts[1].m_params.push_back(m_width);
|
|
shun-iwasawa |
5b2332 |
concepts[1].m_params.push_back(m_height);
|
|
shun-iwasawa |
5b2332 |
concepts[1].m_params.push_back(m_center);
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
std::string Iwa_TextFx::getAlias(double frame,
|
|
shun-iwasawa |
5b2332 |
const TRenderSettings &info) const {
|
|
shun-iwasawa |
5b2332 |
std::string alias = getFxType();
|
|
shun-iwasawa |
5b2332 |
alias += "[";
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
std::string paramalias("");
|
|
shun-iwasawa |
5b2332 |
for (int i = 0; i < getParams()->getParamCount(); ++i) {
|
|
shun-iwasawa |
5b2332 |
TParam *param = getParams()->getParam(i);
|
|
shun-iwasawa |
5b2332 |
paramalias += param->getName() + "=" + param->getValueAlias(frame, 3);
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
if (m_targetType->getValue() == INPUT_TEXT)
|
|
shun-iwasawa |
5b2332 |
return alias + "," + std::to_string(getIdentifier()) + paramalias + "]";
|
|
shun-iwasawa |
5b2332 |
else
|
|
shun-iwasawa |
5b2332 |
return alias + std::to_string(frame) + "," +
|
|
shun-iwasawa |
5b2332 |
std::to_string(getIdentifier()) + paramalias + "]";
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
//------------------------------------------------------------------
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
template <typename pixel="" raster,="" typename=""></typename>
|
|
shun-iwasawa |
5b2332 |
void Iwa_TextFx::putTextImage(const RASTER srcRas, TPoint &pos, QImage &img) {
|
|
shun-iwasawa |
5b2332 |
for (int j = 0; j < img.height(); j++) {
|
|
shun-iwasawa |
5b2332 |
int rasY = pos.y + j;
|
|
shun-iwasawa |
5b2332 |
if (rasY < 0) continue;
|
|
shun-iwasawa |
5b2332 |
if (srcRas->getLy() <= rasY) break;
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
PIXEL *pix = srcRas->pixels(rasY);
|
|
shun-iwasawa |
5b2332 |
QRgb *img_p = (QRgb *)img.scanLine(img.height() - j - 1);
|
|
shun-iwasawa |
5b2332 |
for (int i = 0; i < img.width(); i++, img_p++) {
|
|
shun-iwasawa |
5b2332 |
int rasX = pos.x + i;
|
|
shun-iwasawa |
5b2332 |
if (rasX < 0) continue;
|
|
shun-iwasawa |
5b2332 |
if (srcRas->getLx() <= rasX) break;
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
pix[rasX].r = (typename PIXEL::Channel)(
|
|
shun-iwasawa |
5b2332 |
qRed(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX);
|
|
shun-iwasawa |
5b2332 |
pix[rasX].g = (typename PIXEL::Channel)(
|
|
shun-iwasawa |
5b2332 |
qGreen(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX);
|
|
shun-iwasawa |
5b2332 |
pix[rasX].b = (typename PIXEL::Channel)(
|
|
shun-iwasawa |
5b2332 |
qBlue(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX);
|
|
shun-iwasawa |
5b2332 |
pix[rasX].m = (typename PIXEL::Channel)(
|
|
shun-iwasawa |
5b2332 |
qAlpha(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX);
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
}
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
//==============================================================================
|
|
shun-iwasawa |
5b2332 |
|
|
shun-iwasawa |
5b2332 |
FX_PLUGIN_IDENTIFIER(Iwa_TextFx, "iwa_TextFx");
|