From 84faa2fab566412e469f780b696d456e3fe4bca3 Mon Sep 17 00:00:00 2001 From: manongjohn Date: Thu, 27 Jan 2022 17:06:59 -0500 Subject: [PATCH] Type Tool for Raster levels --- toonz/sources/common/tvrender/tfont_qt.cpp | 43 +++++ toonz/sources/include/tfont.h | 9 + toonz/sources/tnztools/typetool.cpp | 199 ++++++++++++++++++++- 3 files changed, 246 insertions(+), 5 deletions(-) diff --git a/toonz/sources/common/tvrender/tfont_qt.cpp b/toonz/sources/common/tvrender/tfont_qt.cpp index 36d66bda..ce5417d3 100644 --- a/toonz/sources/common/tvrender/tfont_qt.cpp +++ b/toonz/sources/common/tvrender/tfont_qt.cpp @@ -25,6 +25,11 @@ #include "traster.h" #include "tmathutil.h" #include "tvectorimage.h" +#include "trasterimage.h" +#include "toonz/trasterimageutils.h" + +#include "trop.h" + using namespace std; //============================================================================= @@ -235,6 +240,44 @@ TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &unused, int inkId, //----------------------------------------------------------------------------- +TPoint TFont::drawChar(TRaster32P &outImage, TPoint &unused, TPixel32 color, + wchar_t charcode, wchar_t nextCharCode) const { + QImage grayAppImage; + this->drawChar(grayAppImage, unused, charcode, nextCharCode); + + int lx = grayAppImage.width(); + int ly = grayAppImage.height(); + + TRaster32P ras(lx, ly, lx, (TPixelRGBM32 *)grayAppImage.bits(), false); + + outImage = TRaster32P(lx, ly); + outImage->lock(); + + TPixel32 bgColor(0, 0, 0, 0); + int ty = 0; + + for (int gy = ly - 1; gy >= 0; --gy, ++ty) { + uchar *srcPix = grayAppImage.scanLine(gy); + TPixel32 *tarPix = outImage->pixels(ty); + for (int x = 0; x < lx; ++x) { + int m = (int)(*srcPix); + + if (m == 255) + *tarPix = bgColor; + else + *tarPix = color; + + ++srcPix; + ++tarPix; + } + } + outImage->unlock(); + + return getDistance(charcode, nextCharCode); +} + +//----------------------------------------------------------------------------- + TPoint TFont::getDistance(wchar_t firstChar, wchar_t secondChar) const { QFontMetrics metrics(m_pimpl->m_font); return TPoint(metrics.width(QChar(firstChar)), 0); diff --git a/toonz/sources/include/tfont.h b/toonz/sources/include/tfont.h index 290a9da0..c831ab31 100644 --- a/toonz/sources/include/tfont.h +++ b/toonz/sources/include/tfont.h @@ -5,6 +5,7 @@ // Toonz includes #include "trastercm.h" +#include "trasterimage.h" #include "texception.h" // STL includes @@ -49,6 +50,8 @@ public: wchar_t nextCode = 0) const; TPoint drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin, int inkId, wchar_t charcode, wchar_t nextCode = 0) const; + TPoint drawChar(TRaster32P &outImage, TPoint &glyphOrigin, TPixel32 color, + wchar_t charcode, wchar_t nextCode = 0) const; // brief get kerning distance between two characters TPoint getDistance(wchar_t firstChar, wchar_t secondChar) const; @@ -142,6 +145,12 @@ public: nextCode); } + TPoint drawChar(TRaster32P &outImage, TPoint &glyphOrigin, TPixel32 color, + wchar_t charcode, wchar_t nextCode = 0) { + return getCurrentFont()->drawChar(outImage, glyphOrigin, color, charcode, + nextCode); + } + TPoint getDistance(wchar_t firstChar, wchar_t secondChar) { return getCurrentFont()->getDistance(firstChar, secondChar); } diff --git a/toonz/sources/tnztools/typetool.cpp b/toonz/sources/tnztools/typetool.cpp index 490418fc..aac3e889 100644 --- a/toonz/sources/tnztools/typetool.cpp +++ b/toonz/sources/tnztools/typetool.cpp @@ -16,6 +16,7 @@ #include "tvectorimage.h" #include "ttoonzimage.h" #include "toonz/toonzimageutils.h" +#include "toonz/trasterimageutils.h" #include "tools/cursors.h" #include "tundo.h" #include "tvectorgl.h" @@ -230,6 +231,45 @@ public: QString getToolName() override { return QString("Type Tool"); } }; +//--------------------------------------------------------- + +class FullColorRasterUndoTypeTool final : public TFullColorRasterUndo { + TTileSetFullColor *m_afterTiles; + +public: + FullColorRasterUndoTypeTool(TTileSetFullColor *beforeTiles, + TTileSetFullColor *afterTiles, + TXshSimpleLevel *level, const TFrameId &id, + bool createdFrame, bool createdLevel) + : TFullColorRasterUndo(beforeTiles, level, id, createdFrame, createdLevel, + 0) + , m_afterTiles(afterTiles) {} + + ~FullColorRasterUndoTypeTool() { delete m_afterTiles; } + + void redo() const override { + insertLevelAndFrameIfNeeded(); + TRasterImageP image = getImage(); + if (!image) return; + if (m_afterTiles) { + TRasterImageUtils::paste(image, m_afterTiles); + ToolUtils::updateSaveBox(); + } + + TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); + notifyImageChanged(); + } + + int getSize() const override { + if (m_afterTiles) + return TFullColorRasterUndo::getSize() + m_afterTiles->getMemorySize(); + else + return TFullColorRasterUndo::getSize(); + } + + QString getToolName() override { return QString("Type Tool"); } +}; + //--------------------------------------------------------- // // StrokeChar @@ -267,6 +307,17 @@ public: vi->transform(scale); paintChar(vi, m_styleId); m_offset = (scale * TPointD((double)(adv.x), (double)(adv.y))).x; + } else if (TRasterImageP ri = m_char) { + TRaster32P newRaster; + TPoint p; + TPalette *plt = ri->getPalette(); + TColorStyle *colorStyle = plt->getStyle(m_styleId); + TPixel32 color = colorStyle->getMainColor(); + TPoint adv = TFontManager::instance()->drawChar( + (TRaster32P &)newRaster, p, color, (wchar_t)m_key, + (wchar_t)nextCode); + m_offset = (scale * TPointD((double)(adv.x), (double)(adv.y))).x; + m_char = new TRasterImage(newRaster); } else { TRasterCM32P newRasterCM; TPoint p; @@ -381,6 +432,7 @@ public: void addTextToVectorImage(const TVectorImageP ¤tImage, std::vector &images); void addTextToToonzImage(const TToonzImageP ¤tImage); + void addTextToRasterImage(const TRasterImageP ¤tImage); void stopEditing(); void reset() override; @@ -430,7 +482,8 @@ TypeTool::TypeTool() , m_vertical("Vertical Orientation", false) // W_ToolOptions_Vertical , m_size("Size:") // W_ToolOptions_Size , m_undo(0) { - bind(TTool::VectorImage | TTool::ToonzImage | TTool::EmptyTarget); + bind(TTool::VectorImage | TTool::ToonzImage | TTool::RasterImage | + TTool::EmptyTarget); m_prop[0].bind(m_fontFamilyMenu); // Su mac non e' visibile il menu dello style perche' e' stato inserito nel // nome @@ -615,6 +668,7 @@ void TypeTool::setSize(std::wstring strSize) { TImageP img = getImage(true); TToonzImageP ti = img; TVectorImageP vi = img; + TRasterImageP ri = img; // for vector levels, adjust size according to the ratio between // the viewer dpi and the vector level's dpi if (vi) dimension *= Stage::inch / Stage::standardDpi; @@ -639,7 +693,7 @@ void TypeTool::setSize(std::wstring strSize) { if (TVectorImageP vi = m_string[i].m_char) vi->transform(TScale(ratio)); m_string[i].m_offset *= ratio; } - if (ti) + if (ti || ri) updateStrokeChar(); else updateCharPositions(); @@ -930,6 +984,17 @@ glPushMatrix(); TPointD adjustedDim = m_scale * TPointD(dim.lx, dim.ly); charWidth = adjustedDim.x; + } else if (TRasterImageP ri = m_string[j].m_char) { + TRectD dim = ri->getBBox(); + ri->setPalette(vPalette); + + TPoint rasterCenter(dim.getLx() / 2, dim.getLy() / 2); + TTranslation transl1(convert(rasterCenter)); + TTranslation transl2(m_string[j].m_charPosition); + GLRasterPainter::drawRaster(transl2 * m_scale * transl1, ri, false); + + TPointD adjustedDim = m_scale * TPointD(dim.getLx(), dim.getLy()); + charWidth = adjustedDim.x; } // sottolineo i caratteri della preedit string @@ -1072,6 +1137,64 @@ vi->transform( TRotation(m_startPoint,-90) ); //--------------------------------------------------------- +void TypeTool::addTextToRasterImage(const TRasterImageP ¤tImage) { + UINT size = m_string.size(); + if (size == 0) return; + + TRasterP targetRaster = currentImage->getRaster(); + TRect changedArea; + + UINT j; + for (j = 0; j < size; j++) { + if (m_string[j].isReturn()) continue; + + if (TRasterImageP ri = m_string[j].m_char) { + TRectD srcBBox = ri->getBBox() + m_string[j].m_charPosition; + TDimensionD dim = srcBBox.getSize(); + TDimensionD enlargeAmount(dim.lx * (m_scale.a11 - 1.0), + dim.ly * (m_scale.a22 - 1.0)); + changedArea += TRasterImageUtils::convertWorldToRaster( + srcBBox.enlarge(enlargeAmount), currentImage); + } + } + + if (!changedArea.isEmpty()) { + TTileSetFullColor *beforeTiles = + new TTileSetFullColor(targetRaster->getSize()); + beforeTiles->add(targetRaster, changedArea); + + for (j = 0; j < size; j++) { + if (m_string[j].isReturn()) continue; + + if (TRasterImageP srcRi = m_string[j].m_char) { + TRaster32P srcRaster = srcRi->getRaster(); + TTranslation transl2(m_string[j].m_charPosition + + convert(targetRaster->getCenter())); + TRop::over(targetRaster, srcRaster, transl2 * m_scale); + } + } + + TTileSetFullColor *afterTiles = + new TTileSetFullColor(targetRaster->getSize()); + afterTiles->add(targetRaster, changedArea); + + TXshSimpleLevel *sl = + TTool::getApplication()->getCurrentLevel()->getSimpleLevel(); + TFrameId id = getCurrentFid(); + + TUndoManager::manager()->add(new FullColorRasterUndoTypeTool( + beforeTiles, afterTiles, sl, id, m_isFrameCreated, m_isLevelCreated)); + if (m_undo) { + delete m_undo; + m_undo = 0; + } + + ToolUtils::updateSaveBox(); + } +} + +//--------------------------------------------------------- + void TypeTool::addTextToImage() { if (!m_validFonts) return; TFontManager *instance = TFontManager::instance(); @@ -1082,8 +1205,9 @@ void TypeTool::addTextToImage() { TImageP img = getImage(true); TVectorImageP vi = img; TToonzImageP ti = img; + TRasterImageP ri = img; - if (!vi && !ti) return; + if (!vi && !ti && !ri) return; if (vi) { QMutexLocker lock(vi->getMutex()); @@ -1105,6 +1229,8 @@ void TypeTool::addTextToImage() { addTextToVectorImage(vi, images); } else if (ti) addTextToToonzImage(ti); + else if (ri) + addTextToRasterImage(ri); notifyImageChanged(); // getApplication()->notifyImageChanges(); @@ -1224,8 +1350,9 @@ void TypeTool::leftButtonDown(const TPointD &pos, const TMouseEvent &) { TImageP img = getImage(true); TVectorImageP vi = img; TToonzImageP ti = img; + TRasterImageP ri = img; - if (!vi && !ti) return; + if (!vi && !ti && !ri) return; setSize(m_size.getValue()); @@ -1234,10 +1361,14 @@ void TypeTool::leftButtonDown(const TPointD &pos, const TMouseEvent &) { m_undo = new UndoTypeTool( 0, 0, getApplication()->getCurrentLevel()->getSimpleLevel(), getCurrentFid(), m_isFrameCreated, m_isLevelCreated); - else + else if (ti) m_undo = new RasterUndoTypeTool( 0, 0, getApplication()->getCurrentLevel()->getSimpleLevel(), getCurrentFid(), m_isFrameCreated, m_isLevelCreated); + else + m_undo = new FullColorRasterUndoTypeTool( + 0, 0, getApplication()->getCurrentLevel()->getSimpleLevel(), + getCurrentFid(), m_isFrameCreated, m_isLevelCreated); } // closeImeWindow(); @@ -1301,6 +1432,7 @@ void TypeTool::replaceText(std::wstring text, int from, int to) { TImageP img = getImage(true); TToonzImageP ti = img; TVectorImageP vi = img; + TRasterImageP ri = img; TPoint adv; TPointD d_adv; @@ -1351,6 +1483,33 @@ void TypeTool::replaceText(std::wstring text, int from, int to) { assert(vPalette); newTImage->setPalette(vPalette); + m_string.insert(m_string.begin() + index, + StrokeChar(newTImage, d_adv.x, character, styleId)); + } else if (ri) { + TRaster32P newRaster; + TPoint p; + unsigned int index = from + i; + + TPalette *vPalette = img->getPalette(); + assert(vPalette); + TColorStyle *colorStyle = vPalette->getStyle(styleId); + TPixel32 color = colorStyle->getMainColor(); + + if (instance->hasKerning() && (UINT)m_cursorIndex < m_string.size() && + !m_string[index].isReturn()) + adv = instance->drawChar((TRaster32P &)newRaster, p, color, + (wchar_t)character, + (wchar_t)m_string[index].m_key); + else + adv = instance->drawChar((TRaster32P &)newRaster, p, color, + (wchar_t)character, (wchar_t)0); + + d_adv = m_scale * TPointD((double)(adv.x), (double)(adv.y)); + + TRasterImageP newTImage(newRaster); + + newTImage->setPalette(vPalette); + m_string.insert(m_string.begin() + index, StrokeChar(newTImage, d_adv.x, character, styleId)); } @@ -1392,6 +1551,7 @@ void TypeTool::addBaseChar(std::wstring text) { TImageP img = getImage(true); TToonzImageP ti = img; TVectorImageP vi = img; + TRasterImageP ri = img; int styleId = TTool::getApplication()->getCurrentLevelStyleIndex(); TPoint adv; @@ -1453,6 +1613,35 @@ void TypeTool::addBaseChar(std::wstring text) { else m_string.insert(m_string.begin() + m_cursorIndex, StrokeChar(newTImage, d_adv.x, character, styleId)); + } else if (ri) { + TRaster32P newRasterCM; + TPoint p; + + TPalette *vPalette = img->getPalette(); + assert(vPalette); + TColorStyle *colorStyle = vPalette->getStyle(styleId); + TPixel32 color = colorStyle->getMainColor(); + + if (instance->hasKerning() && (UINT)m_cursorIndex < m_string.size() && + !m_string[m_cursorIndex].isReturn()) + adv = instance->drawChar((TRaster32P &)newRasterCM, p, color, + (wchar_t)character, + (wchar_t)m_string[m_cursorIndex].m_key); + else + adv = instance->drawChar((TRaster32P &)newRasterCM, p, color, + (wchar_t)character, (wchar_t)0); + + d_adv = m_scale * TPointD((double)(adv.x), (double)(adv.y)); + + TRasterImageP newRImage(newRasterCM); + + newRImage->setPalette(vPalette); + + if ((UINT)m_cursorIndex == m_string.size()) + m_string.push_back(StrokeChar(newRImage, d_adv.x, character, styleId)); + else + m_string.insert(m_string.begin() + m_cursorIndex, + StrokeChar(newRImage, d_adv.x, character, styleId)); } if (instance->hasKerning() && m_cursorIndex > 0 &&