| |
| |
| |
| |
| |
| |
| |
| |
| |
| Iwa_TextFx::Iwa_TextFx() |
| : m_text(L"Lorem ipsum") |
| , m_hAlign(new TIntEnumParam(Qt::AlignLeft, "Left")) |
| , m_center(TPointD(0.0, 0.0)) |
| , m_width(200.0) |
| , m_height(60.0) |
| , m_font(new TFontParam()) |
| , m_textColor(TPixel32::Black) |
| , m_boxColor(TPixel32::Transparent) |
| , m_showBorder(false) { |
| m_targetType->setValue(INPUT_TEXT); |
| |
| m_hAlign->addItem(Qt::AlignRight, "Right"); |
| m_hAlign->addItem(Qt::AlignHCenter, "Center"); |
| m_hAlign->addItem(Qt::AlignJustify, "Justify"); |
| |
| m_text->setMultiLineEnabled(true); |
| |
| m_center->getX()->setMeasureName("fxLength"); |
| m_center->getY()->setMeasureName("fxLength"); |
| m_width->setMeasureName("fxLength"); |
| m_height->setMeasureName("fxLength"); |
| |
| m_width->setValueRange(1.0, (std::numeric_limits<double>::max)()); |
| m_height->setValueRange(1.0, (std::numeric_limits<double>::max)()); |
| |
| |
| QFont font; |
| font.fromString(QString::fromStdWString(m_font->getValue())); |
| font.setPixelSize(30); |
| m_font->setValue(font.toString().toStdWString(), true); |
| |
| bindParam(this, "targetType", m_targetType); |
| bindParam(this, "columnIndex", m_columnIndex); |
| bindParam(this, "text", m_text); |
| bindParam(this, "hAlign", m_hAlign); |
| bindParam(this, "center", m_center); |
| bindParam(this, "width", m_width); |
| bindParam(this, "height", m_height); |
| bindParam(this, "font", m_font); |
| bindParam(this, "textColor", m_textColor); |
| bindParam(this, "boxColor", m_boxColor); |
| bindParam(this, "showBorder", m_showBorder); |
| } |
| |
| |
| |
| bool Iwa_TextFx::doGetBBox(double frame, TRectD &bBox, |
| const TRenderSettings &ri) { |
| bBox = TConsts::infiniteRectD; |
| return true; |
| } |
| |
| |
| |
| void Iwa_TextFx::doCompute(TTile &tile, double frame, |
| const TRenderSettings &ri) { |
| QString text; |
| if (m_targetType->getValue() == INPUT_TEXT) |
| text = QString::fromStdWString(m_text->getValue()); |
| else |
| text = m_noteLevelStr; |
| if (text.isEmpty()) return; |
| |
| QFont font; |
| font.fromString(QString::fromStdWString(m_font->getValue())); |
| |
| double fac = sqrt(fabs(ri.m_affine.det())); |
| int size = (int)(fac * fabs(font.pixelSize())); |
| |
| TPoint center = convert( |
| fac * m_center->getValue(frame) - |
| (tile.m_pos + tile.getRaster()->getCenterD()) + |
| TPointD(ri.m_cameraBox.getLx() / 2.0, ri.m_cameraBox.getLy() / 2.0)); |
| |
| QRect textBoxRect(0, 0, fac * m_width->getValue(frame), |
| fac * m_height->getValue(frame)); |
| textBoxRect.moveCenter(QPoint(center.x, center.y)); |
| |
| Qt::AlignmentFlag hAlignFlag = (Qt::AlignmentFlag)m_hAlign->getValue(); |
| |
| |
| |
| |
| int flag = hAlignFlag | Qt::AlignVCenter | Qt::TextWordWrap; |
| |
| QFont tmpFont(font); |
| tmpFont.setPixelSize(100); |
| QFontMetricsF tmpFm(tmpFont); |
| QRectF bbox = tmpFm.boundingRect(textBoxRect, flag, text); |
| |
| float ratio = std::min(textBoxRect.width() / bbox.width(), |
| textBoxRect.height() / bbox.height()); |
| |
| |
| int fontSize = (int)(100.0f * ratio); |
| tmpFont.setPixelSize(fontSize); |
| tmpFm = QFontMetricsF(tmpFont); |
| bbox = tmpFm.boundingRect(textBoxRect, flag, text); |
| bool isInRect; |
| if (textBoxRect.width() >= bbox.width() && |
| textBoxRect.height() >= bbox.height()) |
| isInRect = true; |
| else |
| isInRect = false; |
| while (1) { |
| fontSize += (isInRect) ? 1 : -1; |
| if (fontSize <= 0) |
| return; |
| if (isInRect && fontSize >= size) break; |
| tmpFont.setPixelSize(fontSize); |
| tmpFm = QFontMetricsF(tmpFont); |
| bbox = tmpFm.boundingRect(textBoxRect, flag, text); |
| |
| bool newIsInRect = (textBoxRect.width() >= bbox.width() && |
| textBoxRect.height() >= bbox.height()); |
| if (isInRect != newIsInRect) { |
| if (isInRect) fontSize--; |
| break; |
| } |
| } |
| |
| if (size < fontSize) { |
| fontSize = size; |
| } |
| |
| font.setPixelSize(fontSize); |
| tmpFm = QFontMetricsF(font); |
| bbox = tmpFm.boundingRect(textBoxRect, flag, text); |
| |
| double lineWidth = 0.1 * (double)fontSize; |
| |
| |
| |
| QImage img(bbox.width() + (int)(lineWidth * 4), |
| bbox.height() + (int)(lineWidth * 2), |
| QImage::Format_ARGB32_Premultiplied); |
| img.fill(Qt::transparent); |
| |
| bbox.moveCenter(img.rect().center()); |
| |
| QPainter painter(&img); |
| TPixel32 boxColor = m_boxColor->getValue(frame); |
| TPixel32 color = m_textColor->getValue(frame); |
| |
| if (boxColor.m > 0) |
| painter.fillRect(img.rect(), QColor((int)boxColor.r, (int)boxColor.g, |
| (int)boxColor.b, (int)boxColor.m)); |
| |
| QPen pen(QColor((int)color.r, (int)color.g, (int)color.b, (int)color.m)); |
| painter.setPen(pen); |
| painter.setFont(font); |
| painter.drawText(bbox, flag, text); |
| |
| if (m_showBorder->getValue()) { |
| pen.setWidthF(lineWidth); |
| pen.setJoinStyle(Qt::MiterJoin); |
| painter.setPen(pen); |
| painter.drawRect(img.rect().adjusted(lineWidth / 2, lineWidth / 2, |
| -lineWidth / 2, -lineWidth / 2)); |
| } |
| |
| TPoint imgRootPos = center - TPoint(img.width() / 2, img.height() / 2); |
| |
| tile.getRaster()->clear(); |
| TRaster32P ras32 = (TRaster32P)tile.getRaster(); |
| TRaster64P ras64 = (TRaster64P)tile.getRaster(); |
| if (ras32) |
| putTextImage<TRaster32P, TPixel32>(ras32, imgRootPos, img); |
| else if (ras64) |
| putTextImage<TRaster64P, TPixel64>(ras64, imgRootPos, img); |
| else |
| throw TException("Iwa_TextFx: unsupported Pixel Type"); |
| } |
| |
| |
| |
| void Iwa_TextFx::getParamUIs(TParamUIConcept *&concepts, int &length) { |
| concepts = new TParamUIConcept[length = 2]; |
| |
| concepts[0].m_type = TParamUIConcept::POINT; |
| concepts[0].m_label = "Center"; |
| concepts[0].m_params.push_back(m_center); |
| |
| concepts[1].m_type = TParamUIConcept::RECT; |
| concepts[1].m_params.push_back(m_width); |
| concepts[1].m_params.push_back(m_height); |
| concepts[1].m_params.push_back(m_center); |
| } |
| |
| |
| |
| std::string Iwa_TextFx::getAlias(double frame, |
| const TRenderSettings &info) const { |
| std::string alias = getFxType(); |
| alias += "["; |
| |
| std::string paramalias(""); |
| for (int i = 0; i < getParams()->getParamCount(); ++i) { |
| TParam *param = getParams()->getParam(i); |
| paramalias += param->getName() + "=" + param->getValueAlias(frame, 3); |
| } |
| |
| if (m_targetType->getValue() == INPUT_TEXT) |
| return alias + "," + std::to_string(getIdentifier()) + paramalias + "]"; |
| else |
| return alias + std::to_string(frame) + "," + |
| std::to_string(getIdentifier()) + paramalias + "]"; |
| } |
| |
| |
| |
| template <typename RASTER, typename PIXEL> |
| void Iwa_TextFx::putTextImage(const RASTER srcRas, TPoint &pos, QImage &img) { |
| for (int j = 0; j < img.height(); j++) { |
| int rasY = pos.y + j; |
| if (rasY < 0) continue; |
| if (srcRas->getLy() <= rasY) break; |
| |
| PIXEL *pix = srcRas->pixels(rasY); |
| QRgb *img_p = (QRgb *)img.scanLine(img.height() - j - 1); |
| for (int i = 0; i < img.width(); i++, img_p++) { |
| int rasX = pos.x + i; |
| if (rasX < 0) continue; |
| if (srcRas->getLx() <= rasX) break; |
| |
| pix[rasX].r = (typename PIXEL::Channel)( |
| qRed(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX); |
| pix[rasX].g = (typename PIXEL::Channel)( |
| qGreen(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX); |
| pix[rasX].b = (typename PIXEL::Channel)( |
| qBlue(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX); |
| pix[rasX].m = (typename PIXEL::Channel)( |
| qAlpha(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX); |
| } |
| } |
| } |
| |
| |
| |
| FX_PLUGIN_IDENTIFIER(Iwa_TextFx, "iwa_TextFx"); |